Python で word2vec を使ってみる
word2vecとは
単語のベクトル表現を獲得する一つの手法です。
word2vecの特徴としては、意味的な計算が可能な表現であるということです。
例えば次の式のように、kingのベクトルからmanのベクトルを差し引いたベクトルにwomanのベクトルを足し合わすことで、queenのベクトルと近似するベクトルが得られます。
king - man + woman = queen
事前知識として
word2vec install
pip でインストールできます。
$ sudo pip install word2vec
英語のモデルファイルが、下記の使い方のページよりダウンロードできるので、簡単に試すことができます。
word2vec を試してみる
今回はWeb文書を適当にクローリングしてきて、ベクトル表現を獲得してみます。
- news.yahoo.co.jp をシードにして、Webページをクローリング(PythonでN-gramで書いたコードを利用)
- BeautifulSoupでHTMLをParseして、MeCabで分かち書きます。
- word2vecでモデルを学習します。
1. Web文書のクロール
http://news.yahoo.co.jp をシードにして、深さ2のURLを収集。
本文書執筆時点で、184URLを取得し、jsonでダンプします。
具体的な実装は、PythonでN-gramを参照されたい。
2. MeCabで分かち書き
すべてのURLから文書を取得し、分かち書きしたのちに、ファイルに保存しています。
# coding: utf-8 import sys import json import MeCab import urllib2 from collections import defaultdict from operator import itemgetter from BeautifulSoup import * class HTMLParser(): def get(self, url): try: c = urllib2.urlopen(url) except: print "Could not open %s" % url return "" soup = BeautifulSoup(c.read()) text = '\n'.join(self.__getNavigableStrings(soup)) return text def __getNavigableStrings(self, soup): if isinstance(soup, NavigableString): if type(soup) not in (Comment, Declaration) and soup.strip(): yield soup elif soup.name not in ('script', 'style'): for c in soup.contents: for g in self.__getNavigableStrings(c): yield g if __name__ == "__main__": f = open("urls.json", "r") urls = json.load(f) f.close() print "Count of urls : " + str(len(urls)) STOP_WORD = " 。 、 「 」 ( ) ? ? : , , . ! ! # $ % & ' ( ) = ~ | ` { } * + ? _ > [ ] @ : ; / . ¥ ^ 【 】 ¥ _ / 『 』 > ? _ * + ` | 〜 * + > ? # ” # $ % & ’ \" ・".split() hp = HTMLParser() tagger = MeCab.Tagger("-O wakati") wakati_text = [] for url in urls: text = hp.get(url) wakati_raw = tagger.parse(text.encode('utf-8')) wakati_formalize = [] for row in wakati_raw.split('\n'): row = row.rstrip().lower() for sw in STOP_WORD: row = row.replace(sw, '') wakati_formalize.append(row) wakati_text.append(' '.join(wakati_formalize)) f = open("wakati_text.txt", 'w') f.write('\n'.join(wakati_text)) f.close()
3. word2vecでベクトル表現の獲得
次のように訓練を行うと、python interface の使い方 のページと同様に、cosineやanalogyを計算できます。
$python > import word2vec # Training > word2vec.word2vec('wakati_text.txt', 'wakati_text.bin', size=300, verbose=True) # Predictions > model = word2vec.load('wakati_text.bin') > model.cosine('ブラジル')
実際に計算してみた
計算用のプログラム
#coding: utf-8 import word2vec def preprocess(): word2vec.word2vec('wakati_text.txt', 'wakati_text.bin', size=300, verbose=True) def echo(label, tlist): print "==============================" print label print '------------------------------' for x in tlist: print x[0], x[1] if __name__ == "__main__": # run only onece preprocess() model = word2vec.load('wakati_text.bin') key = 'yahoo' tlist = model.cosine(key)[key] echo(key, tlist) key = 'ブラジル' tlist = model.cosine(key)[key] echo(key, tlist)
出力結果
============================== yahoo ------------------------------ japan 0.745264967594 reserved 0.724144233549 corporation 0.721037877617 rights 0.715372173546 翻訳 0.711609108271 all 0.706314503681 エンタメニュース 0.672859051865 c 0.658193204546 wordleaf 0.654228512159 copyright 0.646804855186 ============================== ブラジル ------------------------------ ドイツ 0.796991224026 W杯 0.78659559174 大会 0.779938226056 アルゼンチン 0.771944338876 サッカー 0.748730168265 杯 0.746366345547 w 0.743728945102 戦 0.743359927214 準決勝 0.726702564219 オランダ 0.717565046411
考察
Yahooと共起しやすいJapanだったり、ブラジルの準決勝対戦国のドイツが上位にきたり、類似するベクトル表現はそれなりにとれてる気がします。
意味的な計算もできるのですが、あまり良い例が見つけられなかったので割愛。
データ量が少な過ぎて、上手く学習できていない感も否めない。
おわりに
word2vec を使うだけなら非常に簡単に利用できます。
一方で、その内部を理解するためには、前提となる知識が必要になります。
O'Reilly Japanから、word2vecによる自然言語処理が出版されているので読んでみたい。
関連記事
継続のはなし
Schemeとかを勉強していると、よく登場する概念に”継続”というものがあります。この記事では、継続とは何か?を平易に説明し、継続への導入あるいは入門を目指すことを目的とします。
継続とは何か?
wikipediaには次のように定義されています。
継続とは、プログラムの実行においてある時点において評価されていない残りのプログラムを意味するものであり、手続きとして表現されるものである。
具体的にどういうことなのか、説明して行きます。
今回はGaucheを使っています。
まずはListの生成を考えます。
gosh> (list (+ 1 2) (+ 3 5) (+ 7 11)) ; (list 3 8 18) (3 8 18)
このときSchemeでは、左から順に引数を評価してから手続きの評価に入ります(ちょうど上記のコメントのように)。
例えば,(+ 3 5)を評価するときは、『3と(+ 3 5)を評価した後に、(+ 7 11)を評価し、Listを生成する』のように処理系は解釈しています。
この、『3と(+ 3 5)を評価した後に、(+ 7 11)を評価し、Listを生成する』のことを”継続”といいます。
別の視点から考えてみます。もう一度”継続”の定義を見て下さい。
継続とは、プログラムの実行においてある時点において評価されていない残りのプログラムを意味するものであり、手続きとして表現されるものである。
これに従い、手続きとして表現してみます。
gosh> (define cont (lambda (x) (list 3 x (+ 7 11)))) gosh> (cont (+ 3 5)) ; = (list (+ 1 2) (+ 3 5) (+ 7 11)) (3 8 18)
手続きcontが継続、『3とx=(+ 3 5)を評価した後に、(+ 7 11)を評価し、Listを生成する』を表現しています。
継続を扱う
Schemeでは、継続を扱うための手続きが容易されています。
call-with-current-continuation手続きは、慣習的に、ccやcallのようにdefineします。
gosh> (define cc call-with-current-continuation) ;もしくは (define call call-with-current-continuation)
例 test.scm
(define cc call-with-current-continuation) (define x 100) (define z 700) (define cont '()) (display (list x (cc (lambda (c) (set! cont c) 300)) z)) (newline) ; (100 300 700) ; このときcontは『100と引数を評価した後に、zを評価し、Listを生成する』という継続である。 (display (cont 250)) (newline) ; (100 250 700) (define x 0.1) (define z 0.7) (display (cont 0.3)) (newline) ; (100 0.3 700)
ここで注意して欲しいのは,継続contは、『listの第一引数は評価し終えており、第三引数はこれからzを評価する』ということである。
継続には、もうひとつの側面がある。 例 test.scmの続き
; test.scmが記述されているとする。 (display (cons (cont 1) 'something)) (newline) ; (100 1 0.7) (display (cons '(100 1 0.7) 'something)) (newline) ; ((100 1 0.7) . something)
なぜ、このような結果になるのか。継続contは、『100と引数を評価した後に、zを評価し、Listを生成する』ことを表現している。一方で、consを呼び出し、第一引数を評価するときの継続は、『引数を評価し、第二引数を評価しconsを行う』である。
つまり、継続contを呼び出すということは、本来の継続『引数を評価し、第二引数を評価しconsを行う』の代わりに,『100と引数を評価した後に、zを評価し、Listを生成する』を行うことを意味する.
結果的に、新たな継続を呼び出すと、本来の継続を直ちに終了し、新たな継続を実行する。このように、Schemeでは継続を明示的に扱うことができる。
継続を活用する
例外処理
Listの要素の積を計算する。 product.scm
(define cc call-with-current-continuation) (define (product x) (cc (lambda (cont) (letrec ((iter (lambda (x sum) (cond ((null? x) sum) ((not (number? (car x))) (cont (cons "Error : detect not a number" (car x)))) (#t (iter (cdr x) (* sum (car x)))))))) (iter x 1))) )) (display (product '(1 2 3 4 5))) (newline) ; 120 (display (product '(1 2 3 a 5))) (newline) ; ("Error : detect not a number" . a)
File IO
ファイルに文字列を書き込み、ファイルの文字を数え上げる。fileio.scm
(define (count-chars fname) (call-with-input-file fname (lambda (in) (let loop ((c (read-char in)) (count 0)) (cond ((eof-object? c) count) (else (loop (read-char in) (+ count 1)))))))) (define (write-message fname) (call-with-output-file fname (lambda (out) (format out "I'm a Schemer") (newline out) (flush out)))) (define fname "./test.txt") (write-message fname) (display (count-chars fname)) (newline) ;14
参考記事
【書評】LEAN UX リーン思考によるユーザエクスペリエンス・デザイン(THE LEAN SERIES)
THE LEAN SERIES の RUNNING LEAN 実践リーンスタートアップに続いて、LEAN UX リーン思考によるユーザエクスペリエンス・デザインを読みました。
RUNNING LEAN についての感想はこちら。
リーンキャンバスのWebツールを作ってみた - 巨人の肩の上に登る
LEAN UX を読んでみて
内容的には、RUNNING LEANやリーンスタートアップと重複があります。その中でも、本書の位置づけとしてはUXという目線。しかしながら、上記の類書とは違う、本書特有のUX的な話が特になかったように思います。つまりどういう本かというと、類書の”UXに関する部分をまとめた本”という印象です。
印象に残ったところ
MVPの誤解
p70、 MVPという言葉は、2つの目的で使いわけることができるが、混同して利用されているため、混乱を招く事がある。
1つは、何か学ぶことを主目的としてMVPを作成する方法です。この場合、チームは市場に価値を提供することを重視せず、市場が何を求めているかを理解しようとします。もう1つは、できるだけ速く市場に価値を届けることを望むために、製品や機能の小さなバージョンをつくるというものです。
ユーザ・ストーリー
エンドユーザへのメリットを最小単位で表現したもの.次のようなフォーマットで記述できる。
【ユーザ】として(私は)、
【この機能】が欲しい、
なぜなら【この成果が実現したい】から
当たり前といえば、当たり前ですが、タスクを考えるうえで個々のタスクが何のためなのかを考え、明文化することは非常に有益だと思います.
関連記事
MavericksでPythonからMariaDBを使ってみる
Mac OS X Mavericksで、MariaDBを使ってみた。
MariaDBとは
MariaDBは、MySQLから派生したOSSなリレーショナルデータベースです。
細かい話は下記の記事を参照されたい。
MariaDBのinstall
今回は、homebrewを使ってinstallした。
公式で説明されている、Mac OS X へのinstall方法を参考にした。
Building MariaDB on Mac OS X using Homebrew - MariaDB Knowledge Base
brew installすると下記のようなErrorが出てしまったので、MySQLをunlinkしてから再実行すると解決した。
$ brew install mariadb Error: Cannot install mariadb because conflicting formulae are installed. mysql: because mariadb, mysql, and percona install the same binaries. Please `brew unlink mysql` before continuing. Unlinking removes a formula's symlinks from /usr/local. You can link the formula again after the install finishes. You can --force this install, but the build may fail or cause obscure side-effects in the resulting software.
$ brew unlink mysql Unlinking /usr/local/Cellar/mysql/5.6.16... 105 links removed $ brew install mariadb
mariadbを使ってみる。
$ mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MySQL connection id is 6 Server version: 5.5.9-log Source distribution Copyright (c) 2000, 2014, Oracle, Monty Program Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MySQL [(none)]>
PythonからMariaDBを使う
MariaDBのドライバは、基本的にMySQLと同じ物を使えるようです。今回は、MySQL-pythonを利用します。
pipでinstallしようとしたところ、下記のようなErrodで止まってしまいました。どうやら、Mavericksにアップデートしたことが原因のようです。
$ sudo pip install MySQL-pyhton ... clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] clang: note: this will be a hard error (cannot be downgraded to a warning) in the future error: command 'cc' failed with exit status 1 ...
Stackoverflowに似たような質問があり、その回答を試してみたところ上手くいきました。
$ export CFLAGS=-Qunused-arguments $ export CPPFLAGS=-Qunused-arguments $ sudo -E pip install MySQL-python
さっそく試してみる。
import MySQLdb connection = MySQLdb.connect(host="HOST_NAME",db="DB_NAME",user="USER_NAME", passwd="PASSWARD") cursor = connection.cursor() cursor.execute("select * from TABLE_NAME") result = cursor.fetchall() print result cursor.close() connection.close()
簡単ですが、以上です。
関連記事
PythonとFlaskでメール送信と簡易SMTP Server
flask-mailでメールの送信
Flask extensionのflask-mailを使うと、簡易に実装できます。
インストール
$ sudo pip install Flask-Mail
使い方
まずは、Mailのインスタンスを作成。
from flask import Flask from flaskext.mail import Mail app = Flask(__name__) mail = Mail(app)
そして、送信。HTMLとプレーンテキストを個別に設定できます。
from flaskext.mail import Message @app.route("/") def index(): msg = Message("ここにタイトルがはいります", sender="from@example.com", recipients=["to@example.com"]) msg.body = "testing" msg.html = "<b>testing</b>" mail.send(msg)
より詳細な設定は、公式ドキュメントを参照されたい。
Pythonで簡易SMTP Server
local環境で、メールのテストを行いときに使います。
python -m smtpd -n -c DebuggingServer localhost:25
余談
flask-mailの公式ドキュメントには、下記(-)のように記載されているのですが、そのままだとErrorを吐きます。そこで、Flask extensionsの説明にあるように下記(+)のように修正しました。
- from flaskext.mail import Mail - from flaskext.mail import Message + from flask.ext.mail import Mail + from flask.ext.mail import Message
【書評】小さなチーム、大きな仕事-37シグナルズ成功の法則
37signals のCEOジェイソン・フリードと、同所属のRails作者デビッド・ハイネマイヤー・ハンソンが著した、「小さなチーム、大きな仕事」を読みました.新書くらいのサイズで250ページ程なので,手軽に読めます。
Basecampが有名な会社です。社名の由来が気になって調べたところ、
SETI@Home(注2)のプロジェクトで見つかった未確認の信号のソースが37個あって,そこからとったものです。
とのこと。(参考|Gihyo.jpのInterview)
さて、本書の内容ですが、スタートアップや小さい企業で大きな仕事をしたい人のマインドについて述べられています。そのマインドは共感できる所が多く良いのですが、実際にどう実行してるのか?など実践的な話がないので、そこが残念です。本書のp41まず作り始めようにもあるように(下記引用)、
アイデアと実際に作り上げることとは何の関係もない。なにをしたかが重要なのであって、考えたり、言ったりすることが重要なのではない。
このマインドを、実行するための具体策に落とし込むのは骨がおれるでしょう。
特に共感できたところを、下記にメモしておきます。
「失敗から学ぶこと」は過大評価されている
ハーヴァード・ビジネススクールの調査によると、一度成功した起業家が次に成功する確率は34%なのに対し、最初に失敗した起業家が成功する確率は、はじめて起業する人と同じでたったの23%しかない。
「起業家(アントレプレナー)」はもうたくさんだ
「起業家」という言葉はひっこめよう。時代遅れのお荷物だ。
ヒーローになるな
あるタスクが二時間でできると考えたとしよう。しかしそれに四時間を費やしても、まだ四分の一しか終わっていない。するとあなたはヒーローモードに入る。あなたはそれをやりとげると決断したのだ。しかし、それだけの価値があるのだろうか?この十六時間で他にたくさんのことができたはずだ。やめることが最善の方法となりうることを覚えておこう。
関連記事
リーンキャンバスのWebツールを作ってみた
TinyCanvas
シンプルにリーンキャンバスを作成できる TinyCanvas を作った。
Running Lean を読んだのがきっかけ
アッシュ・マウリャ著の Running Lean を読んだみた。
とても有益だったので、リーンキャンバスを作ってみようと思い立ったものの、無料で使えるツールが見当たらなかったので、作ってみた。
やや、車輪の再発明感がありますが、宜しければ使ってみて下さい。
本書の感想
エリックリース著のリーン・スタートアップは非常に面白かったのですが、中々実践に移すのが難しい...。
Running Lean はそういったニーズに答える本です。
自身のプロジェクトに上手く取り入れられていない人にはおすすめ!
リーンキャンバスとは何ぞ?って人は、下記の記事を読んでみて下さい。
「開発者のためのリーン・スタートアップ」「リーン・キャンバス入門」の資料を公開します - delirious thoughts
TinyCanvas のサンプル
追記|使い方とか書いてなかった...
作成したキャンバスのURLをブックマークしといて下さい。
そのURLを共有すれば同じ物が見えます。
関連記事