tensorflow - 快速矩阵乘法和神经网络

标签 tensorflow neural-network matrix-multiplication

我使用过一点神经网络,但不多。因此,为了提高我的舒适度,我决定用它来解决我最喜欢的数学问题之一:快速矩阵乘法。 标准算法需要 O(n^3) 来乘以两个 nxn 矩阵。 Strassen 算法的时间复杂度为 O(n^2.8)。基于 Coppersmith 和 Winograd 工作的算法可以降低到 O(n^2.373),但由于常数因子较大而不切实际。 后两者之间有很大的回旋余地。特别是,如果您可以使用 48 次或更少的乘法运算来将两个 4x4 矩阵相乘,那么您就比 Strassen 做得更好。

所以这是我的设置:我有两个(伪随机生成的)nxn 矩阵,A 和 B。一个神经网络采用 A 元素的 NMULT 线性组合和 B 的 NMULT 线性组合,将它们逐点相乘,然后取 n ^2 输出的线性组合,尝试重构乘积 AB。损失是条目的平方和误差。 对抗网络采用两个随机矩阵 A' 和 B',并输出 softsign(A' + A_offset) 和 softsign(B' + B_offset),损失函数 = -1 * 另一个网络的平方和误差。

我交替进行 3 个训练步骤:在随机输入矩阵 A 和 B 上训练快速矩阵乘法网络,在随机输入矩阵 A' 和 B' 上训练对抗网络,并在输出上训练 fmm 网络对抗网络。

这不起作用。我不仅不能比斯特拉森做得更好,我什至不能重现基本的矩阵乘法!也就是说,如果我取 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))

最佳答案

找到(或重新发现)矩阵乘法算法相当于求解 Brent Equations 的系统.

对于具有 k 次初等乘法的 n*n 矩阵乘积,系统具有 n^6 个方程,总和为 k 三因子乘积。因此,系统是高度非线性的,并且具有 3k n^2 未知数。在 practice ,很难找到 2*2 情况之外的解决方案。对于 2*2,有 64 个方程,每个方程有 7 个乘积。对于 3*3,有 729 个方程,每个方程有 23 个乘积。

研究人员试图发现 decades. 小因子矩阵的矩阵乘法算法如果神经网络能够击败整个科学界,这是可能的,但确实令人惊讶。

尽管我心存疑虑,related research成功地利用神经网络重新发现了 2x2 和 3x3 的算法。

关于tensorflow - 快速矩阵乘法和神经网络,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46984581/

相关文章:

c++ - 用于矩阵乘法的 OpenMP

python - 导入错误:无法导入名称 normalize_data_format

c++ - 使用 tensorflow 的 C++ API 构建错误

machine-learning - 关于感知器的一些问题

haskell - 为什么使用 Repa 进行矩阵乘法比使用 hmatrix 更快?

java - 在java矩阵工具包(MTJ)中创建行 vector

machine-learning - 如何禁用 tensorflow 中特定层的动量?

tensorflow - 在 Tensorflow 中,如何生成标量摘要?

r - 如何使用神经网络包预测新病例

python - 以图像作为标签的 Caffe 测试网