巨人の肩の上に登る

先人の積み重ねた発見に基づいて、なにかを発見しようとすることを指す。

Python で word2vec を使ってみる

f:id:mayo_yamasaki:20140714161338p:plain

word2vecとは

単語のベクトル表現を獲得する一つの手法です。
word2vecの特徴としては、意味的な計算が可能な表現であるということです。
例えば次の式のように、kingのベクトルからmanのベクトルを差し引いたベクトルにwomanのベクトルを足し合わすことで、queenのベクトルと近似するベクトルが得られます。

king - man + woman = queen
事前知識として

word2vec install

pip でインストールできます。

$ sudo pip install word2vec

英語のモデルファイルが、下記の使い方のページよりダウンロードできるので、簡単に試すことができます。

word2vec を試してみる

今回はWeb文書を適当にクローリングしてきて、ベクトル表現を獲得してみます。

  1. news.yahoo.co.jp をシードにして、Webページをクローリング(PythonでN-gramで書いたコードを利用)
  2. BeautifulSoupでHTMLをParseして、MeCab分かち書きます。
  3. 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を使ってみる

f:id:mayo_yamasaki:20140401165933p:plain

Mac OS X Mavericksで、MariaDBを使ってみた。

MariaDBとは

MariaDBは、MySQLから派生したOSSなリレーショナルデータベースです。
細かい話は下記の記事を参照されたい。

MariaDB - Wikipedia

MySQLとMariaDBの違い一覧 - 技術メモ置き場

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

f:id:mayo_yamasaki:20140302070608p:plain

シンプルにリーンキャンバスを作成できる TinyCanvas を作った。

Running Lean を読んだのがきっかけ

アッシュ・マウリャ著の Running Lean を読んだみた。
とても有益だったので、リーンキャンバスを作ってみようと思い立ったものの、無料で使えるツールが見当たらなかったので、作ってみた。
やや、車輪の再発明感がありますが、宜しければ使ってみて下さい。

本書の感想

エリックリース著のリーン・スタートアップは非常に面白かったのですが、中々実践に移すのが難しい...。 Running Lean はそういったニーズに答える本です。
自身のプロジェクトに上手く取り入れられていない人にはおすすめ!

リーンキャンバスとは何ぞ?って人は、下記の記事を読んでみて下さい。
「開発者のためのリーン・スタートアップ」「リーン・キャンバス入門」の資料を公開します - delirious thoughts

TinyCanvas のサンプル

f:id:mayo_yamasaki:20140302071217p:plain

追記|使い方とか書いてなかった...

作成したキャンバスのURLをブックマークしといて下さい。
そのURLを共有すれば同じ物が見えます。


TinyCanvas


関連記事