基本的な機械学習手法でもGoogleAnalyticsデータは分析できる！

## 目標
本記事の目標は終了済みのKaggle「[Google Analytics Customer Revenue Prediction](https://www.kaggle.com/c/ga-customer-revenue-prediction)」で良い結果を導き出すことになります。  
本コンペティションは2年前に行われたテーマになります。  
よく練習用で実施されている「[Titanic - Machine Learning from Disaster](https://www.kaggle.com/c/titanic)」とかはQiitaでも実施したという記事が多く存在するため、日本で情報が少ないコンペティションをやってみようと思いました。  
チュートリアルのKaggle「Titanic」など基本的なコンペティションはやったことはあるけども、あまり他のコンペティションに手を付けていないという方に向けて、基本的な手法で他の機械学習に適用できるかを見ていきます。  

## 基本的な機械学習(Kaggle)の手法とは
__1. データの読み込み__ 
　形式は色々ですがcsvが多いです。
__2. データの確認__ 
　データの中身を確認し処理の方針を決定します。
__3. データの前処理__ 
　数値への変換や欠損値処理、変数追加がここにあたります。
__4. モデルの生成・評価__ 
　前処理したデータをもとにモデルの作成をし、結果を確認します。

今回もやることはほぼ同じですが、これらを発展させた少し応用的な内容となっております。 
弊社のメンバーが行った初心者向けのKaggle実践記事も参考にしてみてください。    
https://qiita.com/takuya_tsurumi/items/bfd667065f482bbd9aba

## 今回利用するデータはGoogle Analytics
本コンペティションで扱うデータはGoogle Analyticsになります。  
Google AnalyticsとはGoogleが提供するWebサイトアナリティクスサービスで、
サイトにトラッキングコードを埋め込むことで、Googleが提供するWebサイトBIサービスにて顧客の情報を可視化できます。  
以下は「UA - Google Merchandise Store」のデモアカウントによるデータになります。(誰でも見ることができます)
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189481/1e2c678c-2208-aede-1505-abf4aab05b83.png)


今回使用する訓練データには以下のデータなどが含まれ、csv形式で提供されています。  

|データ(一部) |説明 |
|----|----|  
|トラフィック |ウェブサイトを訪問したユーザーの流入元に関する情報。検索など。 |  
|デバイス | ブラウザやOSなどの情報 |  
|地域情報 |IP情報に基づいたデータ|
|コンテンツ データ|サイト内でのユーザーの行動に関する情報。ユーザーが閲覧したページの URL、コンテンツの利用状況などを確認できます。|
|トランザクション データ|ウェブサイトで発生したトランザクションに関する情報。|
 
また上記データの内、デバイスや地域情報やトランザクションにはjson形式で値が入っており、内部でまた細かいデータが入っております。

## 実践  
### 1. データ読み込み  
基本はpythonのライブラリpandasのread_csvにて読み込むのですが、苦戦した点が2点ありました。  
**①肝心なtrainデータが24GBでメモリ不足に陥る**
 → chunksizeを指定してメモリが枯渇しないよう大きなデータを分割しながら読み込みます。
　以下のようにメモリエラーとなった場合、要注意です。
![MemoryError.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189481/766b1acd-84e5-d66e-0dda-2f575f2d309e.png)

**②分析用csv内部のjsonのままでは分析ができない**
今回のデータでは1カラム内にjson文字列として複数の情報が入っている形式で格納されておりました。そのままではただの文字列なのでそのままでは分析対象にはできませんでした。
 → 以下のコードのようにconvertersを用いて内部jsonを１つ１つのデータとして分割して分析できるように変換します。  

```python
pd.read_csv(csv_path, sep=',',
    converters={column: json.loads for column in ['device', 'geoNetwork', 'totals', 'trafficSource']}, 
    dtype={'fullVisitorId': 'str'},
    chunksize=200000)
```  

### 2. データ前処理

前処理として実施した事項は以下の3つです。

 - null補完 
 - 日付分解
 - ラベルエンコーディング

**null補完**
   数値データは0埋め

```python
all_data['totals.newVisits'].fillna(0, inplace=True)
```  
   文字列データはunknown埋め

```python
all_data['trafficSource.adContent'].fillna('unknown', inplace=True)
```

**日付分解**
8桁の数字を年・月・日・曜日にして格納(20200318 → 2020 03 18 水)  

```python
all_data['trafficSource.adContent'].fillna('unknown', inplace=True)
```

**ラベルエンコーディング**
    LightGBMはint float booleanにしか対応していないため、scikit-learn の LabelEncoder を使って数値に変換します。  

```python
from sklearn.preprocessing import LabelEncoder
lbl = LabelEncoder()
all_data[device.browser] = lbl.fit_transform(list(all_data[device.browser]))
```

### 3. 集計変数追加  
今回出力しなければいけない結果はfullVisitorIdごとのtotals.transactionRevenueの合計となります。よって機械学習において入れるデータも全てfullVisitorIdごとに集計しなければなりません。  
基本的には合計(sum)を見ますが、機械学習としては何が最終結果に影響するかわからないため、平均(mean)、最大(max)も一緒に取得するように工夫しております。  
実施する際に工夫した点は以下2つです。

**①数値データがトランザクションごとのデータなので、ユーザー単位で集計する必要があります。**

total.hitsを一例にしますと

```python 
train_group = train.groupby(['fullVisitorId'])
train_group[totals.hits].agg(['mean', 'max', 'sum']).reset_index()
```

**②カテゴリデータ(文字列)は一番初めの値を参照します。**

```python
train_group[device.browser].first().reset_index()
```

実際は数値カラム、カテゴリカラムをまとめて実施し、最終的に全てのカラムにおいて上記処理の結果を結合します。
    
## 使用モデル
Kaggleでよく使われている機械学習モデルに倣ってLightGBMを使用

```python
params={'learning_rate': 0.01,
        'objective':'regression',
        'metric':'rmse',
        'num_leaves': 31,
        'verbose': 1,
        'random_state':42,
        'bagging_fraction': 0.6,
        'feature_fraction': 0.6
}
```

## 結果
Private Score 0.88457となりました。 
 ![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189481/2fd42858-9757-f35c-fd7c-2aadc8b68f07.png)

当時のコンペティションの1位が0.88140いう数値だったため、そこまで悪くない数値になったのではないかと思います。  
基本的な機械学習処理を応用することで、他の機械学習事項にも正しく適用できることを示せたのではないかと思います。  
KaggleにおいてTutorialしか行っていないという方も色々と探して応用すればできるものも結構存在しますので、挑戦してみてはいかがでしょう。