Otto 分類問題
這裡,我們将對Otto資料集進行分類。
- 本文主要參考 2.3 Introduction to Keras。個人覺得這是一個很好Keras教程,希望大家也去學習學習。
- 關于Otto,可以在 otto group 找到更多詳細的材料
- 本文主要關注代碼的實作,具體細節和基本概念不會詳細展開
讓我們開始吧
就像以前說過的那樣,處理一個問題主要分為三個部分:資料準備,模型建構和模型優化
導入子產品
這裡遇到了新的子產品
- StandardScaler 用于歸一化,感覺很好使。詳見StandardScaler
- LabelEncoder 配合np_utils用于One-hot編碼,詳見LabelEncoder。注意和OneHotEncoder的差別。
- EarlyStopping 當監測值不再改善時,該回調函數将中止訓練。詳見EarlyStopping
- ModelCheckpoint 儲存模型。詳見ModelCheckpoint
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import LabelEncoder
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers.core import Dense, Activation, Dropout
from keras.callbacks import EarlyStopping, ModelCheckpoint
## 資料準備 讀取資料。資料可以在 [otto group](https://www.kaggle.com/c/otto-group-product-classification-challenge/data) 找到
train_path = './data/train.csv'
test_path = './data/test.csv'
df = pd.read_csv(train_path)
觀察資料。有93個特征,最後一列是種類,第一列的id對于訓練沒有任何作用。
df.head()
id | feat_1 | feat_2 | feat_3 | feat_4 | feat_5 | feat_6 | feat_7 | feat_8 | feat_9 | … | feat_85 | feat_86 | feat_87 | feat_88 | feat_89 | feat_90 | feat_91 | feat_92 | feat_93 | target |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | … | 1 | Class_1 | ||||||||||||||||
1 | 2 | 1 | … | Class_1 | ||||||||||||||||
2 | 3 | 1 | … | Class_1 | ||||||||||||||||
3 | 4 | 1 | 1 | 6 | 1 | 5 | … | 1 | 2 | Class_1 | ||||||||||
4 | 5 | … | 1 | 1 | Class_1 |
5 rows × 95 columns
導入資料。
- 第一列id對訓練沒用,是以我們不需要它。
- train 和 test 兩個檔案有所差別(test中沒有給出target)
def load_data(path, train=True):
df = pd.read_csv(path)
X = df.values.copy()
if train:
np.random.shuffle(X)
X, label = X[:, :-].astype(np.float32), X[:, -]
return X, label
else:
X, ids = X[:, :].astype(np.float32), X[:, ].astype(str)
return X, ids
X_train, y_train = load_data(train_path)
X_test, ids = load_data(test_path, train=False)
預處理,訓練資料和測試資料一起歸一化,以免忘記了
def preprocess_data(X, scaler=None):
if not scaler:
scaler = StandardScaler()
scaler.fit(X)
X = scaler.transform(X)
return X, scaler
X_train, scaler = preprocess_data(X_train)
X_test, _ = preprocess_data(X_test, scaler)
One-hot 編碼
def preprocess_label(labels, encoder=None, categorical=True):
if not encoder:
encoder = LabelEncoder()
encoder.fit(labels)
y = encoder.transform(labels).astype(np.int32)
if categorical:
y = np_utils.to_categorical(y)
return y, encoder
y_train, encoder = preprocess_label(y_train)
搭建網絡模型
dim = X_train.shape[]
print(dim, 'dims')
print('Building model')
nb_classes = y_train.shape[]
model = Sequential()
model.add(Dense(, input_shape=(dim, )))
model.add(Activation('relu'))
model.add(Dropout())
model.add(Dense())
model.add(Activation('relu'))
model.add(Dropout())
model.add(Dense())
model.add(Activation('relu'))
model.add(Dropout())
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
93 dims
Building model
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
batch_size =
epochs =
訓練,同時保持最佳模型
fBestModel = 'best_model.h5'
early_stop = EarlyStopping(monitor='val_acc', patience=, verbose=)
best_model = ModelCheckpoint(fBestModel, verbose=, save_best_only=True)
model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, verbose=, validation_split=, callbacks=[best_model, early_stop])
Train on 55690 samples, validate on 6188 samples
Epoch 1/2
55690/55690 [==============================] - 2s 42us/step - loss: 0.5256 - acc: 0.7967 - val_loss: 0.5268 - val_acc: 0.7982
Epoch 2/2
55690/55690 [==============================] - 2s 42us/step - loss: 0.5251 - acc: 0.7991 - val_loss: 0.5256 - val_acc: 0.8017
<keras.callbacks.History at 0x13551adaef0>
預測并儲存結果。将結果儲存為Kaggle上要求的格式,然後送出了測試結果,得到了0.5左右的分數,據說大概前50%左右
prediction = model.predict(X_test)
num_pre = prediction.shape[]
columns = ['Class_'+str(post+) for post in range()]
df2 = pd.DataFrame({'id' : range(,num_pre+)})
df3 = pd.DataFrame(prediction, columns=columns)
df_pre = pd.concat([df2, df3], axis=)
df_pre.to_csv('predition.csv', index=False)