TensorFlow - 为什么这个softmax回归没有学习到任何东西?

7 投票
4 回答
3305 浏览
提问于 2025-05-10 23:13

我想用TensorFlow做一些大事情,但我想从小做起。

我有一些小的灰色方块(上面有一点噪音),我想根据它们的颜色来分类(比如分成三类:黑色、灰色和白色)。我写了一个小的Python类来生成这些方块和对应的1-hot向量,并修改了他们的基本MNIST示例来输入这些数据。

但是它什么都学不到——比如对于这三类,它总是大约有33%的准确率。

import tensorflow as tf
import generate_data.generate_greyscale

data_generator = generate_data.generate_greyscale.GenerateGreyScale(28, 28, 3, 0.05)
ds = data_generator.generate_data(10000)
ds_validation = data_generator.generate_data(500)
xs = ds[0]
ys = ds[1]
num_categories = data_generator.num_categories

x = tf.placeholder("float", [None, 28*28])
W = tf.Variable(tf.zeros([28*28, num_categories]))
b = tf.Variable(tf.zeros([num_categories]))
y = tf.nn.softmax(tf.matmul(x,W) + b)
y_ = tf.placeholder("float", [None,num_categories])
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)

# let batch_size = 100 --> therefore there are 100 batches of training data
xs = xs.reshape(100, 100, 28*28) # reshape into 100 minibatches of size 100
ys = ys.reshape((100, 100, num_categories)) # reshape into 100 minibatches of size 100

for i in range(100):
  batch_xs = xs[i]
  batch_ys = ys[i]
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

xs_validation = ds_validation[0]
ys_validation = ds_validation[1]
print sess.run(accuracy, feed_dict={x: xs_validation, y_: ys_validation})

我的数据生成器是这样的:

import numpy as np
import random

class GenerateGreyScale():
    def __init__(self, num_rows, num_cols, num_categories, noise):
        self.num_rows = num_rows
        self.num_cols = num_cols
        self.num_categories = num_categories
        # set a level of noisiness for the data
        self.noise = noise

    def generate_label(self):
        lab = np.zeros(self.num_categories)
        lab[random.randint(0, self.num_categories-1)] = 1
        return lab

    def generate_datum(self, lab):
        i = np.where(lab==1)[0][0]
        frac = float(1)/(self.num_categories-1) * i
        arr = np.random.uniform(max(0, frac-self.noise), min(1, frac+self.noise), self.num_rows*self.num_cols)
        return arr

    def generate_data(self, num):
        data_arr = np.zeros((num, self.num_rows*self.num_cols))
        label_arr = np.zeros((num, self.num_categories))
        for i in range(0, num):
            label = self.generate_label()
            datum = self.generate_datum(label)
            data_arr[i] = datum
            label_arr[i] = label
        #data_arr = data_arr.astype(np.float32)
        #label_arr = label_arr.astype(np.float32)
        return data_arr, label_arr

相关文章:

  • 暂无相关问题
暂无标签

4 个回答

0

我在遇到类似问题时发现了这个问题。我通过调整特征的规模解决了我的问题。

先说一下背景:我在跟着tensorflow的教程,但我想用Kaggle上的数据(这里有数据)来做模型。不过一开始我一直遇到同样的问题:模型根本学不会。经过几轮排查,我意识到Kaggle的数据和tensorflow的MNIST数据集的规模完全不同。因此,我对数据进行了缩放,使它们的范围都在0到1之间,这样就能一致了。

我觉得有必要在这里分享一下我的经验,以防有些初学者在跟着教程设置时像我一样卡住了 =)

2

你的问题在于,梯度的变化没有限制,导致损失函数变成了nan(不是一个数字)。

你可以看看这个问题:为什么在增加批量大小时,TensorFlow示例会失败?

另外,确保你运行模型的步骤足够多。你现在只是在训练数据集上运行了一次(100次 * 100个例子),这对模型的收敛来说是不够的。至少要增加到2000次(也就是在数据集上运行20次)。

补充说明(不能评论,所以我在这里加我的想法):我链接的帖子提到,你可以使用GradientDescentOptimizer,只要把学习率设置为0.001左右。问题在于,你的学习率对于你使用的损失函数来说太高了。

另外,你也可以换一个损失函数,这样就不会让梯度变化得那么剧烈。在定义crossEntropy时,使用tf.reduce_mean代替tf.reduce_sum

3

首先,试着用随机值来初始化你的W矩阵,而不是用零。因为如果所有输入的输出都是零,优化器就没有任何东西可以处理了。

不要这样:

W = tf.Variable(tf.zeros([28*28, num_categories]))

试试这样:

W = tf.Variable(tf.truncated_normal([28*28, num_categories],
                                    stddev=0.1))
2

虽然dga和syncd的建议很有帮助,但我尝试了非零权重初始化和更大的数据集,结果还是没成功。最后让我成功的办法是换了一个优化算法。

我把:

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

换成了:

train_step = tf.train.AdamOptimizer(0.0005).minimize(cross_entropy)

我还把训练的循环嵌套在另一个循环里,这样可以训练多个周期,结果收敛得很好,如下所示:

 ===# EPOCH 0 #===
Error: 0.370000004768
 ===# EPOCH 1 #===
Error: 0.333999991417
 ===# EPOCH 2 #===
Error: 0.282000005245
 ===# EPOCH 3 #===
Error: 0.222000002861
 ===# EPOCH 4 #===
Error: 0.152000010014
 ===# EPOCH 5 #===
Error: 0.111999988556
 ===# EPOCH 6 #===
Error: 0.0680000185966
 ===# EPOCH 7 #===
Error: 0.0239999890327
 ===# EPOCH 8 #===
Error: 0.00999999046326
 ===# EPOCH 9 #===
Error: 0.00400000810623

编辑 - 为什么这样有效:我想问题在于我没有手动选择一个合适的学习率计划,而Adam算法能够自动生成一个更好的学习率。

撰写回答