我使用了一些神经网络,但并不多。因此,为了提高我的舒适度,我决定用一个来解决我最喜欢的数学问题之一:快速矩阵乘法。 标准算法采用O(n ^ 3)乘以两个nxn矩阵。 Strassen算法在O(n ^ 2.8)中完成。 Coppersmith和Winograd基于工作的算法下降到O(n ^ 2.373)但由于常数因子很大而不切实际。 后两者之间有很多摆动空间。特别是,如果你可以使用48次或更少的乘法运算乘以两个4x4矩阵,那么你做得比Strassen好。
所以这里是我的设置:我有两个(伪随机生成的)nxn矩阵,A和B.一个神经网络采用BULT的A和NMULT线性组合的NMULT线性组合,将它们逐点相乘,然后取n ^ 2输出的线性组合,试图重建产品AB。损失是条目上的平方和误差。 对抗网络采用两个随机矩阵A'和B',并输出softsign(A'+ A_offset)和softsign(B'+ B_offset),其中丢失函数= -1 *另一个网络的平方和误差。 / p>
我在3个训练步骤之间交替:在随机输入矩阵A和B上训练快速矩阵乘法网络,在随机输入矩阵A'和B'上训练对抗网络,并在输出上训练fmm网络对抗性网络。
它不起作用。我不仅不能比Strassen做得更好,我甚至无法重现基本的矩阵乘法!也就是说,如果我取n = 2且NMULT = 8,我不会得到0错误。
我知道除了使用神经网络之外还有其他(可能更好)的方法来解决这个问题 - 我只是将其作为一种学习方法。谁能给我建议如何解决这个问题?
见下面的代码:
import numpy as np
import tensorflow as tf
epochs=1000
tot_batch = 1000
learning_rate = 0.01
MATRIX_SIZE = 2
NMULTS = 8
nvals = MATRIX_SIZE * MATRIX_SIZE
# These are the inputs to the adversarial NN generating our input matrices A&B.
a_inputs = tf.placeholder(tf.float32, [None, nvals])
b_inputs = tf.placeholder(tf.float32, [None, nvals])
adv_a_icpt = tf.Variable(tf.random_normal([nvals]))
adv_b_icpt = tf.Variable(tf.random_normal([nvals]))
a_vector = tf.nn.softsign(a_inputs + adv_a_icpt)
b_vector = tf.nn.softsign(b_inputs + adv_b_icpt)
# These are the two adversarial matrices we are multiplying; all entries
# are in [-1, 1]. This makes normalizing the error easier.
a_matrix = tf.reshape(a_vector, [-1, MATRIX_SIZE, MATRIX_SIZE])
b_matrix = tf.reshape(b_vector, [-1, MATRIX_SIZE, MATRIX_SIZE])
# This is the product A * B.
m_matrix = tf.matmul(a_matrix, b_matrix)
# This is what the fast-matrix-multiply NN will be predicting.
m_vector = tf.reshape(m_matrix, [-1, nvals])
fmm_a_wts = tf.Variable(tf.random_normal([nvals, NMULTS]))
fmm_b_wts = tf.Variable(tf.random_normal([nvals, NMULTS]))
fmm_output_wts = tf.Variable(tf.random_normal([NMULTS, nvals]))
# This is the output of the fast-matrix-multiply NN.
def fmm_output(input_a_vec, input_b_vec):
hidden_a_inputs = tf.matmul(input_a_vec, fmm_a_wts)
hidden_b_inputs = tf.matmul(input_b_vec, fmm_b_wts)
hidden_output = tf.multiply(hidden_a_inputs, hidden_b_inputs)
return tf.matmul(hidden_output, fmm_output_wts)
# Treat each element of the input arrays as having a variance of O(1). Then
# the output array elements have a variance of O(MATRIX_SIZE).
loss_adv = tf.divide(
tf.losses.mean_squared_error(m_vector, fmm_output(a_vector, b_vector)),
MATRIX_SIZE)
abs_err_vec_adv = tf.abs(tf.subtract(m_vector, fmm_output(a_vector, b_vector)))
mean_abs_err_adv = tf.reduce_mean(abs_err_vec_adv, reduction_indices=[1])
m_rand = tf.matmul(tf.reshape(a_inputs, [-1, MATRIX_SIZE, MATRIX_SIZE]),
tf.reshape(b_inputs, [-1, MATRIX_SIZE, MATRIX_SIZE]))
loss_rand = tf.divide(
tf.losses.mean_squared_error(tf.reshape(m_rand, [-1, nvals]),
fmm_output(a_inputs, b_inputs)),
MATRIX_SIZE)
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
train_ADV = optimizer.minimize(-loss_adv,
var_list=[adv_a_wts, adv_b_wts,
adv_a_icpt, adv_b_icpt])
train_FMMA = optimizer.minimize(loss_adv,
var_list=[fmm_a_wts, fmm_b_wts,
fmm_output_wts])
train_FMMR = optimizer.minimize(loss_rand,
var_list=[fmm_a_wts, fmm_b_wts,
fmm_output_wts])
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
adv_batch_size = 100
fmm_batch_size = 100
for epoch in range(epochs):
adv_loss = 0.0
rand_loss = 0.0
for i in range(tot_batch):
# Run the fast-matrix-multiply NN training against random inputs.
batch_a_inputs = np.random.uniform(low=-1., size=[fmm_batch_size, nvals])
batch_b_inputs = np.random.uniform(low=-1., size=[fmm_batch_size, nvals])
_, rerr = sess.run([train_FMMR, loss_rand],
feed_dict={ a_inputs : batch_a_inputs,
b_inputs : batch_b_inputs })
# Run the adversarial NN training.
batch_a_inputs = np.random.normal(size=[adv_batch_size, nvals])
batch_b_inputs = np.random.normal(size=[adv_batch_size, nvals])
sess.run(train_ADV, feed_dict={ a_inputs : batch_a_inputs,
b_inputs : batch_b_inputs })
# Run the fast-matrix-multiply NN training against adversarial inputs.
batch_a_inputs = np.random.normal(size=[fmm_batch_size, nvals])
batch_b_inputs = np.random.normal(size=[fmm_batch_size, nvals])
_, aerr, mae = sess.run([train_FMMA, loss_adv, mean_abs_err_adv],
feed_dict={ a_inputs : batch_a_inputs,
b_inputs : batch_b_inputs })
adv_loss += aerr / tot_batch
rand_loss += 3.0 * rerr / tot_batch
if i % 200 == 0:
print("Batch " + str(i) + ", mean abs error: " + str(mae[0:4]))
print("Epoch: " + str(epoch) + ", rand loss = " + str(rand_loss) +
", adv loss = " + str(adv_loss))
答案 0 :(得分:1)
要找到(或重新发现)矩阵乘法算法相当于解决Brent Equations的系统。
对于具有n*n
基本乘法的k
矩阵乘积,系统具有n^6
个等式,其中k
个3因子乘积之和。因此,该系统是高度非线性的并且具有3k n^2
个未知数。在practice中,很难找到超出2*2
案例的解决方案。对于2*2
,有64
个等式,每个等式有七个产品。对于3*3
,有729
个等式,每个等式都有23
个产品。
研究人员已经尝试为decades.发现小因子矩阵的矩阵乘法算法。如果神经网络能够战胜整个科学界,那么这将是可能的,但实际上更令人惊讶。
尽管我怀疑,related research成功地使用神经网络重新发现了2x2和3x3的算法。