ColaboratoryでCSVを読み込ませてTPU使ってkerasで文章判別モデルを構築してみた

# Colabで高速なTPU使って自然言語処理&深層学習する
##目的
TPUを使って高速に、クラウドソーシングで集めた教師データ(文章とラベルのセットデータ)をLSTMで学習させたい
## 流れ
1.データをCSVでアップロードし、pandasで形を整える
2.mecabを用いて文章を形態素解析する
3.Word2Vecで単語ベクトルに変換する
4.kerasでLSTMモデルの構築、TPUで学習させる



*注意：単語分散表現、単語ベクトルなどの専門用語はわかりやすいように統一している部分があり、間違いなく記述しているわけではありません。おおよその概要を掴めていただければ幸いです。
*注意：チュートリアルではないので、データなどのご用意はありません

## 1.データをCSVでアップロードし、pandasで形を整える

まずは学習させる教師データを用意します。今回はクラウドソーシングで集めた教師データが詰まったCSVをアップロードします。結構めんどくさいですが、以下のコードで出来ます


```
#まず、諸々をinstallして認証する
!pip install -U -q PyDrive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials
auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)


```
認証ができたら、次にアップロードしたいファイルをGoogleDriveにアップロードしたのち、共有リンクを取得します

```
#読み込む時は共有リンクを取得しなければならない
!pip install -U -q numpy
!pip install -U -q pandas
import numpy as np
import pandas as pd
#共有リンクのうち、id=~~~~~~の文字列をコピペ
id = ‘~~~~~~'
downloaded = drive.CreateFile({'id': id})
downloaded.GetContentFile(‘data.csv')
df_data = pd.read_csv(“data.csv",encoding='cp932',header=None)
df_data = df_data.drop(0,axis=0).drop(1,axis=1)
df_data = df_data.drop(0,axis=1)
columns = df_data.iloc[0].values
```


これでCSVをアップロードし、pandasで形を整えることができました。
numpyやpandasなどのライブラリを使用する際には、!pip install -U -q *****でインストールしなければいけないのは注意点ですね。



##2.mecabを用いて文章を形態素解析する
文章をディープラーニングの入力データとするには、少し注意が必要です。
なぜなら、文章は文字というシンボルの連なりであり、そのシンボル一つ一つは意味を持ちません。
例えば「火」「炎」というそれぞれの文字は、文字コードがUTF-8の場合、「E781AB」「E7828E」という文字コードに変換され、処理されます。人間が「火」と「炎」という文字を見た際に、「同じような意味だな」と考えることができますが、コンピュータは文字を文字コードに変換しているため、人間と同じように**単語の意味**を理解することができないのです。

**単語の意味を理解できないので、文章の意味ももちろん理解することはできません。**

そこで考えられたのが、単語の意味を数値化した**単語ベクトル**です。単語の意味を数値化すれば、「火」と「炎」という意味の近い単語は、近しい数値が出てきます。単語を単語ベクトルに変換する方法はいくつも考えられてきましたが、革新的な発想で、極めて高い精度で単語ベクトルを獲得できる**Word2Vec**が世界中の研究者を驚愕させました。(開発者自身もその力に驚愕したそうです)

今回は、文章を単語に分割する形態素解析を行える、Mecabと、単語ベクトルに変換できるWord2Vecを組み合わせて文章ベクトルを作っていきます。(単語ベクトルの連なりなので、文章ベクトルです。単語に分割せずいきなり文章ベクトルを取得する、**skip-thought vectors**などもあります)



それでは、mecabで文章を形態素解析していきます。mecabを使うための準備がちょっと面倒です


```
#mecabのインストール
!apt install aptitude
!aptitude install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file -y
!pip install mecab-python3
import MeCab
tagger = MeCab.Tagger('-Owakati')
```

```
#形態素解析用のメソッドを定義
!pip install -U -q re
import MeCab
import re

def tokenize(text):
    wakati = MeCab.Tagger("-O wakati")
    wakati.parse("")
    words = wakati.parse(text)

    # Make word list
    if words[-1] == u"\n":
        words = words[:-1]

    return words
```

```
#実際に形態素解析！
texts = df_data.iloc[1:]
tokenized_texts = [tokenize(a) for a in texts]
```



これで形態素解析が完了しました。
次にWord2Vecを用いて単語ベクトルに変換していきましょう
Word2Vecは学習済みのものを用いています。


##3.Word2Vecで単語ベクトルに変換する
```
#必要な3ファイルの読み込み
!pip install -U -q gensim
from gensim.models import word2vec
id = ‘~~~~~~~~~~~'  # 共有リンクで取得した id= より後の部分
id2 = ‘-----------'
id3 = ‘¥¥¥¥¥¥¥¥¥¥¥¥'
downloaded = drive.CreateFile({'id': id})
downloaded.GetContentFile('wiki.model.zip')
!unzip wiki.model.zip
downloaded2 = drive.CreateFile({'id': id2})
downloaded2.GetContentFile('wiki.model.syn1neg.npy.zip')
!unzip wiki.model.syn1neg.npy.zip
downloaded3 = drive.CreateFile({'id': id3})
downloaded3.GetContentFile('wiki.model.wv.syn0.npy.zip')
!unzip wiki.model.wv.syn0.npy.zip

model = word2vec.Word2Vec.load("wiki.model")
```


これでWord2Vecのロードができました

次に、Word2Vecを用いて単語を単語ベクトルに変換していきます。
ここで、Word2Vecの語彙辞書の中にないものは、未知語とするために、unknown_tokenを設定しています

```
unknown_token = np.random.random_sample(200)
context_vectors = []
for str in tokenized_text:
    context_vector = []
    for char in m.removeStoplist(str, []).split(" "):
        try:
            context_vector.append(model[char])
        except KeyError:
　　　　　　　context_vector.append(unknown_token)
    context_vectors.append(word_vectors)
```


これで単語ベクトルの連なり(文章ベクトル)に変換することができました



##4.kerasでLSTMモデルの構築、TPUで学習させる

kerasで、TPUを使用するには、少し工夫が必要になります。
いくつかのモジュールをインポートし、

```
TPU_WORKER = "grpc://" + os.environ["COLAB_TPU_ADDR"]
strategy = tf.contrib.tpu.TPUDistributionStrategy(
    tf.contrib.cluster_resolver.TPUClusterResolver(TPU_WORKER)
)

tpu_model = tf.contrib.tpu.keras_to_tpu_model(
    model,
    strategy=strategy
)
```

をする必要があります。



kerasでLSTMを構築した後、TPU用のモデルに変換していきます

```
!pip install -U -q matplotib
!pip install -U -q keras
!pip install -U -q os
import numpy as np
import matplotlib.pyplot as plt
import os
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dropout, Dense, Activation, LSTM
from tensorflow.keras.optimizers import Adam, RMSprop
from tensorflow.keras.callbacks import EarlyStopping
from sklearn.model_selection import train_test_split
from sklearn.utils import shuffle
from tensorflow.keras import backend as K 
np.random.seed(0)




N_train = int(len(input_data) * 0.8)
N_validation = len(input_data) - N_train

print(input_data.shape,output_data.shape, len(data[2]))
X_train, X_validation, Y_train, Y_validation, row_train, row_validation = \
    train_test_split(input_data, output_data, data[2], test_size=N_validation)


maxlen = 25
'''
モデル設定
'''
n_in = 200  
n_hidden = 512
n_out = 1


def weight_variable(shape, name=None):
    return np.random.normal(scale=.01, size=shape)

model = Sequential()
model.add(LSTM(n_hidden,
               recurrent_dropout=0.5,
               kernel_initializer='he_uniform',
               input_shape=(maxlen, n_in)))
model.add(Dense(n_out, kernel_initializer='he_uniform'))


model.summary()
# optimizer = Adam(lr=0.0010, beta_1=0.9, beta_2=0.999)
optimizer = RMSprop(lr=0.0005, rho=0.9, epsilon=None, decay=0.0)
model.compile(loss='mean_squared_error',optimizer=optimizer)
TPU_WORKER = "grpc://" + os.environ["COLAB_TPU_ADDR"]
strategy = tf.contrib.tpu.TPUDistributionStrategy(
    tf.contrib.cluster_resolver.TPUClusterResolver(TPU_WORKER)
)

tpu_model = tf.contrib.tpu.keras_to_tpu_model(
    model,
    strategy=strategy
)
```


構築が済みましたので、学習をさせていきます。

```
epochs = 300
batch_size = 128
tpu_model.fit(X_train, Y_train,
          batch_size=batch_size,
          epochs=epochs,
          validation_data=(X_validation, Y_validation))
```



これで学習が進みます。普段はMacbook pro 2016年モデルを使っていますが、かかる時間は1/100以下になりました。本当にTPUすごい。
なかなかTPUを使うために面倒臭い工程が必要にはなりますが、ぜひ試してみてください。

今回はモデル評価については割愛します〜　
読んで頂き、ありがとうございました。お役に立てていれば幸いです



以下参考にしたサイト様になります！
[無料でColaboratoryからTPUを試してみる](https://qiita.com/namakemono/items/a6c4e84375c810240a25)
[google Colaboratoryでファイルを読み込む方法](https://qiita.com/uni-3/items/201aaa2708260cc790b8)
[Google Colaboratory内で画像やCSVファイルにアクセスするのが一苦労だった話](https://qiita.com/yoshizaki_kkgk/items/bf01842d1a80c0f9e56c)
[https://qiita.com/5at00001040/items/d7867974d2fd1d21dbbf](https://qiita.com/5at00001040/items/d7867974d2fd1d21dbbf)