基本张量流分类示例

时间:2018-05-23 10:07:45

标签: python tensorflow

我很难理解张量流,我找不到不依赖于MNIST数据集的好基本例子。我试图为某些公共数据集创建一个分类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之间。

Normalized vs not normalized

蓝色:标准化数据,红色:上面创建的原始输入数据

批量输入数据。如果使用的子集足够随机,它会减少所需的迭代次数而不会过多地损害精度。

不要忘记图层之间的激活功能:)

1 个答案:

答案 0 :(得分:2)

输入:

用两个类绘制合成数据。

enter image description here

上述代码的输出:

所有输出都被归类为单一类别,并且由于类别不平衡,准确率高达70%。

enter image description here

<小时/>

代码问题

  1. 即使定义了两个图层,也没有在两者之间定义激活函数。因此,tf.softmax( ((x*w1)+b1) * w2 + b2)会压缩到单个图层。只有一个超平面尝试分离此输入,超平面位于输入空间之外,这就是为什么您将所有输入分类为单个类。
  2. 错误:Softmax已应用两次:logits以及entropy_loss期间。
  3. 整个输入是作为单个批次而不是mini-batches给出的。
  4. 输入需要规范化。
  5. 解决上述问题,输出变为:

    enter image description here

    上述输出是有意义的,因为模型有两个隐藏层,所以我们有两个超平面试图分离数据。最后一层然后以这种方式组合这两个超平面以最小化误差。

    将隐藏层从2增加到3:

    enter image description here

    有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()