我很难理解 tensorflow,而且我找不到不依赖于 MNIST 数据集的好的基本示例。我试图为一些公共(public)数据集创建一个分类 nn,它们提供了许多(未知的)特征,并为每个样本提供了一个标签。他们提供了大约 90 种音频分析功能,并以出版年份作为标签。 ( https://archive.ics.uci.edu/ml/datasets/yearpredictionmsd )
不用说,我没有设法训练网络,而且我对理解所提供的功能也无能为力。
我现在正在尝试生成人工数据,并尝试围绕它训练网络。数据是一对数字(位置),如果该位置在任意点(5,5)周围半径为 r 的圆内,则标签为 1。
numrows=10000
circlex=5
circley=5
circler=3
data = np.random.rand(numrows,2)*10
labels = [ math.sqrt( math.pow(x-circlex, 2) + math.pow(y-circley, 2) ) for x,y in data ]
labels = list( map(lambda x: x<circler, labels) )
如果尝试了网络形状、参数、优化器、学习率等的多种组合(我承认这方面的数学不强),但要么没有收敛,要么很糟糕(上次测试的准确率为 70%)。
当前版本(标签转换为 one_hot 编码 [1,0] 和 [0,1](外部,内部)。
# model creation
graph=tf.Graph()
with graph.as_default():
X = tf.placeholder(tf.float32, [None, 2] )
layer1 = tf.layers.dense(X, 2)
layer2 = tf.layers.dense(layer1, 2)
Y = tf.nn.softmax(layer2)
y_true = tf.placeholder(tf.float32, [None, 2] )
loss=tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits_v2(logits=Y, labels=y_true) )
optimizer = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
def accuracy(predictions, labels):
return (100.0 * np.sum(np.argmax(predictions, 1) == np.argmax(labels, 1))
/ predictions.shape[0])
# training
with tf.Session(graph=graph) as session:
tf.global_variables_initializer().run()
for step in range(1000):
_, l, predictions = session.run([optimizer,loss,Y], feed_dict={X:data, y_true:labels})
if step % 100 == 0:
print("Loss at step %d: %f" % (step, l)
print("Accuracy %f" % accuracy(predictions, labels))
此示例中的准确性约为 70%(损失约为 0.6)。
问题是……我做错了什么?
更新
我将按照最初提出的问题离开。我学到的主要经验教训:
标准化您的输入数据。平均值应该在 0 左右,范围在 -1 和 1 之间。
蓝色:归一化数据,红色:上面创建的原始输入数据
批量输入数据。如果使用的子集足够随机,它会减少所需的迭代次数,而不会对准确性造成太大影响。
不要忘记层与层之间的激活函数 :)
最佳答案
输入:
用两个类绘制合成数据。
上述代码的输出:
所有输出都被归类为单一类别,由于类别不平衡,准确率高达 70%。
代码问题
- 尽管定义了两层,但两者之间没有定义激活函数。所以
tf.softmax( ((x*w1)+b1) * w2 + b2)
压缩到一个层。只有一个超平面试图分离这个输入,而超平面位于输入空间之外,这就是为什么你将所有输入分类为一个类。 - 错误:
Softmax
应用了两次:在logits
上以及在entropy_loss
期间。 - 整个输入作为单个批处理给出,而不是
小批量
。 - 输入需要标准化。
修复上述问题,输出变为:
上面的输出是有道理的,因为模型有两个隐藏层,所以我们有两个超平面试图分离数据。最后一层然后以最小化误差的方式组合这两个超平面。
将隐藏层从 2 层增加到 3 层:
有了 3 个隐藏层,我们得到了 3 个超平面,我们可以看到最后一层调整这些超平面以很好地分离数据。
代码:
# Normalize data
data = (data - np.mean(data)) /np.sqrt(np.var(data))
n_hidden = 3
batch_size = 128
# Feed batch data
def get_batch(inputX, inputY, batch_size):
duration = len(inputX)
for i in range(0,duration//batch_size):
idx = i*batch_size
yield inputX[idx:idx+batch_size], inputY[idx:idx+batch_size]
# Create the graph
tf.reset_default_graph()
graph=tf.Graph()
with graph.as_default():
X = tf.placeholder(tf.float32, [None, 2] )
layer1 = tf.layers.dense(X, n_hidden, activation=tf.nn.sigmoid)
layer2 = tf.layers.dense(layer1, 2)
Y = tf.nn.softmax(layer2)
y_true = tf.placeholder(tf.int32, [None] )
loss = tf.losses.sparse_softmax_cross_entropy(logits=layer2, labels=y_true)
optimizer = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(Y, 1),tf.argmax(tf.one_hot(y_true,2), 1)), tf.float32))
# training
with tf.Session(graph=graph) as session:
session.run(tf.global_variables_initializer())
for epoch in range(10):
acc_avg = 0.
loss_avg = 0.
for step in range(10000//batch_size):
for inputX, inputY in get_batch(data, labels, batch_size):
_, l, acc = session.run([optimizer,loss,accuracy], feed_dict={X:inputX, y_true:inputY})
acc_avg += acc
loss_avg += l
print("Loss at step %d: %f" % (step, loss_avg*batch_size/10000))
print("Accuracy %f" % (acc_avg*batch_size/10000))
#Get prediction
pred = session.run(Y, feed_dict={X:data})
# Plotting function
import matplotlib.pylab as plt
plt.scatter(data[:,0], data[:,1], s=20, c=np.argmax(pred,1), cmap='jet', vmin=0, vmax=1)
plt.show()
关于python - 基本 tensorflow 分类示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50485506/