Google Colaboratoryでファイルを読み込む
前回のエントリの続きになります。 uepon.hatenadiary.com
前回はGoogleColaboratoryを設定してみたものでした。ただ、これでは画像ファイルを認識させるために読み込ませるようなことができません。ネット上のサーバに置いておくという手もありますが、それもまた面倒です。ということで、その方法をググって見ました。
以下のエントリを参考にしています。ありがとうございます。
ファイルをインスタンスにアップロードする
簡単な方法はpythonのコードでnotebook上にUIを作り出し、ファイルをアップロードするというものです。 以下のようなコードを書いて実行すると…
from google.colab import files uploaded = files.upload()
notebook上にアップロード操作用のUIが現れます。 【ファイルの操作】ボタンをクリックするとファイル選択のダイアログが表示されますのでファイルを選択して【OK】をクリックしてください。
では以下のようなCSV(郵便番号データ)を読み込ませてみます。ファイル名は23AICHI.CSV
となります。
ファイル選択のダイアログでファイル名を選択し【OK】ボタンをクリックすると以下のようにnotebookが表示が変更します。
この操作では一応タイムアウト機能もあるようです。再生ボタンの周りがくるくる回っている間は問題ありませんが、タイムアウト後にファイルのアップロード操作を行おうとすると以下の様にアップロード状況などは表示されないようです。(ボタンなどを操作するとファイル操作ダイアログは表示され、ファイルの選択は行われますが、それ以上なにかされることはありません。)
【処理待ちの状態】
【タイムアウト後に操作してもなにも処理は発生しない】
ファイルが正常にアップロードされたかを確認するにはshコマンドで以下の様に実行すれば無事にアップロードされていることがわかります。
!ls -l
ちなみにインスタンスのデフォルトではless
コマンドはありませんし、more
コマンドでもエンコードがShift_JISのため?文字化けしています。
では、参考にしたエントリではcsvファイルをpandas
で読み込ませていたので自分もやってみます。(日本語なのでかなり不安ですが)
pandasは初めて使うので調べてみました。
Pandasは、プログラミング言語Pythonにおいて、データ解析を支援する機能を提供するライブラリである。特に、数表および時系列データを操作するためのデータ構造と演算を提供する。PandasはBSDライセンスのもとで提供されている。
Python Data Analysis Library — pandas: Python Data Analysis Library
ってことらしい、入力時の面倒くささを解決してくれるような感じなのかな? では実験です。
import pandas as pd import io data = pd.read_csv(io.StringIO(uploaded['sample.csv'].decode('utf-8')), header=-1) data.head()
おや?文字化けはするかなと思っていたのですが、エラーが発生しました。それも原因がファイル名。とはいえErrorが出たらStackOverFlowに検索にいけボタンがあるというのはすごいですね。
CSVファイルのエンコードをutf-8にしてしまえば、正常にいくかと思えば全く同じ状況でした。 怪しいのはファイル名の頭にある数字?あと小文字化も必要なのかなってことで以下の様にファイル名を変えてみました。 23AICHI.CSV → aichi.csv
これを変更してみると…more
も正常になりました。なんだろこれ?
先程のpandasのコードも以下のように修正して実行すると
import pandas as pd import io data = pd.read_csv(io.StringIO(uploaded['aichi.csv'].decode('utf-8')), header=-1) data.head()
うまくいきました。こんなところで引っかかるなんて…
【追記】
以下とすれば問題ありませんでした。
import pandas as pd import io data = pd.read_csv('23AICHI.CSV', header=-1) data.head()
GoogleDriveにあるディレクトリをマウントする
インスタンスへのディレクトリのマウントにはFUSE filesystem over Google Driveというものを使用します。
要約するとGoogleDriveのディレクトリをLinuxのファイルシステムにマウントするもののようです。
以下参考リンク。
↑これと同じことをそのまま行えばいいようです。
1)google-drive-ocamlfuseのインストール
インストールに必要となるパッケージも含めてインストールを行います。
# Install a Drive FUSE wrapper. # https://github.com/astrada/google-drive-ocamlfuse !apt-get install -y -qq software-properties-common python-software-properties module-init-tools !add-apt-repository -y ppa:alessandro-strada/ppa 2>&1 > /dev/null !apt-get update -qq 2>&1 > /dev/null !apt-get -y install -qq google-drive-ocamlfuse fuse
【実行の様子】
2)Colabratory用の認証トークンの生成
以下のコードを実行すると認証のリンクが表示され、リンク先に行って認証を行います。
# Generate auth tokens for Colab from google.colab import auth auth.authenticate_user()
【実行の様子】
実行するとリンクが表示されるので、それをブラウザの別タブで開き
対象となるユーザを選択し、
アクセスの許可を与えます。【OK】ボタンをクリックします。
すると、認証トークンが発行されるので、これをコピーして
colab側の入力ボックスにペーストしてEnterを押します。
3)Drive FUSE library用の証明書の生成
以下のコードを実行すると認証のリンクが表示され、リンク先で認証を行います。
# Generate creds for the Drive FUSE library. from oauth2client.client import GoogleCredentials creds = GoogleCredentials.get_application_default() import getpass !google-drive-ocamlfuse -headless -id={creds.client_id} -secret={creds.client_secret} < /dev/null 2>&1 | grep URL vcode = getpass.getpass() !echo {vcode} | google-drive-ocamlfuse -headless -id={creds.client_id} -secret={creds.client_secret}
【実行の様子】
実行するとリンクが表示されるので、それをブラウザの別タブで開き
対象となるアカウントを選択し、
Google Driveのアクセス許可を与えます。【OK】ボタンをクリックします。
すると、認証コードが発行されるので、これをコピーしてcolab側の入力ボックスにペーストしてEnterを押します。
認証が終わると以下のような状態になります。
4)インスタンスにdrive
というディレクトリを作り、そこにGoogle Driveをマウントする
# Create a directory and mount Google Drive using that directory. !mkdir -p drive !google-drive-ocamlfuse drive print('Files in Drive:') !ls drive/ # Create a file in Drive. !echo "This newly created file will appear in your Drive file list." > drive/created.txt
※ リンクそのままではPython2系のprintを使用しているのでPython3系に合わせる編集をしています。
【実行の様子】
5)マウントの確認
マウントされたGoogle Driveの状況をls
コマンドで確認してみるとこんな感じになります。
無事にマウントが行われたようです。
では先程のpandasを使ったcsvをオープンするコードでも確かめてみます。予めGoogleDriveに先程使用したcsvファイルを保存しておきます。
import pandas as pd import io data = pd.read_csv('drive/Colab Notebooks/aichi.csv', header=-1) data.head()
【実行の様子】
【注意点】 このマウントはインスタンスの永続限界時間である12時間を超えるとインスタンスが初期化されるためマウントも解除されてしまいます。 ファイルが削除されるわけではないので、再度インスタンスの接続を行ったらマウント処理を行うことを忘れないようにしてください。 アイドル状態が90分続くと停止しますが、12時間を超えていなければ大丈夫なのかなと思っています。
終わりに
tensorflowとKerasを使ってアップルとオレンジを判別するコードを実行してみます。
以前のエントリーで「AI Business Challenge Day:第4回 機械学習実践勉強会 画像認識技術ハンズオン」で使用したコードをGoogle Colabで動作させてみます。 画像はGoogle Driveに格納させています。
画像の格納されたパスの部分のみ変更していますが、基本的には同じです。
from keras.models import Sequential from keras.layers import Activation, Dense, Dropout from keras.utils.np_utils import to_categorical from keras.optimizers import Adagrad from keras.optimizers import Adam import numpy as np from PIL import Image import os image_list = [] label_list = [] basePath = "drive/Colab Notebooks/" # トレーニングデータを読み込む for dir in os.listdir(basePath + "data/train"): traindir = basePath + "data/train/" + dir if os.path.isdir(traindir) == False: continue label = 0 # 正解ラベル if dir == "apple": label = 0 # りんごの場合は、0 elif dir == "orange": label = 1 # オレンジの場合は、1 for file in os.listdir(traindir): if file != ".DS_Store": label_list.append(label) # 正解ラベルを配列に入れる filepath = traindir + "/" + file # ファイルパス resized_img = Image.open(filepath).resize((25, 25)) # 画像を25x25にリサイズする image = np.array(resized_img) # 25x25の2次元配列にする→[[R,G,B], [R,G,B]...] image = image.transpose(2, 0, 1) # 配列を次元を変換する→[[R,R,R,...], [G,G,G,...], [B,B,B,...]] image = image.reshape(1, image.shape[0] * image.shape[1] * image.shape[2]).astype("float32")[0] # 1次元配列に変換→[R,R,R,...,G,G,G,...,B,B,B] image_list.append(image / 255.) # 0.0〜1.0までの値にして配列に入れる image_list = np.array(image_list) # 画像リストをnumpy配列に変換 Y = to_categorical(label_list) # 正解ラベルを配列にする(0→[1,0], 1→[0,1]) # 層を構築 model = Sequential() # 入力層 model.add(Dense(200, input_dim=1875)) model.add(Activation("relu")) model.add(Dropout(0.2)) # 隠れ層 model.add(Dense(200)) model.add(Activation("relu")) model.add(Dropout(0.2)) # 出力層 model.add(Dense(2)) model.add(Activation("softmax")) # オプティマイザにAdamを使用 opt = Adam(lr=0.001) model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"]) # nb_epoch: 学習回数 # batch_size: 1度に処理する分量(GPUモードの際は、メモリ制限がある場合がある) model.fit(image_list, Y, nb_epoch=1500, batch_size=100, validation_split=0.1) # model.fit(image_list, Y, nb_epoch=10, batch_size=100, validation_split=0.1) total = 0. ok_count = 0. for dir in os.listdir(basePath + "data/test"): testdir = basePath + "data/test/" + dir if os.path.isdir(testdir) == False: continue label = 0 if dir == "apple": label = 0 # りんごの場合は、0 elif dir == "orange": label = 1 # オレンジの場合は、1 for file in os.listdir(testdir): if file != ".DS_Store": label_list.append(label) filepath = testdir + "/" + file resized_img = Image.open(filepath).resize((25, 25)) image = np.array(resized_img) image = image.transpose(2, 0, 1) image = image.reshape(1, image.shape[0] * image.shape[1] * image.shape[2]).astype("float32")[0] # 予測する print(filepath) result = model.predict_classes(np.array([image / 255.])) print("label:", label, "result:", result[0]) total += 1. if label == result[0]: ok_count += 1. print(ok_count / total * 100, "%")
【実行の様子】
(略)
問題なく動いたようです。 インスタンスのマシンスペックの凄さはあんまりわかりませんでしたが、セットアップをほとんどしなくてもここまでできるのは本当に嬉しいことです。
【関連エントリー】