我试图训练一个模型来根据航空公司、月份的日期、目的地和出发地预测出发延误。我尝试了几种方法,但准确率非常低。输入图片描述首先,我直接使用了从-20到+20分钟的延误标签,我尝试通过设置区间使其更简单,例如:对于延误在[0 5[的 => 0,[5 10]的 => 1 ..等
但准确率仍然很差,我尝试了几种方法;
更改层数
不规范化特征,去除和添加新特征
但我仍然找不到有效的方法
################### 加载数据集
df= dataset[['UniqueCarrier','DayofMonth','DepDelay','Dest','Origin']]df.tail()df = df.dropna()df = df[(df['DepDelay'] <= 20) & (df['DepDelay'] <= 20)]
############### 掩码延误值
mask = (df.DepDelay > 0) & (df.DepDelay < 5)column_name = 'DepDelay'df.loc[mask, column_name] = 0mask = (df.DepDelay >= 5) & (df.DepDelay < 10)column_name = 'DepDelay'df.loc[mask, column_name] = 1mask = (df.DepDelay >= 10) & (df.DepDelay < 15)column_name = 'DepDelay'df.loc[mask, column_name] = 2mask = (df.DepDelay >= 15) & (df.DepDelay <= 20)column_name = 'DepDelay'df.loc[mask, column_name] = 3mask = (df.DepDelay >= -5) & (df.DepDelay < 0)column_name = 'DepDelay'df.loc[mask, column_name] = -1mask = (df.DepDelay >= -10) & (df.DepDelay < -5)column_name = 'DepDelay'df.loc[mask, column_name] = -2mask = (df.DepDelay >= -15) & (df.DepDelay < -10)column_name = 'DepDelay'df.loc[mask, column_name] = -3mask = (df.DepDelay >= -20) & (df.DepDelay < -15)column_name = 'DepDelay'df.loc[mask, column_name] = -4
############### 分割标签和特征
y= df['DepDelay']df.drop(columns = ['DepDelay'], inplace = True, axis = 1)
################ 替换字符值
from sklearn import preprocessingle = preprocessing.LabelEncoder()df['Dest'] = le.fit_transform(df.Dest.values)df['Origin'] = le.fit_transform(df.Origin.values)df['UniqueCarrier'] = le.fit_transform(df.UniqueCarrier.values
########################## 归一化
from sklearn.preprocessing import StandardScalerfrom sklearn import preprocessing# 归一化训练数据 std_scale = preprocessing.StandardScaler().fit(df)df_norm = std_scale.transform(df)training_norm_col1 = pd.DataFrame(df_norm, index=df.index, columns=df.columns) df.update(training_norm_col1)print (df.head())
########################## 模型
import tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layersfrom keras.models import Sequentialfrom keras.layers import Dense, Dropoutimport matplotlib.pyplot as pltimport numpyclass LossHistory(keras.callbacks.Callback): def on_train_begin(self, logs={}): self.losses = [] def on_batch_end(self, batch, logs={}): self.losses.append(logs.get('loss'))model = Sequential()model.add(Dense(64, input_dim=4, activation='relu'))model.add(Dense(30, activation='relu'))model.add(Dense(12, activation='relu'))model.add(Dense(1))# 编译模型model.compile(loss='mean_squared_error', optimizer='adam', metrics= ['accuracy'])# 拟合模型history = LossHistory()model.fit(df, y, validation_split=0.33, epochs=1000, batch_size=50,verbose=1, callbacks=[history])print(history.losses)
训练时的准确率约为:0.3524。用于训练的数据框大约有300万行
回答:
当使用loss = 'mean_squared_error'
并且在单节点最终层没有使用激活函数(即默认的线性激活函数)时,如您所做的那样,您处于一个回归设置中,此时准确率是无意义的(它仅在分类问题中是有意义的)。
不幸的是,Keras在这种情况下不会“保护”您,坚持计算并报告回一个“准确率”,尽管它对于您的问题来说是无意义且不适当的 – 请参阅我在当损失为均方误差(MSE)时,Keras中定义准确率的函数是什么?中的回答
如果您想坚持使用回归设置,您应该简单地从模型编译中移除metrics=['accuracy']
,并且不要担心 – 在回归设置中,MSE本身可以(并且通常确实)也作为性能指标。但这意味着您将尝试直接预测数值,而不是像您描述的那样来自分箱的“标签”。
如果您想预测像
[0 5] => 0 [5 10] => 1
等这样的分箱区间,即在分类设置中工作,您应该将损失更改为categorical_cross_entropy
,并保留准确率作为您的指标。请记住,您还应该将标签转换为独热编码(参见Keras的to_categorical
),并将最终层替换为
model.add(Dense(num_classes, activation='softmax'))
其中num_classes
是您的分箱过程所得的类别数量。