はじめに
勉強の為、Pythonでデータ分析を使ってみました。
データ分析の練習の為、SIGNATEの【練習問題】お弁当の需要予測を試してみました。
【練習問題】お弁当の需要予測
https://signate.jp/competitions/24
この練習問題は、お弁当の売れ残り対策の為、お弁当の需要予測を行うという内容で、
曜日、天気、温度等の要因が販売個数とどんな関係があるか分析し、お弁当の需要を予測しましょうという内容となっています。
SIGNATE
SIGNATE は、2018年4月にオープンしたAI開発コンペティションサイトです。 データ分析に関するコンペティションを開催しており、好成績を残したデータサイエンティストは賞金や実績、データを提供した企業や団体は最適な分析結果が得られます。
環境
Python本体をダウンロードし、インストールします。
バージョンは3.9.0を使用しました。
Pythonとは1991年にオランダ人のグイド・ヴァンロッサムというプログラマーによって開発され、オープンソースで運営されているプログラミング言語です。
データ解析に使うライブラリの一式が入ったツールキットをダウンロードし、インストールします。
ツールキットの中にエディタも入っており、仮想環境を作成して、その上でPythonを動かすこともできます。
また、データ解析に使用するパッケージが用意されていて、とても便利で簡単です。
世界中に2500万人以上のユーザーがいる、オープンソースのIndividual Edition(Distribution)は、Python / Rデータサイエンスと機械学習を1台のマシンで実行する最も簡単な方法です。個人開業医向けに開発されたこのツールキットは、何千ものオープンソースパッケージやライブラリを操作できるようにするためのものです。
データ解析をしてみる
今回は、勉強の為にデータ解析に触れてみるだけでソースはほぼお借りしてきたものを流用しています。
それでも、内容の理解の為に調べることが多すぎて中々時間が足りなくなりました。
また、内容について詳細を調べると難しいものが多く勉強したものを紹介する内容となっています。
データ解析
まずはデータ解析に使うデータを用意します。
【練習問題】お弁当の需要予測
必要なデータは、SIGNATEのページに用意されており、2つのCSVファイルをダウンロードします。
・train.csv
学習用データ期間:2013年11月18日 ~ 2014年 9月30日
'y'が目的変数で販売個数になります。
(例)
日時 | y | 週 | 売り切れ | 名前 | kcal | 備考 | イベント | 給料日 | 天気 | 降水量 | 気温 |
---|---|---|---|---|---|---|---|---|---|---|---|
2013-11-18 | 90 | 月 | 0 | 厚切りイカフライ | 快晴 | -- | 19.8 | ||||
2013-11-19 | 101 | 火 | 1 | 手作りヒレカツ | 快晴 | -- | 17.0 | ||||
2013-11-20 | 118 | 水 | 0 | 白身魚唐揚げ野菜あん | 快晴 | -- | 15.5 | ||||
2013-11-21 | 120 | 木 | 1 | 若鶏ピリ辛焼 | 快晴 | -- | 15.2 | ||||
2013-11-22 | 130 | 金 | 1 | ビッグメンチカツ | 快晴 | -- | 16.1 |
・test.csv
評価用データ期間:2014年10月 1日 ~ 2014年11月30日
このデータに対して評価用データ期間の販売個数を予測します。
ライブラリ・モジュールのインポート
・pandas
データ分析に使用するライブラリ
#pandasをインポート
import pandas as pd
・sklearn
Pythonの機械学習ライブラリ
#Pythonの機械学習ライブラリからデータを切り分けるモジュールをインポートする。
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression,Ridge
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor,GradientBoostingRegressor
・Pipeline
何重にも重なる処理を、わかりやすく表現する機能。
#Pipelineをインポートします。
from sklearn.pipeline import Pipeline
・r2_score
機械学習ライブラリのscikit-learnのr2_score関数を使います。
r2_score関数は決定係数といい、データ解析のモデルの当てはまりの良さを示す指標で、最も当てはまりの良い場合、1.0 となります。
#r2_scoreをインポートします。
from sklearn.metrics import r2_score
データ解析用のCSVを読み込み、データを加工する。
ここから実際にデータ解析に使用するデータの読み込みを行います。
#CSVからデータを取得
#弁当データCSV(学習用データ期間:2013年11月18日 ~ 2014年 9月30日)
train = pd.read_csv('bento_train.csv')
#テストデータCSV(評価用データ期間:2014年10月 1日 ~ 2014年11月30日)
test = pd.read_csv('bento_test.csv')
目的変数である'y'を
#弁当データCSVから目的変数である'y'をCSVデータの表から削除し、変数trainXに代入。
trainX = train.drop('y', axis=1)
#弁当データCSVから目的変数である'y'のデータを変数'y'に代入。
y = train['y']
#予測するデータのCSVを読み込みます。
testX = test.copy()
```python:sample.py
#学習用CSVデータの使用しないカラムとデータを削除する。
trainX = trainX.drop(['remarks', 'event', 'payday', 'name', 'precipitation', 'datetime' ], axis=1)
testX = testX.drop(['remarks', 'event', 'payday', 'name', 'precipitation', 'datetime' ], axis=1)
#"kcal"の平均値(mean)で値の入っていないデータを補填する。
trainX["kcal"] = trainX["kcal"].fillna(trainX["kcal"].mean())
testX["kcal"] = testX["kcal"].fillna(testX["kcal"].mean())
データ解析ライブラリのpandasを使用してダミー変数を作成する。
読み込んだCSVデータ内の曜日と天気を数字に変換しています。
#ダミー変数を作成するカラムをリストにする。
dummy_colums = ['week','weather']
#trainXのカラムに対してダミー変数を作成する。
trainX = pd.get_dummies(trainX, dummy_na=False, columns=dummy_colums)
#testXのカラムに対してダミー変数を作成する。
testX = pd.get_dummies(testX, dummy_na=False, columns=dummy_colums)
データ分析処理
Pandas、sklearnを用いて回帰分析を行います。
1つ1つの説明が長すぎて書ききれないので紹介だけします。
詳細は参考文献を参照してください。
・ols (Pandas)
最小二乗法(OLS: Ordinary Least Squares) 誤差の二乗が最も小さくなるようにする。
・Ridge (sklearn)
リッジ回帰「L2正則化(またはRidge)」とは、特に正則化項(罰則項)として「L2ノルム」を採用した正則化のこと
機械学習において、過剰に学習させてしまう過学習を抑制する効果がある。
正則化とは機械学習において、モデルの過学習を抑えるために損失関数(誤差関数)に正則化項を導入する手法のこと。
・DecisionTreeRegressor(sklearn)
決定木分析 (Decision Tree Analysis) は、機械学習の手法の一つで決定木と呼ばれる、木を逆にしたようなデータ構造を用いて分類と回帰を行います。
・RandomForestRegressor(sklearn)
複数の決定木を使って各決定木の予測結果の多数決で結果を求める方法です。
・GradientBoostingRegressor(sklearn)
勾配ブースティング回帰という手法、難しすぎて説明はできないので参考資料を参照ください。
# pipelineを使用して、データ分析を行う。
pipelines = {
'ols': Pipeline([('scl',StandardScaler()),
('est',LinearRegression())]),
'ridge':Pipeline([('scl',StandardScaler()),
('est',Ridge(random_state=0))]),
'tree': Pipeline([('scl',StandardScaler()),
('est',DecisionTreeRegressor(random_state=0))]),
'rf': Pipeline([('scl',StandardScaler()),
('est',RandomForestRegressor(random_state=0))]),
'gbr1': Pipeline([('scl',StandardScaler()),
('est',GradientBoostingRegressor(random_state=0))]),
'gbr2': Pipeline([('scl',StandardScaler()),
('est',GradientBoostingRegressor(n_estimators=200,
random_state=0))])
}
# 機械学習を実行する。
scores = {}
for pipe_name, pipeline in pipelines.items():
pipeline.fit(X_train, y_train)
scores[(pipe_name,'train')] = r2_score(y_train, pipeline.predict(X_train))
scores[(pipe_name,'test')] = r2_score(y_test, pipeline.predict(X_test))
# 機械学習結果の表示
test train
gbr1 0.703323 0.945273
gbr2 0.672755 0.981484
ols 0.305589 0.523082
rf 0.630820 0.954129
ridge 0.328230 0.522096
tree 0.426131 1.000000
#機械学習モデルを作成する
model = GradientBoostingRegressor()
model.fit(trainX, y)
データ解析結果
データ解析結果の表示
#データ解析結果
pred = model.predict(testX)
#目的変数:販売予測個数の表示
[ 70.53448298 65.18182648 72.74002415 68.84283309 61.25705554
57.47444883 62.03288102 69.23002959 56.65529706 112.29291597
70.65305346 67.25483235 75.78145572 70.25964217 110.69620083
104.56811264 72.94582533 68.92227057 73.39214705 69.3901024
62.55510811 70.75695636 77.06749736 113.91819978 62.13074626
70.29577602 66.89244724 111.60799719 114.53484058 60.77451103
91.9875916 131.79963899 113.6323069 109.66488392 116.62545708
95.00540798 117.70979352 117.96092206 104.16261241 94.09085023]
・上記で作成した内容をtest.csvの内容と合わせて表にすると以下のようになります。
以下の表は、不要なカラムを省いています。
年月日 | 販売予想個数 | 曜日 | お弁当名 | 天気 | 温度 |
---|---|---|---|---|---|
2014/10/1 | 70.53448298 | 水 | メンチカツ | 雨 | 20.2 |
2014/10/2 | 65.18182648 | 木 | バーベキューチキン | 曇 | 23.9 |
2014/10/3 | 72.74002415 | 金 | 豚肉のマスタード焼き | 晴れ | 28.7 |
2014/10/6 | 68.84283309 | 月 | 麻婆春雨 | 雨 | 21.5 |
2014/10/7 | 61.25705554 | 火 | 厚揚げ肉みそ炒め | 晴れ | 22.1 |
2014/10/8 | 57.47444883 | 水 | 完熟トマトのホットカレー | 晴れ | 23.3 |
2014/10/9 | 62.03288102 | 木 | 豚キムチ炒め | 曇 | 22.5 |
2014/10/10 | 69.23002959 | 金 | ポークカレー | 薄曇 | 26.1 |
2014/10/14 | 56.65529706 | 火 | 若鶏梅肉包揚げ | 快晴 | 26.8 |
2014/10/15 | 112.292916 | 水 | ミックスグリル | 雨 | 15.6 |
2014/10/16 | 70.65305346 | 木 | 豚肉と白菜の中華炒め | 晴れ | 18.6 |
2014/10/17 | 67.25483235 | 金 | ヒレカツ | 快晴 | 23 |
2014/10/20 | 75.78145572 | 月 | 豚柳川 | 薄曇 | 23.9 |
2014/10/21 | 70.25964217 | 火 | ポーク生姜焼き | 雨 | 20.2 |
2014/10/22 | 110.6962008 | 水 | 麻婆豆腐 | 雨 | 15.5 |
2014/10/23 | 104.5681126 | 木 | ビーフストロガノフ | 雨 | 14.7 |
2014/10/24 | 72.94582533 | 金 | 唐揚げ丼 | 快晴 | 18.7 |
2014/10/27 | 68.92227057 | 月 | マス塩焼き | 薄曇 | 22.7 |
2014/10/28 | 73.39214705 | 火 | チンジャオロース | 快晴 | 19.1 |
2014/10/29 | 69.3901024 | 水 | 厚切イカフライ | 快晴 | 19.6 |
2014/10/30 | 62.55510811 | 木 | 鶏肉と野菜の黒胡椒炒め | 晴れ | 19.6 |
2014/10/31 | 70.75695636 | 金 | 八宝菜 | 曇 | 18.8 |
2014/11/4 | 77.06749736 | 火 | 豚肉の生姜焼き | 晴れ | 18.9 |
2014/11/5 | 113.9181998 | 水 | ハンバーグ | 曇 | 16 |
2014/11/6 | 62.13074626 | 木 | 彩り野菜と鶏肉の黒酢あん | 曇 | 19.2 |
2014/11/7 | 70.29577602 | 金 | ポークカレー | 晴れ | 20.1 |
2014/11/10 | 66.89244724 | 月 | 親子煮 | 快晴 | 21.2 |
2014/11/11 | 111.6079972 | 火 | ポークのバーベキューソテー | 曇 | 14.7 |
2014/11/12 | 114.5348406 | 水 | 鶏肉の唐揚げ | 曇 | 14.4 |
2014/11/13 | 60.77451103 | 木 | 白身魚味噌焼き | 快晴 | 19.5 |
2014/11/14 | 91.9875916 | 金 | エビフライ・エビカツ | 快晴 | 15.8 |
2014/11/17 | 131.799639 | 月 | 野菜ごろごろシチュー | 薄曇 | 14.3 |
2014/11/18 | 113.6323069 | 火 | 麻婆豆腐 | 快晴 | 16.1 |
2014/11/19 | 109.6648839 | 水 | ベルギー風チキンのクリーム煮 | 快晴 | 14.9 |
2014/11/20 | 116.6254571 | 木 | スタミナ炒め | 曇 | 10.5 |
2014/11/21 | 95.00540798 | 金 | ロコモコ丼 | 快晴 | 14.9 |
2014/11/25 | 117.7097935 | 火 | なすと挽肉のはさみ揚げ | 雨 | 11.4 |
2014/11/26 | 117.9609221 | 水 | 鶏肉の治部煮風 | 雨 | 9.2 |
2014/11/27 | 104.1626124 | 木 | 牛丼風 | 快晴 | 15.1 |
2014/11/28 | 94.09085023 | 金 | 鶏肉のスイートチリソース | 曇 | 15.3 |
まとめ・感想
初心者がデータ解析に触ってみたということで、内容はお借りしてきたものが多く、書いている間は何をしているのか調べるのが9割でしたが、それでも難しく最後の表に当てはめるまで出来てよかったとホッとするくらいで、内容の理解が追い付いていない状態です。
はじめにPythonについて何ができるのか調べたところ、人工知能やデータ解析ができ、シンプルなコードで読みやすいとあったのでテーマに選びました。
しかし、データ解析は調べれば調べるほど難しい内容となっていて、ちゃんと勉強するなら数カ月はかかるものじゃないかと思うような難易度で、気軽にやってみようというものではなかったです。
参考文献
・Pythonとは?特徴やできること・人気の理由を初心者向けに解説
https://www.sejuku.net/blog/7720
・データ分析のライブラリ!Pandasとは【初心者向け】
https://techacademy.jp/magazine/17697
・Scikit-learnとは?データ分析や機械学習に欠かせないScikit-learnのメリットや機能まとめ
https://ai-kenkyujo.com/scikit-learn/
・[SIGNATE練習問題]お弁当の需要予測をやってみた
https://nanjamonja.net/archives/46#i-4
・Pandasでダミー変数を作成するget_dummies関数の使い方
https://deepage.net/features/pandas-get-dummies.html
・Pandasで最小二乗法(ols)を使った回帰を行う方法
https://deepage.net/features/pandas-ols.html
・【初学者向け】L2正則化をわかりやすく解説【リッジ回帰】
https://mathmatical22.xyz/2019/09/23/%E3%80%90%E5%88%9D%E5%AD%A6%E8%80%85%E5%90%91%E3%81%91%E3%80%91l2%E6%AD%A3%E5%89%87%E5%8C%96%E3%80%90%E3%83%AA%E3%83%83%E3%82%B8%E5%9B%9E%E5%B8%B0%E3%80%91/
・超入門!リッジ回帰・Lasso回帰・Elastic Netの基本と特徴をサクッと理解!
https://aizine.ai/ridge-lasso-elasticnet/#toc1
・scikit-learn で決定木分析 (CART 法)
https://pythondatascience.plavox.info/scikit-learn/scikit-learn%E3%81%A7%E6%B1%BA%E5%AE%9A%E6%9C%A8%E5%88%86%E6%9E%90
・機械学習手法「ランダムフォレスト」でクラス分類にチャレンジしよう
https://www.sejuku.net/blog/64455
・勾配ブースティング回帰木を使用した回帰分析
https://jpn.nec.com/hpc/sxauroratsubasa/column/012.html
・勾配ブースティング回帰の実践的な説明
https://ichi.pro/kobai-bu-suthingu-kaiki-no-jissenteki-na-setsumei-5290993901470