我是深度学习世界和张量流动的新手。 Tensorflow现在对我来说太复杂了。
我正在关注TF Layers API的教程,我遇到了一个热门编码的问题。这是我的代码
import pandas as pd
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
wine_data = load_wine()
feat_data = wine_data['data']
labels = wine_data['target']
X_train, X_test, y_train, y_test = train_test_split(feat_data,
labels,
test_size=0.3,
random_state=101)
scaler = MinMaxScaler()
scaled_x_train = scaler.fit_transform(X_train)
scaled_x_test = scaler.transform(X_test)
# ONE HOT ENCODED
onehot_y_train = pd.get_dummies(y_train).as_matrix()
one_hot_y_test = pd.get_dummies(y_test).as_matrix()
num_feat = 13
num_hidden1 = 13
num_hidden2 = 13
num_outputs = 3
learning_rate = 0.01
import tensorflow as tf
from tensorflow.contrib.layers import fully_connected
X = tf.placeholder(tf.float32,shape=[None,num_feat])
y_true = tf.placeholder(tf.float32,shape=[None,3])
actf = tf.nn.relu
hidden1 = fully_connected(X,num_hidden1,activation_fn=actf)
hidden2 = fully_connected(hidden1,num_hidden2,activation_fn=actf)
output = fully_connected(hidden2,num_outputs)
loss = tf.losses.softmax_cross_entropy(onehot_labels=y_true, logits=output)
optimizer = tf.train.AdamOptimizer(learning_rate)
train = optimizer.minimize(loss)
init = tf.global_variables_initializer()
training_steps = 1000
with tf.Session() as sess:
sess.run(init)
for i in range(training_steps):
sess.run(train,feed_dict={X:scaled_x_train,y_true:y_train})
# Get Predictions
logits = output.eval(feed_dict={X:scaled_x_test})
preds = tf.argmax(logits,axis=1)
results = preds.eval()
当我运行此代码时出现此错误
ValueError:无法为Tensor提供形状值(124,) 'PLACEHOLDER_1:0', 形状'(?,3)'
经过一番挖掘,我发现将sess.run
修改为
sess.run(train,feed_dict{X:scaled_x_train,y_true:onehot_y_train})
并将y_train
更改为onehot_y_train
使代码运行
我只是想知道幕后发生了什么,为什么在这段代码中需要one_hot编码?
答案 0 :(得分:1)
您的网络正在对3个班级(A,B和C班级)进行班级预测。
在定义神经网络以将您的13个输入转换为可用于区分这3个类的表示时,您可以做出一些选择。
您可以输出1个数字。让我们定义一个单值输出< 1表示A类,[0,1]之间的输出是B类,输出> 1是C类。
你可以定义这个,使用像平方误差这样的损失函数,网络会学会在这些假设下工作,并且可能在它的一半方面做得很好。
然而,这是定义3个类的一个相当随意的值选择,我相信你可以看到。它肯定是次优的。学习这种表示比它需要的更难。我们可以做得更好吗?
让我们选择一种更合理的方法。我们有3个输出,而不是1个输出。我们定义每个输出以表示我们对特定类的相信程度。为了符合您使用的交叉熵损失,我们将通过对它们应用sigmoid进一步将这些值约束在[0,1]范围内。太棒了,我们现在在范围[0,1]中有3个值,每个值都表示输入应该属于我们的3个类中的每一个。
您的每个输入都有标签,您确定这些输入是A,B或C类。因此对于给定C类的输入,您的标签自然会是[0,0,1 ](例如,你知道它不是A或B,在这两种情况下都是0,而你知道这个类的C是1)。瞧,你有一个热门的编码!
正如您可能想象的那样,这比我提出的第一个问题要容易得多。因此,我们选择以这种方式表示我们的问题,因为我们最终得到的网络在我们这样做时表现更好。这并不是说你不能用另一种方式来代表它,你只是希望得到最好的结果,而且热门编码通常会超出你可能想到的其他表现形式。