ロジスティック回帰による分類
機械学習における「分類」では、複数のグループに分類された教師データから母集団におけるグループの分布をモデル化し、未知の入力がどのグループに属するのかを推定します。ここでは、太宰治と宮澤賢治の青空文庫から引用した小説の書き出し部分を教師データとして与え、未学習の小説の書き出しに対して著者を分類するモデルを構築します。
本サンプルプログラムでは、BluemixのObject Storageへデータファイルを配置し、Object Storage上のファイルからRDDを生成します。そこで、まずはじめにBluemixでのApache SparkサービスとObject Storageサービスの連携方法について解説します。
Object Storageサービスをデータソースとして追加するには、まずNotebook右のPaletteから[Data Sources]を選択します。そこから[Add Source]ボタンをクリックするとfig11のようなダイアログが表示されるので、[Create or connect to an Object Storage ...]というリンクをクリックし、遷移先でさらに[Add Object Storage]をクリックすると、fig12のObject Storage選択画面が表示されます。既存のBluemixやSoftLayerのObject Storageも選択できますが、今回は5GBまで無料で利用できるFreeプランを選択してObject Storageサービスを新しく生成します。コンテナ名は「notebooks」としておいてください。
Object Storageの追加が終わったあと、再びNotebookに戻りPaletteの[Data Source]から[Add Source]を選択すると、今度はファイルをアップロードできるようになります。list5とlist6の内容をそれぞれ「dazai.txt」と「miyazawa.txt」として保存し、Object Storageへアップロードしてください。
メロス は 激怒 した 必ず かの 邪智 暴虐 の 王 を 除か なければ ならぬ と 決意 した メロス には 政治 が わからぬ 昔 の 話 で ある 須々木 乙彦 は 古着屋 へ はいって 君 の ところ に 黒 の 無地 の 羽織 は ないか と 言った これ は れい の 飲食店 閉鎖 の 命令 が 未だ 発せ られない 前 の お話 で ある 新宿 辺 も こんど の 戦火 で 朝 食堂 で スウプ を 一さじ すっ と 吸って お母さま が あ と 幽 な 叫び 声 を お挙げ に なった 或る とし の 春 私 は 生れて はじめて 本州 北端 津軽 半島 を 凡そ 三週間 ほど かかつて 一周 した ので あるが
オツベル と きたら 大した もんだ 稲扱 器械 の 六台 も 据え つけて のんのんのんのんのんのん と 大そろ しない 音を たてて やっている をかし な はがき が ある 土曜日 の 夕がた 一郎 の うち に きました では みなさん は そういう ふうに 川 だと 言われ たり 乳 の 流れた あと だと 言われ たり していた この ぼんやり と 白い もの が ほんとう は 何 か ご承知 ですか グスコーブドリ は イーハトーヴ の 大きな 森 の なか に 生まれ ました おとうさん は グスコーナドリ と いう 名高い 木こり で どんな 大きな 木 でも まるで 赤ん坊 を 寝かし つける ように わけ なく 切って しまう 人 でした 二人 の 若い 紳士 が すっかり イギリス の 兵隊 の かたち を して ぴかぴか する 鉄砲 を かついで 白熊 の ような 犬 を 二疋 つれて だいぶ 山奥 の 木の葉 の かさかさ した とこ を こんな こと を 云い ながら あるいて おり ました
ロジスティック回帰による著者分類プログラムのコードをlist7に記載します。
from pyspark.mllib.regression import LabeledPoint from pyspark.mllib.classification import LogisticRegressionWithSGD from pyspark.mllib.feature import HashingTF # HadoopConfigurationへのCredentialの設定 def set_hadoop_config(credentials): prefix = "fs.swift.service." + credentials['name'] hconf = sc._jsc.hadoopConfiguration() hconf.set(prefix + ".auth.url", credentials['auth_url']+'/v3/auth/tokens') hconf.set(prefix + ".auth.endpoint.prefix", "endpoints") hconf.set(prefix + ".tenant", credentials['project_id']) hconf.set(prefix + ".username", credentials['user_id']) hconf.set(prefix + ".password", credentials['password']) hconf.setInt(prefix + ".http.port", 8080) hconf.set(prefix + ".region", credentials['region']) hconf.setBoolean(prefix + ".public", True) credentials = { # PaletteのData Sourcesから挿入 } credentials['name'] = 'files' set_hadoop_config(credentials) # dazai = sc.textFile("swift://notebooks.files/dazai.txt") miyazawa = sc.textFile("swift://notebooks.files/miyazawa.txt") tf = HashingTF(numFeatures = 1000) features_dazai = dazai.map(lambda line: tf.transform(line.split(" "))) features_miyazawa = miyazawa.map(lambda line: tf.transform(line.split(" "))) train_dazai = features_dazai.map(lambda features: LabeledPoint(0, features)) train_miyazawa = features_miyazawa.map(lambda features: LabeledPoint(1, features)) train = train_dazai.union(train_miyazawa) model = LogisticRegressionWithSGD.train(train.cache()) def label_to_author(label): return 'dazai' if label == 0 else 'miyazawa' test_dazai = tf.transform("私 は その 男 の 写真 を 三葉 見た ことが ある".split(" ")) test_miyazawa = tf.transform("谷川 の 岸 に 小さな 学校 が あり ました".split(" ")) print("Prediction for dazai test: author is %s" % label_to_author(model.predict(test_dazai))) print("Prediction for miyazawa test: author is %s" % label_to_author(model.predict(test_miyazawa)))
インポート文の後、Object Storageからデータを取得するため、set_hadoop_config()メソッド内でHadoopConfigurationにObject Storageの資格情報を渡します。credentials変数に与える資格情報は、Paletteの「Data Source」の各ファイルにある[Insert to code]リンク(fig13)をクリックすることでNotebook内に挿入することができます。この際、[Insert to code]をクリックするファイルは、同じObject Storageにアップロードされているものであればどれでも構いません。
次に、SparkContextのtextFile()メソッドを用いてテキストファイルからRDDを生成します。その後RDDの各行をmap()メソッドで操作しながら、単語ごとにスペースで区切ってHashingTF.transform()メソッドに渡します。HashingTF.transform()メソッドは単語の配列を出現頻度の特徴ベクトルに変換するため、ここでの処理により各著者で頻出する単語や言い回しの特徴がある程度抽出されます。
次にdazaiとmiyazawaの特徴ベクトルに対してそれぞれ0 or 1のラベリングを行い、結合後キャッシュを用意してLogisticRegressionWithSGD.train()メソッドに教師データとして渡してモデルを構築します。
最後に、教師データに利用しなかった小説の冒頭部分でテストデータを用意し、構築したモデルが著者を判定できるかをテストした結果がlist8です。期待通り、小説冒頭部分から著者を分類することができました。
Prediction for dazai test: author is dazai Prediction for miyazawa test: author is miyazawa
おわりに
本稿では、BluemixのApache Sparkサービスを用いて初歩的な機械学習のサンプルプログラムを実装し、SparkとMLlibを活用することでシンプルにスケーラブルな機械学習処理を記述できることをご紹介しました。今回利用したAPIやライブラリは、Sparkに用意されている豊富な機能全体のごく一部なので、もしより詳しい情報を知りたい場合は書籍や公式サイトを参照ください。