SIGNATEのSOTAに参加した話

ここで実行されているコードはこちらの[github](https://github.com/jaguar2801/hikkoshi)にあります
-
## [アップル引越しセンターのデータ分析](https://signate.jp/competitions/269)
今回の評価は平均誤差で行う。[MAE（mean_absolute_error）](https://keras.io/ja/losses/)

### データの前処理
与えられたデータには「日付、法人が絡むかどうか、休業日、午前の料金区分、午後の料金区分」の５つの説明変数と、目的変数が需要数となります。
　日本のデータなので、日付から曜日を出して、説明変数に付け加えた。曜日をダミー変数にしてデータに付け加えて、データの前処理を行なった。

標準化や正規化は、カテゴリデータが多いのでやっても意味をなさないと思い、今回の解析では行わなかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1157150/3047c5b1-c7aa-39d7-aa16-810daf2e368e.png)


### データ可視化
##### 引越しの需要数を可視化
周期性があるようにも見えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1157150/e23fcda0-2397-2209-71de-e2babeb67f67.png)

##### 数値データを散布図で表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1157150/0c67cf8d-c68a-a564-9249-aa957b6283a9.png)
データのほとんどがカテゴリデータを数値に変えているだけなので、綺麗な散布図は出てこなかったですね。カテゴリデータを解析した経験がないので可視化してもよくわかりませんでした。

##### ヒートマップを可視化
相関があるかどうかを見るためにヒートマップを表示。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1157150/83a9df18-66d4-6a67-3cf3-ef93c9a17866.png)
yとの相関はprice_am,price_pmが高いので、この２つは重要度の高い説明変数かもしれない。
日曜日との相関が高いのは何となくわかる。他の曜日とは相関が少なさそう。

### データ分析

###### SVR

``` python
tuned_parameters = [
    {'C': [1,5, 10,50, 100,500, 1000], 'kernel': ['linear']},
    {'C': [1,5, 10,50, 100,500, 1000], 'kernel': ['rbf'], 'gamma': [0.001, 0.0001]},
    {'C': [1,5, 10,50, 100,500, 1000], 'kernel': ['poly'], 'degree': [2, 3, 4], 'gamma': [0.001, 0.0001]},
    {'C': [1,5, 10,50, 100,500, 1000], 'kernel': ['sigmoid'], 'gamma': [0.001, 0.0001]}
    ]
#score = mean_absolute_error(y_pred, y_train)
clf = GridSearchCV(
    SVR(), # 識別器
    tuned_parameters, # 最適化したいパラメータセット 
    cv=10, # 交差検定の回数
    n_jobs=-1,
   scoring='neg_mean_absolute_error'
) # モデルの評価関数の指定
clf.fit(X_train, y_train)
```

``` python
def best_model(best_params):
    if best_params['kernel']=='rbf':
        model = SVR(kernel=best_params['kernel'], C=best_params['C'], epsilon=0.1, gamma=best_params['gamma'])
    elif best_params['kernel']=='poly':
        model=SVR(kernel=best_params['kernel'], C=best_params['C'], degree=best_param['degree'],
                  epsilon=0.1, gamma=best_params['gamma'])
    elif best_params['kernel']=='linear':
        model=SVR(kernel=best_model['kernel'],C=best_params['C'],epsilon=0.1)
    elif best_params['kernel']=='sigmoid':
        model=SVR(kernel=best_params['kernel'],C=betst_params['C'],gamma=best_params['gammma'],epsilon=0.1)
    return model

# 最適パラメータで学習させてモデルの保存
fit_model=best_model(clf.best_params_).fit(X_train,y_train)
#　上で学習させたモデルの評価
print(best_model(clf.best_params_)) #10.922771453707899
print(MAE(fit_model))
```
出力）
SVR(C=1000, gamma=0.001)
10.922771453707899

##### LSTM
前処理を施したデータをこのLSTMを繋げたモデルに入力し、学習させた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1157150/ce9cf64e-f57c-4c4e-34ac-8dd4e1c0907a.png)
精度16.51
評価データセットでの精度は16.51であったのであまり良くない。
画像以外でディープラーニングを使ったのが初めてなので、知識が足りず、模倣したモデルなのでどこを触って良いのかがわからなかったのが反省点。


##### 特徴量抽出（ランダムフォレスト、ロジスティック回帰）
今回の解析は説明変数が少ないので特徴量を抽出しなくても解析ができそうだったので後半にやってしまいました。本当は可視化の次にするべきことだったので、反省です。今後はしっかりとした手順で解析に取り組んでいきます。

```` python
def RFC_train(train_X,train_y,test_X,test_y): 
    for_paramG = {'n_estimators':[1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
                  "criterion": ["gini", "entropy"],
                 "max_depth":[i for i in range(1, 3)],
                 }  #どのパラメータ探索 か決める
    #パラメータの探索
    RFC_grid = GridSearchCV(estimator=RandomForestClassifier(random_state=0), 
                            param_grid=for_paramG,scoring='neg_mean_absolute_error', cv=3) 
    RFC_grid.fit(train_X,train_y)
    best_est=RFC_grid.best_estimator_.n_estimators
    best_cri=RFC_grid.best_estimator_.criterion
    best_dep=RFC_grid.best_estimator_.max_depth
    print('グリッドサーチ・ランダムフォレストモデルにおける n_estimators   :  %d'  %RFC_grid.best_estimator_.n_estimators)
    print('グリッドサーチ・ランダムフォレストモデルにおける criterion   : '+RFC_grid.best_estimator_.criterion)
    print('グリッドサーチ・ランダムフォレストモデルにおける max_depth   :  %d'  %RFC_grid.best_estimator_.max_depth)
    print('グリッドサーチ・ランダムフォレストモデルによる予測値（平均誤差）   :  %.3f'  %mean_absolute_error(test_y, RFC_grid.predict(test_X)))
    #上で求めたパラメータを用いて特徴量の可視化を行う。
    RFC=RandomForestClassifier(random_state=0,n_estimators=best_est,criterion=best_cri,max_depth=best_dep)
    RFC.fit(train_X,train_y)
    for col,imp in zip(train_X.columns,RFC.feature_importances_):
        print(col,imp)
        
def Log_train(train_X,train_y,test_X,test_y):
    log_paramG={'C':[10 ** i for i in range(-5, 6)]}
    Log_grid=GridSearchCV(estimator=LogisticRegression(random_state=0),param_grid=log_paramG,scoring='neg_mean_absolute_error',cv=3)
    Log_grid.fit(train_X,train_y)
    best_c=Log_grid.best_estimator_.C
    print('グリッドサーチ・ロジスティック回帰モデルにおける　c:  %f' %best_c)
    print('グリッドサーチ・ロジスティック回帰モデルによる予測値（平均誤差）: %.3f' %mean_absolute_error(test_y,Log_grid.predict(test_X)))
    #上で求めたパラメータを用いてロジスティック回帰を行う
    LR=LogisticRegression(random_state=0,C=best_c)
    LR.fit(train_X,train_y)
    for col,coef in zip(train_X.columns,LR.coef_[-1]):
        print(col,coef)
````
```
RFC_train(X_train,y_train,X_test,y_test)
```
出力
グリッドサーチ・ランダムフォレストモデルにおける n_estimators   :  50
グリッドサーチ・ランダムフォレストモデルにおける criterion   : gini
グリッドサーチ・ランダムフォレストモデルにおける max_depth   :  2
グリッドサーチ・ランダムフォレストモデルによる予測値（平均誤差）   :  16.376
client 0.027684658305739154
close 0.3259602887051022
price_am 0.2871831132215565
price_pm 0.16733437774068471
Friday 0.026096796374157485
Monday 0.016076826193569968
Saturday 0.03651029222393821
Sunday 0.02428369170041409
Thursday 0.014582699445308623
Tuesday 0.03053321333474525
Wednesday 0.04375404275478384

```
Log_train(X_train,y_train,X_test,y_test)
```
出力
グリッドサーチ・ロジスティック回帰モデルにおける　c:  0.100000
グリッドサーチ・ロジスティック回帰モデルによる予測値（平均誤差）: 19.987
client -0.0010388282685728687
close -0.000842851407125532
price_am 0.39875813595169496
price_pm 0.3723323924369462
Friday -0.024789538391321073
Monday -0.019978110439689962
Saturday -0.05182341695864957
Sunday -0.03932198925089044
Thursday -0.02080712382648133
Tuesday 0.07871757806731301
Wednesday 0.07800427978307907

特徴量抽出を２つの手法で行いました。手法が違うと、重要な特徴量が変わってくる。この場合どちらの特徴量を採用すべきか、どのような解釈をするべきなのか、知識不足なのでわからず、「全部使ってちまえ！」となったのは反省点です。数式レベルで理解しないと解釈することが難しくなりますね。

##### xgboost
詳しく知らない手法ですが、kaggleなどの精度を競うコンペで多く使われていることから、今回使いました。ハイパーパラメータも知らないので、精度をあげる方法がわからず、記事の模倣をしただけになりました。
精度は14.74164　となりました。

### 振り返り

- 質的変数から量的変数を求めることをしたことがなく、質的変数の取扱方、この場合に強い予測モデルなど、完全に知識不足でした。
- データを可視化することでデータの形を見たかったのですが、質的変数を可視化して解釈するのは難しいことを知ることができました。
-　初めて、このような解析を行えたことで、数式の大切さを知ることができた。
-　いろんな記事を読むのも良いことだが、精度を上げるとなると、公式ドキュメントをしっかり読むのも大事！
-　個人で行なった解析だったので、狭い知識や、狭い考察をしてしまっているので、複数人で解析をしたくなった。
-　出力を解釈する。その解釈を助けるために何を吐き出させるか、何があったら助かるのか？ということを考えながら解析は行なったほうが良い。


##### ここで実行したコードはこちらの[github](https://github.com/jaguar2801/hikkoshi)にあります