为什么这种TensorFlow实施远没有Matlab的NN成功呢?
matlab
neural-network
python
tensorflow
6
0

作为一个玩具示例,我尝试从100个无噪声数据点拟合函数f(x) = 1/x 。 Matlab默认实现非常成功,均方差约为10 ^ -10,并且插值完美。

我实现了一个神经网络,其中包含10个S形神经元的一个隐藏层。我是神经网络的初学者,所以请当心防止愚蠢的代码。

import tensorflow as tf
import numpy as np

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

#Can't make tensorflow consume ordinary lists unless they're parsed to ndarray
def toNd(lst):
    lgt = len(lst)
    x = np.zeros((1, lgt), dtype='float32')
    for i in range(0, lgt):
        x[0,i] = lst[i]
    return x

xBasic = np.linspace(0.2, 0.8, 101)
xTrain = toNd(xBasic)
yTrain = toNd(map(lambda x: 1/x, xBasic))

x = tf.placeholder("float", [1,None])
hiddenDim = 10

b = bias_variable([hiddenDim,1])
W = weight_variable([hiddenDim, 1])

b2 = bias_variable([1])
W2 = weight_variable([1, hiddenDim])

hidden = tf.nn.sigmoid(tf.matmul(W, x) + b)
y = tf.matmul(W2, hidden) + b2

# Minimize the squared errors.
loss = tf.reduce_mean(tf.square(y - yTrain))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

# For initializing the variables.
init = tf.initialize_all_variables()

# Launch the graph
sess = tf.Session()
sess.run(init)

for step in xrange(0, 4001):
    train.run({x: xTrain}, sess)
    if step % 500 == 0:
        print loss.eval({x: xTrain}, sess)

均方差以〜2 * 10 ^ -3结尾,因此比matlab差约7个数量级。可视化

xTest = np.linspace(0.2, 0.8, 1001)
yTest = y.eval({x:toNd(xTest)}, sess)  
import matplotlib.pyplot as plt
plt.plot(xTest,yTest.transpose().tolist())
plt.plot(xTest,map(lambda x: 1/x, xTest))
plt.show()

我们可以看到拟合度在系统上是不完善的: 在此处输入图片说明而matlab肉眼看起来完美无缺,差异均小于10 ^ -5: 在此处输入图片说明我试图用TensorFlow复制Matlab网络图:

在此处输入图片说明

顺便说一句,该图似乎暗示了tanh而不是S形激活函数。我不能确定它在文档中的任何地方。但是,当我尝试在TensorFlow中使用tanh神经元时,拟合很快会失败,并使用nan作为变量。我不知道为什么。

Matlab使用Levenberg–Marquardt训练算法。贝叶斯正则化在均方为10 ^ -12时更加成功(我们可能在浮点运算的蒸气领域)。

为什么TensorFlow的实现如此糟糕,我该怎么做才能使其变得更好?

参考资料:
Stack Overflow
收藏
评论
共 2 个回答
高赞 时间 活跃

顺便说一句,这是上面的略作清理的版本,它清理了一些形状问题以及tf和np之间不必要的弹跳。 40k步后达到3e-08,4000后达到1.5e-5:

import tensorflow as tf
import numpy as np

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

xTrain = np.linspace(0.2, 0.8, 101).reshape([1, -1])
yTrain = (1/xTrain)

x = tf.placeholder(tf.float32, [1,None])
hiddenDim = 10

b = bias_variable([hiddenDim,1])
W = weight_variable([hiddenDim, 1])

b2 = bias_variable([1])
W2 = weight_variable([1, hiddenDim])

hidden = tf.nn.sigmoid(tf.matmul(W, x) + b)
y = tf.matmul(W2, hidden) + b2

# Minimize the squared errors.                                                                
loss = tf.reduce_mean(tf.square(y - yTrain))
step = tf.Variable(0, trainable=False)
rate = tf.train.exponential_decay(0.15, step, 1, 0.9999)
optimizer = tf.train.AdamOptimizer(rate)
train = optimizer.minimize(loss, global_step=step)
init = tf.initialize_all_variables()

# Launch the graph                                                                            
sess = tf.Session()
sess.run(init)

for step in xrange(0, 40001):
    train.run({x: xTrain}, sess)
    if step % 500 == 0:
        print loss.eval({x: xTrain}, sess)

综上所述,LMA在拟合2D曲线方面比更通用的DNN风格优化器做得更好,这并不奇怪。亚当(Adam)和其他人针对的是非常高的尺寸问题,而对于大型网络LMA开始变得缓慢 (请参阅12-15)。

收藏
评论

我尝试训练50000次迭代,结果出错为0.00012。在Tesla K40上大约需要180秒。

在此处输入图片说明

似乎对于这种问题,一阶梯度下降法不是一个很好的选择(双关语意),您需要Levenberg-Marquardt或l-BFGS。我认为还没有人在TensorFlow中实现它们。

编辑对此问题使用tf.train.AdamOptimizer(0.1) 。经过4000次迭代,它达到了3.13729e-05 。同样,具有默认策略的GPU似乎对于此问题也不是一个好主意。有许多小操作,开销导致我的计算机上GPU版本的运行速度比CPU慢3倍。

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号