问题
This post is related to the following question. The code above is taken from the accepted answer.
The program itself works fine as is, but if I only changed the values of the data provided from
df = pd.DataFrame({'Temperature': [183, 10.7, 24.3, 10.7],
'Weight': [8, 11.2, 14, 11.2],
'Size': [3.97, 7.88, 11, 7.88],
'Property': [0,1,2,0]})
to
df = pd.DataFrame({'Temperature': [0,0,0,0],
'Weight': [1,2,3,4],
'Size': [1,2,3,4],
'Property': [1,1,1,1]})
I receive the following error while executing the code
ValueError: Cannot feed value of shape (1, 1) for Tensor 'Placeholder_1:0', which has shape '(?, 3)'
Nothing really changed structurally, so I am really confused by this error. The odd thing is that changing the values of the data may or may not trigger this issue. I've tried various TF versions including the latest and the same issue always occurs.
Does anybody know what am I missing? The full code example follows.
import tensorflow as tf
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler, OneHotEncoder
df = pd.DataFrame({'Temperature': [183, 10.7, 24.3, 10.7],
'Weight': [8, 11.2, 14, 11.2],
'Size': [3.97, 7.88, 11, 7.88],
'Property': [0,1,2,0]})
df.Property = df.Property.shift(-1)
print ( df.head() )
# parameters
time_steps = 1
inputs = 3
outputs = 3
df = df.iloc[:-1,:]
df = df.values
train_X = df[:, 1:]
train_y = df[:, 0]
scaler = MinMaxScaler(feature_range=(0, 1))
train_X = scaler.fit_transform(train_X)
train_X = train_X[:,None,:]
onehot_encoder = OneHotEncoder()
encode_categorical = train_y.reshape(len(train_y), 1)
train_y = onehot_encoder.fit_transform(encode_categorical).toarray()
learning_rate = 0.001
epochs = 500
batch_size = int(train_X.shape[0]/2)
length = train_X.shape[0]
display = 100
neurons = 100
tf.reset_default_graph()
X = tf.placeholder(tf.float32, [None, time_steps, inputs])
y = tf.placeholder(tf.float32, [None, outputs])
cell = tf.contrib.rnn.BasicLSTMCell(num_units=neurons, activation=tf.nn.relu)
cell_outputs, states = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32)
stacked_outputs = tf.reshape(cell_outputs, [-1, neurons])
out = tf.layers.dense(inputs=stacked_outputs, units=outputs)
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(
labels=y, logits=out))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
training_op = optimizer.minimize(loss)
accuracy = tf.metrics.accuracy(labels = tf.argmax(y, 1),
predictions = tf.argmax(out, 1),
name = "accuracy")
precision = tf.metrics.precision(labels=tf.argmax(y, 1),
predictions=tf.argmax(out, 1),
name="precision")
recall = tf.metrics.recall(labels=tf.argmax(y, 1),
predictions=tf.argmax(out, 1),
name="recall")
f1 = 2 * accuracy[1] * recall[1] / ( precision[1] + recall[1] )
with tf.Session() as sess:
tf.global_variables_initializer().run()
tf.local_variables_initializer().run()
for steps in range(epochs):
mini_batch = zip(range(0, length, batch_size),
range(batch_size, length+1, batch_size))
for (start, end) in mini_batch:
sess.run(training_op, feed_dict = {X: train_X[start:end,:,:],
y: train_y[start:end,:]})
if (steps+1) % display == 0:
loss_fn = loss.eval(feed_dict = {X: train_X, y: train_y})
print('Step: {} \tTraining loss: {}'.format((steps+1), loss_fn))
acc, prec, recall, f1 = sess.run([accuracy, precision, recall, f1],
feed_dict = {X: train_X, y: train_y})
print('\nEvaluation on training set')
print('Accuracy:', acc[1])
print('Precision:', prec[1])
print('Recall:', recall[1])
print('F1 score:', f1)
回答1:
As @Lescurel rightly pointed out, in a classification setting, the variable output
should reflect the number of classes in the target variable.
Whereas in a regression setting, it'll reflect the number of columns of the target variables (assuming we are predicting more than one variable).
So given the sample input data:
df = pd.DataFrame({'Temperature': [1,2,3,4,5],
'Weight': [2,4,6,8,10],
'Size': [9,24,9,9,9],
'Property': [0,0,0,0,1]})
The number of target classes is 2. Hence output = 2
.
Note: Your posted code in https://paste.ubuntu.com/p/tmXgQfm8GB/ works well for me.
Just observed that your target variable Property
is the last column of the DataFrame.
Temperature Weight Size Property
0 1 2 9 0.0
1 2 4 24 0.0
2 3 6 9 0.0
3 4 8 9 1.0
4 5 10 9 NaN
Modify your code as follows, instead of having:
# X_y_split
train_X = df[:, 1:]
train_y = df[:, 0]
change it to:
# X_y_split
train_X = df[:, :-1]
train_y = df[:, -1]
回答2:
What you have here is a classification network: It takes inputs, or features (Temperature, Weight and Size), and classify them into one of your classes : 0, 1 or 2. (Property field)
When you modified the original dataset, you modified the number of classes : from 3 (0,1,2)
, you went to 1. (1)
.
For the code to work, you just need to modify the parameters
section of your code so it fits your dataset.
# parameters
time_steps = 1
inputs = 3
outputs = 1
Note : In this case, I find the the term outputs
is a bit vague. I would have used something like nb_classes
来源:https://stackoverflow.com/questions/51787125/tensorflow-value-error-when-chaining-content-of-data-cannot-feed-value-of-shap