Python 训练Tensorflow MLP对输入进行分类时遇到问题-1、0或1

Python 训练Tensorflow MLP对输入进行分类时遇到问题-1、0或1,python,python-3.x,tensorflow,machine-learning,neural-network,Python,Python 3.x,Tensorflow,Machine Learning,Neural Network,我试图创建一个多层感知器,根据一些指标对情绪进行分类。情绪可以是-1(坏)、0(中性)或1(好)。我能找到的所有分类器示例都是一个热门的示例,因此我认为我将其应用于连续特性的方式有问题 # Data Prep np.random.shuffle(raw_data) X_vals = raw_data[:-200,0:4] Y_vals = [(x,) for x in raw_data[:-200,4]] X_test = raw_data[-200:,0:4] Y_test = [(x,) f

我试图创建一个多层感知器,根据一些指标对情绪进行分类。情绪可以是-1(坏)、0(中性)或1(好)。我能找到的所有分类器示例都是一个热门的示例,因此我认为我将其应用于连续特性的方式有问题

# Data Prep
np.random.shuffle(raw_data)
X_vals = raw_data[:-200,0:4]
Y_vals = [(x,) for x in raw_data[:-200,4]]
X_test = raw_data[-200:,0:4]
Y_test = [(x,) for x in raw_data[-200:,4]]

# Parameters
learning_rate = 0.001
training_epochs = 10
batch_size = 200
display_step = 1

# Network Parameters
n_hidden_1 = 16 # 1st layer number of neurons
n_hidden_2 = 16 # 2nd layer number of neurons
n_input = 4
n_classes = 1

# tf Graph input
X = tf.placeholder("float", [None, n_input])
Y = tf.placeholder("float", [None, n_classes])

# Store layers weight & bias
weights = {
    'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
    'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
    'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes]))
}
biases = {
    'b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'b2': tf.Variable(tf.random_normal([n_hidden_2])),
    'out': tf.Variable(tf.random_normal([n_classes]))
}


# Create model
def multilayer_perceptron(x):
    # Hidden fully connected layer with 256 neurons
    layer_1 = tf.nn.tanh(tf.add(tf.matmul(x, weights['h1']), biases['b1']))
    # Hidden fully connected layer with 256 neurons
    layer_2 = tf.nn.tanh(tf.add(tf.matmul(layer_1, weights['h2']), biases['b2']))
    # Output fully connected layer with a neuron for each class
    out_layer = tf.matmul(layer_2, weights['out']) + biases['out']
    return out_layer

# Construct model
logits = multilayer_perceptron(X)

# Define loss and optimizer
loss_op = tf.losses.mean_squared_error(labels=Y,
                                        predictions=tf.nn.softmax(logits))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
train_op = optimizer.minimize(loss_op)

# Initializing the variables
init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)

    # Training cycle
    for epoch in range(training_epochs):
        avg_cost = 0.
        total_batch = int(raw_data.shape[0]/batch_size)
        # Loop over all batches
        for i in range(total_batch):
            batch_x = X_vals[epoch*batch_size:(epoch+1)*batch_size]
            batch_y = Y_vals[epoch*batch_size:(epoch+1)*batch_size]
            # Run optimization op (backprop) and cost op (to get loss value)
            _, c = sess.run([train_op, loss_op], feed_dict={X: batch_x,
                                                            Y: batch_y})
            print("Optimization Finished!")

# Test model
pred = tf.nn.softmax(logits)  # Apply softmax to logits
correct_prediction = tf.equal(tf.round(pred), Y)
# Calculate accuracy
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print("Accuracy:", accuracy.eval({X: X_test, Y: Y_test}))
因此,我希望所有这些都应该做的是创建一个tanh感知器,它有两个隐藏层,每个层有16个神经元和一个softmax输出层,在除了200个数据点之外的所有数据点上训练它,然后在最后200个数据点上测试它。它应该给出介于-1和1之间的值,然后我对这些值进行四舍五入,以根据正确的标签-1、0或1进行评估


我想我一定是做错了什么,因为即使输入和输出之间有30%的皮尔逊相关性,结果也不比随机机会好。这本来应该很简单。

我注意到你的模型有两个问题。首先,softmax层将所有数据限制在[0,1]范围内,因此您永远不会得到想要的-1值。数据应该像你说的那样是一个热编码的,因为即使你的模型可以吐出一个-1,它仍然是非常有偏见的,在测试时不是非常准确。因此,我将
n_类
更改为3,并将索引0设置为坏,将索引1设置为中性,将索引2设置为好。标签应该是3向量,其中正确类索引处的向量为1,其他地方为0。这表示希望模型学习的每个类标签的概率分布

最后,使用均方误差(MSE)。对于欧几里德嵌入来说,这是一个很好的误差度量(例如,如果您想像YOLO那样了解边界框的位置),但对于您想要的概率分布嵌入来说,它不会很好地工作,因为它测量标签和网络输出之间的欧几里德距离。你想要的是
tf.loss.softmax\u cross\u entropy
。这首先通过softmax发送数据,然后计算交叉熵(两个概率分布之间的KL散度

所以你应该改变

loss\u op=tf.loss.mean\u squared\u error(标签=Y,预测=tf.nn.softmax(logits))

loss\u op=tf.loss.softmax\u cross\u熵(onehot\u labels=Y,logits=logits)

确保在测试期间仍使用softmax


最后,您将使用1对1的训练/测试分割。通常情况下,人们会使用3比1或3比2这样的数据,这样您的培训数据比测试数据多,这通常会导致更好的结果。

适用于此。请提供具有代表性的输入数据:只需在程序顶部对
原始数据的值进行硬编码即可。另外,请记住包括使程序按发布的方式运行所需的其他支持。您应该能够生成输入功能和输出之间具有约30%相关性的随机数据,并重新生成这些数据。我将看看如何提供允许共享的示例数据。为什么
n_classes=1
??另外,因为你有一个分类问题,你不应该使用均方误差,这是回归的…我只需要一个输出神经元;我希望那里的值在-1到1之间,因为我的三个类别是-1、0和1。我认为均方误差在这里是合适的,因为它的行为更像是一个拟合问题。生成“输入特征和输出之间具有约30%相关性的随机数据,并重现这一点”应该是你的工作,而不是潜在受访者的工作。。。!感谢您对softmax的更正!!我把它改成了棕色,但我担心它的表现不会更好。我不愿意切换到一个热点,因为我所做的感觉更像是预测一个连续的数量,而不是分类的东西。(另外,我正在使用10:1的训练/测试分割!)我强烈建议按照建议对标签进行热编码,并使用交叉熵损失。这里有一个类预测问题,不是回归问题。至少在你敲它之前试一下。尤其是因为你目前还没有任何运气。也许我应该把这看作是一个回归问题,而不是一个分类问题?长期目标是获得一个连续的情绪指标,介于-1和1之间。如果是这样的话,我该如何改变我的方法呢?啊,我明白了。如果你想这样,你可以对它进行一次热编码,然后取网络的logits输出的质心,得到[-1,1]中的一个值,这个值可能会更准确。在切换到一个热分类和三个分类后,我仍然与随机机会大致相当。有什么想法吗?