Keras多层神经网络精度
Keras Multi-layer Neural Network Accuracy
我使用 Keras 和 precipitation data in Australia 构建了一个简单的多层神经网络。该代码采用 4 个输入列:['MinTemp', 'MaxTemp', 'Rainfall', 'WindGustSpeed']
并针对 RainTomorrow
输出进行训练。
我已将数据划分为 training/test 个存储桶,将所有值转换为 0 <= n <= 1
。当我尝试 运行 model.fit
时,我的损失值稳定在 ~13.2,但我的准确度始终为 0.0。记录的拟合间隔的一个例子是:
...
Epoch 37/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.1274 - acc: 0.0000e+00 - val_loss: -16.1168 - val_acc: 0.0000e+00
Epoch 38/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.1457 - acc: 0.0000e+00 - val_loss: -16.1168 - val_acc: 0.0000e+00
Epoch 39/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.1315 - acc: 0.0000e+00 - val_loss: -16.1168 - val_acc: 0.0000e+00
Epoch 40/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.1797 - acc: 0.0000e+00 - val_loss: -16.1168 - val_acc: 0.0000e+00
Epoch 41/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.1844 - acc: 0.0000e+00 - val_loss: -16.1169 - val_acc: 0.0000e+00
Epoch 42/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.2205 - acc: 0.0000e+00 - val_loss: -16.1169 - val_acc: 0.0000e+00
Epoch 43/200
...
如何修改以下脚本,使我的准确性提高,预测输出 returns 一个介于 0 和 1 之间的值(0:无雨,1:下雨)?
import keras
import sklearn.model_selection
import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import MinMaxScaler
labelencoder = LabelEncoder()
# read data, replace NaN with 0.0
csv_data = pd.read_csv('weatherAUS.csv', header=0)
csv_data = csv_data.replace(np.nan, 0.0, regex=True)
# Input/output columns scaled to 0<=n<=1
x = csv_data.loc[:, ['MinTemp', 'MaxTemp', 'Rainfall', 'WindGustSpeed']]
y = labelencoder.fit_transform(csv_data['RainTomorrow'])
scaler_x = MinMaxScaler(feature_range =(-1, 1))
x = scaler_x.fit_transform(x)
scaler_y = MinMaxScaler(feature_range =(-1, 1))
y = scaler_y.fit_transform([y])[0]
# Partitioned data for training/testing
x_train, x_test, y_train, y_test = sklearn.model_selection.train_test_split(x, y, test_size=0.2)
# model
model = keras.models.Sequential()
model.add( keras.layers.normalization.BatchNormalization(input_shape=tuple([x_train.shape[1]])))
model.add(keras.layers.core.Dense(4, activation='relu'))
model.add(keras.layers.core.Dropout(rate=0.5))
model.add(keras.layers.normalization.BatchNormalization())
model.add(keras.layers.core.Dense(4, activation='relu'))
model.add(keras.layers.core.Dropout(rate=0.5))
model.add(keras.layers.normalization.BatchNormalization())
model.add(keras.layers.core.Dense(4, activation='relu'))
model.add(keras.layers.core.Dropout(rate=0.5))
model.add(keras.layers.core.Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=["accuracy"])
callback_early_stopping = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10, verbose=0, mode='auto')
model.fit(x_train, y_train, batch_size=1024, epochs=200, validation_data=(x_test, y_test), verbose=1, callbacks=[callback_early_stopping])
y_test = model.predict(x_test.values)
如您所见,您在神经网络输出(最后一层)中使用的 sigmoid 激活函数的范围是 0 到 1。
请注意,您的标签 (y) 已重新调整为 -1 到 1。
我建议您将 y 范围更改为 0 到 1 并保持 sigmoid 输出。
所以 sigmoid 的范围是从 0 到 1。
您的 MinMaxscaler 将数据从 -1 缩放到 1。
您可以通过将输出层中的 'sigmoid' 替换为 'tanh' 来修复它,因为 tanh 的输出范围为 -1 到 1
其他两个答案都可用于解决您的网络输出与 y
矢量值不在同一范围内的事实。将最后一层调整为 tanh 激活,或将 y
-向量范围更改为 [0,1]。
但是,您的网络损失函数和指标是为分类目的而定义的,在您尝试回归时([-1, 1] 之间的连续值)。最常用的损失函数和精度指标是均方误差或平均绝对误差。所以我建议您更改以下内容:
model.compile(loss='mse', optimizer='rmsprop', metrics=['mse, 'mae'])
我使用 Keras 和 precipitation data in Australia 构建了一个简单的多层神经网络。该代码采用 4 个输入列:['MinTemp', 'MaxTemp', 'Rainfall', 'WindGustSpeed']
并针对 RainTomorrow
输出进行训练。
我已将数据划分为 training/test 个存储桶,将所有值转换为 0 <= n <= 1
。当我尝试 运行 model.fit
时,我的损失值稳定在 ~13.2,但我的准确度始终为 0.0。记录的拟合间隔的一个例子是:
...
Epoch 37/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.1274 - acc: 0.0000e+00 - val_loss: -16.1168 - val_acc: 0.0000e+00
Epoch 38/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.1457 - acc: 0.0000e+00 - val_loss: -16.1168 - val_acc: 0.0000e+00
Epoch 39/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.1315 - acc: 0.0000e+00 - val_loss: -16.1168 - val_acc: 0.0000e+00
Epoch 40/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.1797 - acc: 0.0000e+00 - val_loss: -16.1168 - val_acc: 0.0000e+00
Epoch 41/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.1844 - acc: 0.0000e+00 - val_loss: -16.1169 - val_acc: 0.0000e+00
Epoch 42/200
113754/113754 [==============================] - 0s 2us/step - loss: -13.2205 - acc: 0.0000e+00 - val_loss: -16.1169 - val_acc: 0.0000e+00
Epoch 43/200
...
如何修改以下脚本,使我的准确性提高,预测输出 returns 一个介于 0 和 1 之间的值(0:无雨,1:下雨)?
import keras
import sklearn.model_selection
import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import MinMaxScaler
labelencoder = LabelEncoder()
# read data, replace NaN with 0.0
csv_data = pd.read_csv('weatherAUS.csv', header=0)
csv_data = csv_data.replace(np.nan, 0.0, regex=True)
# Input/output columns scaled to 0<=n<=1
x = csv_data.loc[:, ['MinTemp', 'MaxTemp', 'Rainfall', 'WindGustSpeed']]
y = labelencoder.fit_transform(csv_data['RainTomorrow'])
scaler_x = MinMaxScaler(feature_range =(-1, 1))
x = scaler_x.fit_transform(x)
scaler_y = MinMaxScaler(feature_range =(-1, 1))
y = scaler_y.fit_transform([y])[0]
# Partitioned data for training/testing
x_train, x_test, y_train, y_test = sklearn.model_selection.train_test_split(x, y, test_size=0.2)
# model
model = keras.models.Sequential()
model.add( keras.layers.normalization.BatchNormalization(input_shape=tuple([x_train.shape[1]])))
model.add(keras.layers.core.Dense(4, activation='relu'))
model.add(keras.layers.core.Dropout(rate=0.5))
model.add(keras.layers.normalization.BatchNormalization())
model.add(keras.layers.core.Dense(4, activation='relu'))
model.add(keras.layers.core.Dropout(rate=0.5))
model.add(keras.layers.normalization.BatchNormalization())
model.add(keras.layers.core.Dense(4, activation='relu'))
model.add(keras.layers.core.Dropout(rate=0.5))
model.add(keras.layers.core.Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=["accuracy"])
callback_early_stopping = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10, verbose=0, mode='auto')
model.fit(x_train, y_train, batch_size=1024, epochs=200, validation_data=(x_test, y_test), verbose=1, callbacks=[callback_early_stopping])
y_test = model.predict(x_test.values)
如您所见,您在神经网络输出(最后一层)中使用的 sigmoid 激活函数的范围是 0 到 1。
请注意,您的标签 (y) 已重新调整为 -1 到 1。
我建议您将 y 范围更改为 0 到 1 并保持 sigmoid 输出。
所以 sigmoid 的范围是从 0 到 1。 您的 MinMaxscaler 将数据从 -1 缩放到 1。
您可以通过将输出层中的 'sigmoid' 替换为 'tanh' 来修复它,因为 tanh 的输出范围为 -1 到 1
其他两个答案都可用于解决您的网络输出与 y
矢量值不在同一范围内的事实。将最后一层调整为 tanh 激活,或将 y
-向量范围更改为 [0,1]。
但是,您的网络损失函数和指标是为分类目的而定义的,在您尝试回归时([-1, 1] 之间的连续值)。最常用的损失函数和精度指标是均方误差或平均绝对误差。所以我建议您更改以下内容:
model.compile(loss='mse', optimizer='rmsprop', metrics=['mse, 'mae'])