【问题标题】:How to predict new data with a trained neural network (Tensorflow 2.0, regression analysis)?如何使用经过训练的神经网络(Tensorflow 2.0,回归分析)预测新数据?
【发布时间】:2020-03-15 06:24:26
【问题描述】:

我是机器学习和使用 Tensorflow 的新手。我已经按照 Tensorflow 网站上的教程训练了一个用于回归的神经网络。我有 3 个输入列和 2 个输出列,我标记为“标签”。网络在使用测试数据时似乎可以很好地预测数据,但是当我尝试通过导入仅包含 3 个输入列的文件来预测测试和训练集之外的数据时,它给了我一个错误说 "expected dense_input to have shape (5,) 但得到了形状为 (3,)" 的数组。我理解它,因为该模型是在 5 列数据集上训练的,但我想从模型中预测未知值(一旦训练)并且不知道输出。 我只知道输入(3 列)时如何预测结果?如果我还必须知道输出(我确信我不知道),那么回归分析的意义何在?

我的数据如下所示:

我正在尝试让神经网络以这种方式执行:

我想预测我没有数据的输出(比如,RE = 25,BR=0.5,PR=0.25),我不能使用线性回归,因为输入和输出之间的关系不是线性的。我尝试在训练后将输入预测为 5 列文件,最后两列是垃圾(零),但模型试图预测零。据我了解,一旦模型经过训练,权重和偏差应该是固定的,并且无论最后两列(输出)是什么,模型都应该给我预期的输出。我究竟做错了什么?任何帮助表示赞赏。我已经在这里https://drive.google.com/open?id=1HoMID_razNHcXEGIgvnL8WG3H5WRTl3B 上传了代码中使用的文件。此外,有时我的 MSE(均方误差)会收敛,有时则不会。我怀疑这可能与将数据随机输入模型有关,尽管我不确定。

import tensorflow as tf
from tensorflow import keras
import numpy as np 
import matplotlib.pyplot as plt 
import pandas as pd 
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import pickle

column_names = ['Reynolds Number', 'Blockage Ratio', 'Prandtl Number', 'Nusselt Number', 'Drag Coefficient']        
dataset = pd.read_csv('WW.csv', names=column_names, skipinitialspace=True)      
train_dataset = dataset.sample(frac=0.9,random_state=0)
test_dataset = dataset.drop(train_dataset.index)    
train_labels = train_dataset.iloc[:, 3:].values
test_labels = test_dataset.iloc[:, 3:].values   

print(train_dataset)
print(test_dataset)                         

def build_model():
  model = keras.Sequential([
    keras.layers.Dense(3, activation='relu', input_shape=[len(train_dataset.keys())]),
    keras.layers.Dense(4, activation='relu'),
    keras.layers.Dense(2)
  ])

  optimizer = tf.keras.optimizers.RMSprop(0.001)

  model.compile(loss='mse',
                optimizer=optimizer,
                metrics=['mae', 'mse'])
  return model

model = build_model()
model.summary()

class PrintDot(keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs):
    if epoch % 100 == 0: print('')
    print('.', end='')

EPOCHS = 5000

early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=500)
history = model.fit(train_dataset, train_labels, epochs=EPOCHS, validation_split = 0.2, verbose=0, callbacks=[early_stop, PrintDot()])
model.save("model.h5")

hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch
print('\n', hist.tail())

def plot_history(history):
  hist = pd.DataFrame(history.history)
  hist['epoch'] = history.epoch

  plt.figure()
  plt.xlabel('Epoch')
  plt.ylabel('Mean Abs Error [MPG]')
  plt.plot(hist['epoch'], hist['mae'],
           label='Train Error')
  plt.plot(hist['epoch'], hist['val_mae'],
           label = 'Val Error')
  plt.ylim([0,5])
  plt.legend()

  plt.figure()
  plt.xlabel('Epoch')
  plt.ylabel('Mean Square Error [$MPG^2$]')
  plt.plot(hist['epoch'], hist['mse'],
           label='Train Error')
  plt.plot(hist['epoch'], hist['val_mse'],
           label = 'Val Error')
  plt.ylim([0,20])
  plt.legend()
  plt.show()


plot_history(history)

test_predictions = model.predict(test_dataset)
test_dataset['Predicted Nu'], test_dataset['Predicted CD'] = test_predictions[:,0], test_predictions[:,1]
print(test_dataset)

np.savetxt('test_dataset.txt', test_dataset, delimiter=',')

predict = model.predict(train_dataset)
train_dataset['Predicted Nu'], train_dataset['Predicted CD'] = predict[:,0], predict[:,1]
print(train_dataset)

np.savetxt('train_dataset.txt', train_dataset, delimiter=',')

class_names = ['Reynolds Number', 'Blockage Ratio', 'Prandtl Number', 'junk Nusselt Number', 'junk Drag Coefficient']    
all_inputs = pd.read_csv('Predict_Input.csv', names=class_names, skipinitialspace=True)
all_outputs = model.predict(all_inputs)
all_inputs['Predicted Nu'], all_inputs['Predicted CD'] = all_outputs[:,0], all_outputs[:,1]
print(all_inputs)

【问题讨论】:

  • 你能解释一下你想在这里实现什么吗?所以从我所见,train_inputs 是一个(batch_size, 5) 输入,而您正试图预测一个(batch_size, 2) 输出,它已经包含在火车数据中?如果我错了,请纠正我,但是这没有多大意义,因为您正在预测您已经知道的内容。也许你能用一个例子或图表来解释你需要什么?
  • 我已经包含了一个图表和我的一些数据。所有数据都可以在指定的链接中找到。我的网络的代码是否符合我的预期?也就是说,将前三列作为输入,后两列作为输出(指定为train_labels)? @thushv89
  • @HassanAhmed 不幸的是,它并没有像您认为的那样做。正如我在第一条评论中所说,您正在使用所有五个特征来预测输入中已经包含的两个特征。这不是正确的方法。我很快就会发布一个可能的解决方案。

标签: python tensorflow machine-learning


【解决方案1】:

所以重申一下你想要的,你有一个总共包含 5 个特征的数据集。您需要使用前三个特征作为输入,后两个作为目标。以下是实现这一目标需要进行的更改。

import tensorflow as tf
from tensorflow import keras
import numpy as np 
import matplotlib.pyplot as plt 
import pandas as pd 
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import pickle

column_names = ['Reynolds Number', 'Blockage Ratio', 'Prandtl Number', 'Nusselt Number', 'Drag Coefficient']        
dataset = pd.read_csv('WW.csv', names=column_names, skipinitialspace=True)      
train_dataset = dataset.sample(frac=0.9,random_state=0)
test_dataset = dataset.drop(train_dataset.index)    
train_labels = train_dataset.iloc[:, 3:].values
test_labels = test_dataset.iloc[:, 3:].values   

print(train_dataset)
print(test_dataset)                         

模型构建

您的模型应该只有三个特征。因此,input_shape 应该是 3(而不是 5)。批量形状将由 Keras 自动添加。

# We are setting the input size as (None, 3)
def build_model():
  model = keras.Sequential([
    keras.layers.Dense(3, activation='relu', input_shape=(3,)),
    keras.layers.Dense(4, activation='relu'),
    keras.layers.Dense(2)
  ])

  optimizer = tf.keras.optimizers.RMSprop(0.001)

  model.compile(loss='mse',
                optimizer=optimizer,
                metrics=['mae', 'mse'])
  return model

model = build_model()
model.summary()

class PrintDot(keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs):
    if epoch % 100 == 0: print('')
    print('.', end='')

训练模型

在训练模型时,您只需将前三个特征作为输入,最后两个特征作为标签/目标。现在您应该看到它如何帮助解决您的问题。现在您可以只使用已知的三个特征来安全地预测两个未知变量。

因此,当训练作为输入时,我们只给出前三列,目标将是最后两列。

EPOCHS = 5000

early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=500)

# Note that the input only takes the first three columns
history = model.fit(train_dataset.iloc[:,:3], train_labels, epochs=EPOCHS, validation_split = 0.2, verbose=0, callbacks=[early_stop, PrintDot()])
model.save("model.h5")

测试时间

测试和中提琴的规则相同!您在测试时没有使用未知的两个特征来预测(即我们只使用前三个特征)。

test_predictions = model.predict(test_dataset.iloc[:,:3])
print(test_dataset)
test_dataset['Predicted Nu'], test_dataset['Predicted CD'] = test_predictions[:,0], test_predictions[:,1]
print("\nPredicted\n")
print(test_dataset)

【讨论】:

  • 是的,这行得通。非常感谢。我有一个后续问题。当输入层中只有 3 个神经元时,我的网络如何能够接受具有 5 个参数的输入?他们的号码不是必须相同吗?
  • 嗯,实际上您的网络有 5 个输入。你设置了input_shape=[len(train_dataset.keys())],也就是5。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-01
  • 2017-05-23
  • 2021-01-14
  • 2020-09-10
  • 1970-01-01
  • 2018-11-15
  • 2016-12-23
相关资源
最近更新 更多