【问题标题】:keras accuracy doesn't improve more than 59 percentkeras 的准确性提高不超过 59%
【发布时间】:2020-12-13 06:28:15
【问题描述】:

这是我试过的代码:

# normalizing the train data
cols_to_norm = ["WORK_EDUCATION", "SHOP", "OTHER",'AM','PM','MIDDAY','NIGHT', 'AVG_VEH_CNT', 'work_traveltime', 'shop_traveltime','work_tripmile','shop_tripmile', 'TRPMILES_sum',
                'TRVL_MIN_sum', 'TRPMILES_mean', 'HBO', 'HBSHOP', 'HBW', 'NHB', 'DWELTIME_mean','TRVL_MIN_mean', 'work_dweltime', 'shop_dweltime', 'firsttrip_time', 'lasttrip_time']
dataframe[cols_to_norm] = dataframe[cols_to_norm].apply(lambda x: (x - x.min()) / (x.max()-x.min()))
# labels    
y = dataframe.R_SEX.values

# splitting train and test set
X_train, X_test, y_train, y_test =train_test_split(X, y, test_size=0.33, random_state=42)

model = Sequential()
model.add(Dense(256, input_shape=(X_train.shape[1],), activation='relu'))
model.add(Dense(256, activation='relu'))
model.add(layers.Dropout(0.3))
model.add(Dense(256, activation='relu'))
model.add(layers.Dropout(0.3))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer='adam' , metrics=['acc'])
print(model.summary())

model.fit(X_train, y_train , batch_size=128, epochs=30, validation_split=0.2)

Epoch 23/30
1014/1014 [==============================] - 4s 4ms/step - loss: 0.6623 - acc: 0.5985 - val_loss: 0.6677 - val_acc: 0.5918
Epoch 24/30
1014/1014 [==============================] - 4s 4ms/step - loss: 0.6618 - acc: 0.5993 - val_loss: 0.6671 - val_acc: 0.5925
Epoch 25/30
1014/1014 [==============================] - 4s 4ms/step - loss: 0.6618 - acc: 0.5997 - val_loss: 0.6674 - val_acc: 0.5904
Epoch 26/30
1014/1014 [==============================] - 4s 4ms/step - loss: 0.6614 - acc: 0.6001 - val_loss: 0.6669 - val_acc: 0.5911
Epoch 27/30
1014/1014 [==============================] - 4s 4ms/step - loss: 0.6608 - acc: 0.6004 - val_loss: 0.6668 - val_acc: 0.5920
Epoch 28/30
1014/1014 [==============================] - 4s 4ms/step - loss: 0.6605 - acc: 0.6002 - val_loss: 0.6679 - val_acc: 0.5895
Epoch 29/30
1014/1014 [==============================] - 4s 4ms/step - loss: 0.6602 - acc: 0.6009 - val_loss: 0.6663 - val_acc: 0.5932
Epoch 30/30
1014/1014 [==============================] - 4s 4ms/step - loss: 0.6597 - acc: 0.6027 - val_loss: 0.6674 - val_acc: 0.5910
<tensorflow.python.keras.callbacks.History at 0x7fdd8143a278>

我尝试过修改神经网络并仔细检查数据。

我能做些什么来改善结果吗?模型不够深?是否有适合我的数据的替代模型?这是否意味着这些特征没有预测价值?我有点困惑下一步该做什么。

谢谢

更新:

我尝试在我的数据框中添加新列,这是用于性别分类的 KNN 模型的结果。这是我所做的:

#Import knearest neighbors Classifier model
from sklearn.neighbors import KNeighborsClassifier

#Create KNN Classifier
knn = KNeighborsClassifier(n_neighbors=41)

#Train the model using the training sets
knn.fit(X, y)

#predict sex for the train set so that it can be fed to the nueral net
y_pred = knn.predict(X)

#add the outcome of knn to the train set
X = X.assign(KNN_result=y_pred)

它将训练和验证准确率提高了 61%。

Epoch 26/30
1294/1294 [==============================] - 8s 6ms/step - loss: 0.6525 - acc: 0.6166 - val_loss: 0.6604 - val_acc: 0.6095
Epoch 27/30
1294/1294 [==============================] - 8s 6ms/step - loss: 0.6523 - acc: 0.6173 - val_loss: 0.6596 - val_acc: 0.6111
Epoch 28/30
1294/1294 [==============================] - 8s 6ms/step - loss: 0.6519 - acc: 0.6177 - val_loss: 0.6614 - val_acc: 0.6101
Epoch 29/30
1294/1294 [==============================] - 8s 6ms/step - loss: 0.6512 - acc: 0.6178 - val_loss: 0.6594 - val_acc: 0.6131
Epoch 30/30
1294/1294 [==============================] - 8s 6ms/step - loss: 0.6510 - acc: 0.6183 - val_loss: 0.6603 - val_acc: 0.6103
<tensorflow.python.keras.callbacks.History at 0x7fe981bbe438>

谢谢

【问题讨论】:

  • 您正在使用binary_crossentropy。你的y_train 看起来像[[0, 1], [0, 0], [1, 0]] 吗?它应该具有像[batch_size, d0, .. dN] 这样的维度,其中dN 是类别数。你能在这里打印它的尺寸吗?
  • 另外,辍学率似乎有点太高了。此外,您可以尝试更浅的网络,最多有 1 个隐藏层。
  • @tornikeo 我的y_train 看起来像array([1, 0, 1, ..., 0, 0, 1])。你的意思是X_train 应该有维度?
  • 我之前尝试过这样的浅网:model = Sequential() model.add(Dense(15, input_shape=(X_train.shape[1],), activation='relu')) model.add(Dense(10, activation='relu')) model.add(Dense(1, activation='sigmoid'))。结果是一样的
  • 为了让人们更轻松地测试您的代码...使用您的共享文件创建一个 colab(colab.research.google.com)。然后更多的人可以尝试您的问题,而无需自己设置所有内容!可以尝试的人越多 = 得到答案的机会就越多!

标签: python tensorflow keras


【解决方案1】:

简而言之: NN 很少是分类少量数据或已经由一些非异构列紧凑表示的数据的最佳模型。通常情况下,增强方法或 GLM 会通过类似的努力产生更好的结果。

你可以用你的模型做什么?与直觉相反,有时阻碍网络容量可能是有益的,尤其是当网络参数的数量超过训练点的数量时。可以减少神经元的数量,例如在您的情况下将层大小设置为 16 左右并同时删除层;引入正则化(标签平滑、权重衰减等);或通过添加更多不同(对数、二进制)比例的派生列来生成更多数据。

另一种方法是搜索为您的数据类型设计的 NN 模型。例如,Self-Normalizing Neural Networks 或 Wide & Deep Learning for Recommender Systems。

如果您只尝试一件事,我建议您对学习率进行网格搜索或尝试一些不同的优化器。

如何更好地决定使用哪种模型?查看已完成的 kaggle.com 比赛并找到与手头相似的数据集,然后查看排名靠前的地方使用的技术。

【讨论】:

    【解决方案2】:

    在我看来,对于神经网络,您的数据还不够多变。您的数据集中有很多类似的值。这可能是准确性低的原因。尝试一个简单的回归器,而不是神经网络。

    如果你想在任何情况下使用神经网络,你应该改变以下内容:

    通常对于回归,您应该将最后一层的激活函数设置为“relu”或“线性”,sigmoid 通常用于隐藏层。

    尝试先更改这些。如果它不起作用,请尝试不同的策略:

    1. 增加批量大小
    2. 增加 epoch 的数量
    3. 在运行前对数据集应用白化(预处理阶段)。
    4. 降低学习率,你应该使用scheduler。

    对于美白,您可以这样做:

    from sklearn.decomposition import PCA
    
    pca = PCA(whiten=True)
    pca.fit(X)
    X = pca.transform(X)
    
    # make here train test split ...
    
    X_test = pca.transform(X_test) # use the same pca model for the test set.
    
    

    您的数据集中有很多零。在这里,您有每列(0 到 1 之间)零值百分比的列表:

    0.6611697598907094 WORK_EDUCATION
    0.5906196483663051 SHOP
    0.15968546556987515 OTHER
    0.4517919980835284 AM
    0.3695455825652879 PM
    0.449195697003247 MIDDAY
    0.8160996565242585 NIGHT
    0.03156998520561604 AVG_VEH_CNT
    1.618641571247746e-05 work_traveltime
    2.2660981997468445e-05 shop_traveltime
    0.6930343378622924 work_tripmile
    0.605410795044367 shop_tripmile
    0.185622578107549 TRPMILES_sum
    3.237283142495492e-06 TRVL_MIN_sum
    0.185622578107549 TRPMILES_mean
    0.469645614614391 HBO
    0.5744850291841075 HBSHOP
    0.8137429143965219 HBW
    0.5307266729469959 NHB
    0.2017960446874565 DWELTIME_mean
    1.618641571247746e-05 TRVL_MIN_mean
    0.6959996892208183 work_dweltime
    0.6099365168775757 shop_dweltime
    0.0009258629787537107 firsttrip_time
    0.002949164942813393 lasttrip_time
    0.7442934791405661 age_2.0
    0.7541995655566023 age_3.0
    0.7081200773063214 age_4.0
    0.9401296855626884 age_5.0
    0.3490503429901489 KNN_result
    

    【讨论】:

    • 这些建议不是通用的,而不是针对这个问题的吗?
    • @Aswin:不是真的,我是在快速检查数据并分析神经网络后回答的。另一方面,这些是公认的改进神经网络模型的技术。最后,每个数据集都是不同的,在测试不同的设置之前,我们无法知道什么结果是最好的。
    • @CatalinaChircu 我尝试了您的建议,但不幸的是它无助于改进模型。你能提供一些代码来对这些数据应用白化吗?谢谢
    • 再次更新了答案。
    • 现在我通过删除只有零的行获得了 62% 的准确率。我想,这是我能回答的最好的问题。谢谢
    【解决方案3】:

    使用pd.get_dummies 减小批量大小并转换因变量 (Y)

    在最后一层使用:

    model.add(Dense(2, activation='sigmoid'))

    此外,根据数据的大小,您可以将神经元的数量从 256 个减少到 128 个。

    将 Dropout 降低到 0.2:

    model = Sequential()
    model.add(Dense(128, input_shape=(X_train.shape[1],), activation='relu'))
    model.add(Dense(128, activation='relu'))
    model.add(layers.Dropout(0.2))
    model.add(Dense(128, activation='relu'))
    model.add(layers.Dropout(0.2))
    model.add(Dense(2, activation='sigmoid'))
    

    【讨论】:

      【解决方案4】:

      好的,我测试了另一种算法 Catboost,我得到了准确度:0.9295405324035856

      这里:

      导入、常量和函数:

      from catboost import CatBoostRegressor, Pool
      
      PARAMS_CATBOOST_REGRESSOR = dict()
      PARAMS_CATBOOST_REGRESSOR['learning_rate']=0.1
      PARAMS_CATBOOST_REGRESSOR['use_best_model']= True
      PARAMS_CATBOOST_REGRESSOR['logging_level'] = 'Silent'
      PARAMS_CATBOOST_REGRESSOR['l2_leaf_reg'] = 1.0 # lambda, default 3, S: 300
      
      SPLITS=5
      
      def get_prediction(X, Y, X_predict):
          kf = KFold(n_splits=SPLITS, shuffle=True)
          
          count=0
          cat_features=[]
          y_test_predict = np.zeros((X_predict.shape[0]))
          oo = np.zeros((X.shape[0]))  
          
          clf = CatBoostRegressor(**PARAMS_CATBOOST_REGRESSOR)
              
          for train_index, test_index in kf.split(X, Y):
                 count = count+1
                 print("Split "+str(count)+" ... ")
      
                 X_train, X_test = X.iloc[train_index], X.iloc[test_index]
                 y_train, y_test = Y.iloc[train_index], Y.iloc[test_index]
      
                 train_dataset = Pool(data=X_train,
                           label=y_train,
                           cat_features=cat_features)
      
                 eval_dataset = Pool(data=X_test,
                           label=y_test,
                           cat_features=cat_features)
      
                 clf.fit(train_dataset,
                          use_best_model=True,
                          eval_set=eval_dataset)
      
                 print("Count of trees in model = {}".format(clf.tree_count_))
                  
                 oo[test_index] = clf.predict(X_test)
                 y_test_predict += clf.predict(X_predict)    
                  
          y_test_predict = y_test_predict/float(SPLITS)
          return (oo, y_test_predict)
      

      预处理:

      df = pd.read_csv('df1.csv')
      y = df['R_SEX'].values
      
      # Add a column with number of zeros per row
      df['c_zero'] = (df == 0).astype(int).sum(axis=1) 
      
      # Delete columns with more than 70% zeros
      l1 = ['R_SEX', 'NIGHT', 'age_2.0', 'age_3.0', 'age_4.0','age_5.0', 'HBW', 'work_tripmile',  'work_dweltime', 'WORK_EDUCATION' ]
      x_cols = [c for c in df.columns if c not in l1]
      
      X = df[x_cols].values
      sh = df.shape[0]
      
      # Normalize : 
      for c in df[x_cols]:
        dd = df.loc[df[c]==0]
        print(dd.shape[0]/df.shape[0], c)
      

      运行:

      df.reset_index(drop=True, inplace=True)
      YY = df['R_SEX']
      XX = df[x_cols]
      (oo, ypred) = get_prediction(XX, YY, XX)
      

      解析分数:

      df = pd.DataFrame(oo, columns=['pred'])
      df['y'] = YY
      df['v'] = df.apply(lambda row: 1 if row['pred']>=0.5 else 0, axis=1)
      df.sort_values(by=['y'])
      df['diff'] = df['v'] - df['y']
      pp = df[df['diff']==0].shape[0]
      pdf = df.shape[0]
          
      print(pp/pdf)
      

      结果:

      Score = 0.9295405324035856
      

      【讨论】:

      • 此解决方案之所以有效,只是因为您定义了一个新列来指示零的数量,并且标签也是该列的一部分。当我在没有R_SEX 又名标签的情况下定义同一列 (c_zero) 时,它再次产生 60% 的准确度。但没关系。我找到了另一种通过正确可靠的解决方案达到 95+ 准确度的方法。
      猜你喜欢
      • 2020-01-07
      • 1970-01-01
      • 2020-06-15
      • 2018-10-09
      • 2017-10-09
      • 1970-01-01
      • 2019-11-18
      • 2020-12-29
      • 2019-10-23
      相关资源
      最近更新 更多