Scala入門2 EclipseでLift開発(1)

入門2回目にしてLift!?といった感じのタイトルですが、Scalaについて気になったことを試すため脱線したり、書籍の文法学習に戻ったり、また脱線したり・・・という路線で行こうと思います。

今回はScalaのウェブフレームワークLift」をEclipse上で開発できるようにするまでの手順を調べてみることにします。開発環境はUbuntu10.10+Eclipse3.6を想定しています。

Scala2.8.1のインストール

今回は2.8系で開発をしたいため、2.8.1をダウンロードしてきます。

$ sudo wget http://www.scala-lang.org/downloads/distrib/files/scala-2.8.1.final.tgz
$ tar xzf scala-2.8.1.final.tgz

解凍後.profileにパスを通します。

$ vim ~/.profile 
 -> export PATH=$PATH:[解凍後ぶちこんだディレクトリへのパス]/scala-2.8.1.final/bin

sourceコマンドが効かなかったので、一旦ログアウトしてパスを有効に。

$ scala -version
Scala code runner version 2.8.1.final -- Copyright 2002-2010, LAMP/EPFL

MavenでLiftプロジェクトの作成

Mavenも上記方法でインストールするか、apt-getでインストールできます。ここでは省略。

Scala2.8.1とLift2.2の組み合わせでプロジェクトを作成してみます。

$ mvn archetype:generate \
 -DarchetypeGroupId=net.liftweb \
 -DarchetypeArtifactId=lift-archetype-basic_2.8.1 \
 -DarchetypeVersion=2.2 \
 -DarchetypeRepository=http://scala-tools.org/repo-releases \
 -DremoteRepositories=http://scala-tools.org/repo-releases \
 -DgroupId=jp.tantack \
 -DartifactId=hello_lift \
 -Dversion=1.0

DarchetypeArtifactIdは「lift-archetype-blank」「lift-archetype-basic」「lift-archetype-jpa-basic」とあるようです。用途に併せ使い分けろ、とのことですが、よく分からないのでbasicのままにしておきました。DgroupIdとDartifactIdはそれぞれ自分で命名

コマンドに問題がない場合は、設定した方法でビルドして良いか聞かれるため、「y」でビルドを実行します。

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8 minutes 2 seconds
[INFO] Finished at: Sun Jan 16 22:47:45 JST 2011
[INFO] Final Memory: 12M/107M
[INFO] ------------------------------------------------------------------------

プロジェクトの作成に成功しました。

Eclipseプロジェクトへのインポートと動作確認

続いてEclipseMavenを連携させるため、M2_REPOの設定を行ないます。これはMaven Eclipse Pluginを初めて使う場合のみ設定します。

$ mvn -Declipse.workspace=[Eclipseのworkspaceパス] eclipse:add-maven-repo

次にMavenプロジェクトをEclipseプロジェクトに変更します。

$ cd hello_lift/
$ mvn eclipse:eclipse

・・・結構時間掛かります。

終わったらEclipse側からプロジェクトをインポートしてやります。あとはプロジェクトをインポートしたディレクトリに移動し、Jettyを起動させ、動作確認をしてみます。

$ cd workspace/hello_lift/
$ mvn jetty:run

無事起動した場合には、http://localhost:8080/へアクセスすると以下の画面が表示されると思います。

エラーが出た場合には、pom.xmlの設定あたりを見直す必要がありそうです。

今日はLiftプロジェクトをEclipseにインポートし、動作確認もできたことですので、ここまでとしておきます。

今後の課題

現状ではEclipse上でコードを書けるようになっただけで、Jettyの起動やテストの実行はMaven頼みという微妙な状態です。より怠惰なEclipseライフを送れるよう、以下の課題を努力目標として挙げておきます。

  • もっと楽にEclipse上でLiftプロジェクトを作れる方法を探す
  • mvnコマンドを使わず、Eclipse上でJettyを起動できるといいなあ・・・
  • 軽いテストもEclipse上で行えるといいなあ・・・
  • DBとしてMySQLを設定する

あと次回はこの続きじゃなくて、文法修行に戻ったりすると思います。

Scala入門1 Hello World!

集合知のサンプルコードはScalaで書いていこう・・・と意気込み、まずはJSONパーサの作成を試みたのですが、以前勉強会でやっていたこと含めすっかり抜け落ちていたため、入門用の書籍を使って一からやりなおしていくことにしました。

中途半端に覚えてるパターンマッチとか、全て忘れたことにして本当に基本中の基本から。

コマンドラインから Hello World

ScalaにもREPLという対話型の実行環境が備わっています。調べてみると関数型言語では普通に搭載されている機能みたいです。

$ scala
Welcome to Scala version 2.7.7final (Java HotSpot(TM) Server VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.

scala> 

ベタベタに「Hello World!」から書いていきます。

scala> print("Hello World!")
Hello World!

Scalaスクリプトから Hello World

エディタで「.scala」のファイルを作成。

$ vi HelloWorld.scala

先程REPLで実行した一行をそのまま書き込んで保存します。

mainメソッドはスクリプト実行時、Scalaが内部的にラップしてくれるようなので書いていません。

$ scala HelloWorld.scala 
Hello World!

Scalaコードをクラスファイルにコンパイルして Hello World

ScalaJVM上で動作する言語なので、コンパイルしてクラスファイルを作成することができます。

そのためJavaライブラリ等の既存資産を再利用できることもScalaの魅力の一つなのですが、これは今後入門書を読み進めていけば出てくると思います。

試しに作成したばかりのScalaスクリプトをそのままの状態でコンパイルしてみます。

$ scalac HelloWorld.scala 
HelloWorld.scala:1: error: expected class or object definition
print("Hello World!")
^
one error found

怒られた。

ソースコードにクラスかオブジェクトが必要とのことですので、スクリプトの内容をちょっと書き換えてみます。

object HelloWorld {
	def main(args: Array[String]): Unit = {
		println("Hello World!")
	}
}

これでどうだ!

$ scalac HelloWorld.scala 
$ ls
HelloWorld.scala HelloWorld$.class HelloWorld.class

無事コンパイルされ、同ディレクトリにクラスファイルも生成されています。

ではクラスファイルを実行してみましょう。

$ java HelloWorld 
Exception in thread "main" java.lang.NoClassDefFoundError: scala/ScalaObject
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
	at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Caused by: java.lang.ClassNotFoundException: scala.ScalaObject
	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
	... 12 more
Could not find the main class: HelloWorld.  Program will exit.

また怒られた。NoClassDefFoundErrorとな。

ちょっとどうなってるのか分からないので、次回までの宿題としてクラスファイルを逆コンパイルし、中身がどうなっているかを観察してみようと思います。

追記(2011/01/14)

scalacでコンパイルしたクラスファイルはscalaコマンドで実行するようです。

$ scala HelloWorld
Hello World!

javaコマンドで実行するためには、実行時Scalaのライブラリにパスを通してやらないとダメ。

・・・ってこれ、1年ぐらい前に同じ事調べたの思い出しました。

参考

SCALAプログラミング入門

SCALAプログラミング入門

集合知プログラミング独書会(1)

読みたかった書籍の一つ「集合知プログラミング」の独り読書会を本日から行っていきます。

1章 集合知への招待

この章では集合知がどのようなものか、どのように活用されているか、機械学習とその限界について書かれています。

集合知とは

この書籍では集合知を以下のように定義しています。

今までにない知見を生み出すために、集団の振る舞い、嗜好、アイデアを結びつけることを指す。

集合知と言えば、今や死語となった「Web2.0」が盛んに叫ばれるようになってから普及してきた技術、といったイメージを持っていました。しかし、それ以前にも集合知という概念は存在しており、身近な例として「世論調査」が挙げられています。

集合知とは、独立した貢献者たちから新たな結論を作り上げることである。

ただ世論調査のように膨大なコストと手間の掛かる手法を個人で実行するこはできません。

それがインターネット&Webサービスの普及により、ネット上の特定箇所に知識が集まるようになってきました。例えば先日私が類似度計算に失敗したはてなブックマーク、より巨大な知識の集まるものとしてはtwitterFacebookWikipedia等があります。

この書籍では上記のようなサービスから、オープンなAPIを通じてデータを集める方法を紹介し、

利用者のデータを利用して計算を行い、利用者の経験を拡大することのできるような新たな情報を作り上げるようなアルゴリズムについて扱う。

といったことをやっていくようです。

機械学習とその限界

機械学習という言葉もよく聞くようになってきましたが、以前は人工知能研究という遠い世界のお話だと思っていました。機械学習の身近な例ですと、スパムメールに対するフィルタリングですとか、広告に利用される行動ターゲティングあたりが有名でしょうか。

機械学習はコンピュータに学習させるためのアルゴリズムとして、以下の2ステップを行うようです。

1. 与えられたデータの特質を推測できるような情報を生み出し
2. その情報を利用して将来現れるであろうデータの予測をする

どうやって予測を実現するのか、よく分かりませんね。

このあたりの疑問を解決するため、スパムメールのフィルタリングを例に挙げ、機械学習のプロセスが解説されています。

人がある単語を含んだメールはスパムである、と経験に基づいてパターンを作り上げるように、同様のパターンを機械に教えてあげることでフィルタリングを行うようです。

最初にパターンを教えてやれば、以後は自動的に学習し、経験を積んで言ってくれるのかな?本当に?・・・と、モヤモヤしたものを抱えつつ読み進めてみると、機械学習の限界について触れられていました。

機械学習の手法は既に見たデータを基にしか一般化できず、それでさえ完全ではない。

つまり人の経験や人間関係等の人生から抽出した膨大なパターンを与えてやれば、理論上は人間と同じ行動をできるかも知れないけれども、少ないパターンを基に一般化を行っても正確じゃないよ、ってことのようです。

スパムフィルタリングにしても、この単語が含まれていてもこの人からのメールは受け取る・・・といったように、常に機械に対して学習を続けさせていくことで、より正確なフィルタリングを実現させるみたいです。私が思っていたほど楽に学習し、経験を積み上げてくれるわけではないってことですね。

機械学習の使用例

機械学習を利用して利益を挙げているものの代表格としてGoogleが真っ先に挙がっています。あとはAmazonLast.fmも馴染み深いですね。他分野ではバイオテクノロジー、クレジット詐欺の発見、マーケティング、市場分析、果ては国防あたりにも利用されているようです。

読み進めるにあたって

2章からは実践に入るわけですが、数学の知識が必要で私の理解できない箇所は、適当にスルーして後からやり直す予定でいます。海外のWebサービスAPIを使っているものについては、そのまま利用するか、国内サービスで似たものがあれば、それを利用してサンプルコードを書いていきます。

あとは名古屋周辺で同分野に興味のある方がいれば、独書会から読書会に発展させるかも知れません。勉強会を開くとしても4月以降になりそうですが、興味があれば連絡下さい。

はてなブックマークのホットエントリーから、自分好みのエントリーを抽出する・・・のに失敗した記録

あけましておめでとうございます。今年「は」よろしくお願い致します。

前年は個人的に色々と納得できない道に進み、プログラマとしての道も途絶えてしまったため、今年は納得のできる生き方をしていきたいです。

ってことで、前回Pythonに触れてみましたので、今回は少し実践的な内容で勉強していきます。

表題の通り今回は最新のはてなブックマークホットエントリーから、自身のブックマーク履歴を元に自分の好みのエントリーを抽出する・・・といったことをやってみようと思います。

今回実装する簡易レコメンデーションエンジンのしくみ

やりたいことは言わば「レコメンデーションエンジン」の簡易版です。レコメンデーションエンジンはAmazonのオススメ商品機能等でも使われているので、皆様にも馴染みのあるシステムなんじゃないかなーと思います。

今回実装したい機能のしくみを解説しておきます。

はてなブックマークにはエントリー毎に「このジャンルは○○と××だな」等、ユーザーが「タグ」を使ってエントリーを分類するための機能が備わっています。今回はその「タグ」を推薦のための尺度として使います。

まずはマイブックマークのブックマーク履歴から全てのタグから抽出・集計します。ブックマーク数が膨大な場合には、かかる負荷を考え、間隔を開けた上で複数回に分けて集計してやる必要がありそうです。幸い私のブックマークは、200件弱しか登録されていないため1回で集計できそうです。

続いて最新のホットエントリーから自身の嗜好に近いエントリーを抽出するため、1件1件について、それぞれタグを抽出・集計していきます。

ここまででマイブックマークとホットエントリーのタグを集計したタグ群が作られたことになります。タグはそれぞれ登場した回数をカウントしてあるため、これを元にタグクラウドを作る・・・なんてこともできそうなわけですが、今回はそれを更に先へ進め、マイブックマークのタグ群とホットエントリーのタグ群の類似度を計算し、より類似度の高いものをオススメホットエントリーとして提示してくれるようなシステムを作ります。

類似度の計算方法は高校数学や統計学で馴染みのあるユークリッド距離、コサイン類似度からピアソン相関、マンハッタン距離、Jaccard係数など色々考案されているようです。

今回は比較対象の母集団に大きな差があるため、集団の中での順位付けを類似度の指標とするスピアマンの順位相関係数を使ってオススメ記事を抽出してみます。

初めて知った&使う計算手法ですので、計算に不備があるかもしれません。

ここまで長々と書きましたが、コードにすると単純ですので、さっそくコードを書いていくことにします。

・・・その前に

RSSフィードをパースするためのライブラリを取得しておきます。検索してみたところヒットしたfeedparserを使うことにします。こっちの方がスタンダードだよ、っていうものがあれば教えていただけると嬉しいです。

$ sudo wget http://feedparser.googlecode.com/files/feedparser-4.1.zip
$ unzip feedparser-4.1.zip 
$ sudo python setup.py install
running install
running build
running build_py
creating build
creating build/lib.linux-i686-2.6
copying feedparser.py -> build/lib.linux-i686-2.6
running install_lib
copying build/lib.linux-i686-2.6/feedparser.py -> /usr/local/lib/python2.6/dist-packages
byte-compiling /usr/local/lib/python2.6/dist-packages/feedparser.py to feedparser.pyc
running install_egg_info
Writing /usr/local/lib/python2.6/dist-packages/feedparser-4.1.egg-info

Pythonの外部ライブラリは、こんな感じでインストールするんですね。

タグの集計を行う

今回のコードはURLベタ書き、エラー処理なしで必要最低限の処理しか行っていないため、現段階での実用性は皆無です。

myBookmarkUrl = 'http://b.hatena.ne.jp/tantack/rss'
hotEntryUrl = 'http://b.hatena.ne.jp/hotentry/it.rss'
entryInfoUrl = 'http://b.hatena.ne.jp/entry/json/?url='

#与えられたURLのRSSをfeedparserでパースする
def getRssContent(url):
    resp = urllib2.urlopen(url)
    rss = resp.read()
    return feedparser.parse(rss)

#マイブックマークRSSを取得・パースしてタグの集計を行う
def getMyBookmark():
    count = 0
    myTagDict = {}
    content = getRssContent(myBookmarkUrl)
    bookmarkCount = int(content.channel.opensearch_totalresults)
    if(bookmarkCount <= 0):
        return myTagDict
    else:
        while count < bookmarkCount:
            content = getRssContent(myBookmarkUrl + '?of=' + str(count))
            for entry in content.entries:
                try:
                    for tag in entry.tags:
                        if(tag.term in myTagDict):
                            myTagDict[tag.term] = myTagDict[tag.term] + 1
                        else:
                            myTagDict[tag.term] = 1
                except AttributeError:
                    print('タグ未登録')
            count += 20
    return myTagDict

#IT関連のホットエントリーRSSを取得・パースしてURLリストを返す
def getHotEntry():
    urlList = []
    content = getRssContent(hotEntryUrl)
    for text in content.entries:
        urlList.append(text.link)
    return urlList

#URLリストからエントリー毎に付けられたタグの集計を行う
def getEntryTags(urlList):
    entryTagList = []
    for index, url in enumerate(urlList):
#        if(index > 5):
#            break
        tagDict = {}
        resp = urllib2.urlopen(entryInfoUrl + url)
        jsonObj = resp.read()
        entryInfo = json.loads(jsonObj)
        for info in entryInfo['bookmarks']:
            tags = info['tags']
            if(len(tags) > 0):
                for tag in tags:
                    if(tag in tagDict):
                        tagDict[tag] = tagDict[tag] + 1
                    else:
                        tagDict[tag] = 1
        entryDict = {'title': entryInfo['title'], 'url': entryInfo['url'], 'tagDict': tagDict}
        entryTagList.append(entryDict)
    return entryTagList

マイブックマークのタグについて、5回以上登録されているものを出現頻度順ソートしてみます。

Google App Engine 19
Scala 13
java 11
business 9
tips 8
資料 8
programming 7
eclipse 7
webサービス 6
security 6
development 6
neta 5
Java 5
javascript 5
学習 5
Amazon EC2 5

この結果を見る限り、半年以上前の私はGAEやScalaJava系の技術に興味を持っていることが分かります。ここに出てくるようなタグがより多く登録されているエントリーがオススメとして推薦されるはずです。本来は大文字と小文字、略字等の情報を統合して計算すべきですが、それはエンジンの精度を上げる段階でやっていくことにします。

類似度の計算を行う

今回の本題である類似度計算を行います。

#2つのデータセットの中からキーの重複するものをリストとして返す
def getKeyList(myTagDict, entryTagDict):
    keyList = []
    for myTagKey in myTagDict.iterkeys():
        if(myTagKey in entryTagDict):
            keyList.append(myTagKey)
    return keyList

#キーリストに存在するデータを順位付けして返す
def getRank(keyList, tagDict):
    beforeDict = {}
    sortedDict = {}
    for key in keyList:
        beforeDict[key] = tagDict[key]
    count = 1
    for key, value in sorted(beforeDict.items(), key=lambda x:x[1], reverse=True):
        sortedDict[key] = count
        count += 1
    return sortedDict
    
#スピアマンの順位相関係数を用いて類似度の計算を行う
def getSpearman(myTagDict, entryTagList):
    result = {}
    for entryDict in entryTagList:
        entryTagDict = entryDict['tagDict']
        keyList = getKeyList(myTagDict, entryTagDict)
        #重複するタグが2種類以上ある場合のみ計算を行う
        keyCount = len(keyList)
        if(keyCount > 1):
            d = 0
            myTagRank = getRank(keyList, myTagDict)
            entryTagRank = getRank(keyList, entryTagDict)
            for myTagKey, myTagRank in myTagRank.iteritems():
                r = myTagRank - entryTagRank[myTagKey]
                d += pow(r, r)
            spearman = 1 - (6 * d) / (keyCount * (pow(keyCount, keyCount) - 1))
            result[entryDict['title']] = spearman
    return result

これで類似度の計算ができるようになった・・・はず!

さっそく2011年1月1日19時近辺のIT関連ホットエントリーとマイブックマークの類似度を計算し、降順ソートで表示してみます。

Score: 1.0 title: LAN内で使用中のIPアドレス(pingで応答があるノード)を簡易に調査するワンライナー(Linux編) - RX-7乗りの適当な日々
Score: 0.999999999985 title: あなたはいくつブクマした?2010年「はてなブックマーク 年間ランキング」 - はてなブックマークニュース
Score: 0.999999455796 title: MacをJavaScriptの開発環境にするメモ - 0xFF
Score: 0.999998425007 title: 5分で分かる JavaScript を知らない人が JavaScript の便利さを学べる記事を書いたよ - NEST :: laboratory
Score: 0.999997487085 title: ベスト・オブ・ウェブサービス2010--無料で使える10のサービス - CNET Japan
Score: 0.999997055585 title: Sooey - なぜ日本のネットベンチャーはエントランスばかりが小奇麗で、執...
Score: 0.999994611431 title:  中規模データ処理で学んだ tips - フリーフォーム フリークアウト
Score: 0.999964391134 title: エンジニアの英語勉強法 - nokunoの日記
Score: 0.99995713214 title: Internet Explorer 9 Betaに、はてなブックマークが対応
Score: 0.999781096068 title: スマートフォンオブザイヤー2010特別対談:AndroidはiPhoneに対抗するべきではない (1/3) - ITmedia +D モバイル
Score: 0.999565224455 title: Gmailをより便利に快適にしてくれるウェブアプリ9選 : ライフハッカー[日本版]
Score: 0.999379209882 title: 電子書籍で読もう:2010“無料”日本語電子書籍配信サイトまとめ - ITmedia eBook USER
Score: 0.99899333488 title: 海外向けネットショップ個人でやったら年収2億超えた:ハムスター速報
Score: 0.994513707792 title: グルーポン残飯おせちの外食文化研究所水口社長にインタビューしてみました:ネットのお話 ブログ
Score: 0.994427185082 title: アプリ購入総額6万円を超える中から厳選した私のiPhoneレギュラーアプリ50+α - iPhoneとiMacと自分と…
Score: 0.98899368385 title:  はてなブックマークの全文とタグをEvernoteに取り込む『はてブえん』 | Macの手書き説明書
Score: 0.975 title: 
「自炊の森」はシステム変更へ、プレオープンは休止、権利者への配慮を模索?

Score: 0.959041394336 title: 銀行口座を公開した結果がこれだよ!! - ビジネスから歩み去る有村
Score: 0.923076923077 title: 5分でわかる Python を知らない人が Python の便利さを学べる記事をかいたよ | HIROKI.JP
Score: 0.923076923077 title: グルーポン(GROUPON) - 2011年1月1日 バードカフェ「謹製おせち」の件について
Score: 0.923076923077 title: 新春特別企画:2011年のJavaScript ─ウェブアプリ全盛の時代へ|gihyo.jp … 技術評論社
Score: 0.923076923077 title: iPhoneの知らなかった機能
Score: 0.846153846154 title: Togetter - 「新春おせちテロ?グルーポンで買った悲劇の1万円おせちはこうして作られた」
Score: 0.596153846154 title: ラウンドアップ:2011年こそは転職で成功する--転職希望者に向けたノウハウを一気読み - CNET Japan

あががががが・・・なんか違う!

より類似度の高いものほど1.0へ近づくわけですが、この結果を見ると殆どのエントリーが1.0近い値を示しています。明らかに計算手法に不備があると考えられます。

マイブックマークとホットエントリーのタグ同士が完全一致するもののみを抽出して順位付けしたため、「あとで読む」等のジャンルに関係ないものも混じってしまったのがいけなかったのでしょうか。重複しないものについても順位付けした上で、改めて完全一致するものについて係数を求めるべき・・・?

いずれにせよ、精度が低いことには間違いありません。より精度を高くするため、タグに対してフィルタリングを掛けた上で、アルゴリズムについても調べ直す必要がありそうです。

改良に向けて

今回は精度が出ないダメエンジンを作ってしまったため、今後より精度が高くなるよう改良を加えていく必要があります。

以下に改良すべき点を羅列。

  • cron等で定期的にホットエントリーを収集し、テキストファイルまたはDBにデータを保持できるようにする
  • 記事のジャンルと関係ないタグについてフィルタリングを掛けるようにする
  • ユーザーから得られるデータが少量であっても、大量の母集団に対してある程度精度の高い結果を出せるアルゴリズムを探してみる
  • エラー処理をちゃんと実装する
  • 私以外のユーザーでもオススメエントリーを提示できるようにする

とりあえず今月は今回実装したコードを上記基準で改良していくことにします。

久しぶりにまともにコードを書いて・・・

とてもたのしかったです。

参考

WEB+DB PRESS Vol.57

WEB+DB PRESS Vol.57

アルゴリズム実践教室第2回「レコメンドエンジン開発に挑戦」を参照。
集合知イン・アクション

集合知イン・アクション

Pythonにさわってみる

読んでみたい書籍の幾つかはPythonで書かれているため、まずはPythonに触れて文法を覚えいくことにしました。

UbuntuにはデフォルトでPythonが入っているため、まずはバージョンを確認。

$ python --version
Python 2.6.6

調べてみたところ最新版は2.7.xと3.1.xの模様。バージョン3からは大きな変更が加わっているという話だったので、まずは2系の習得から。

$ python

対話モード起動。文法の確認程度ならこのモードで十分できそうです。

で、文法の確認

まずは基本。

>>> print "Hello World"
Hello World

でた。

ただ3系では上記の記述は使えないらしいです。

$ python3.1
>>> print "Hello World"
  File "<stdin>", line 1
    print "Hello World"
                      ^
SyntaxError: invalid syntax

なるほど、エラーになりました。

print関数のみに変更されたってことで、

>>> print("Hello World")
Hello World

これなら両バージョンで行けるようです。

ただイチイチ変更点を確認していると時間掛かりそうなので、なるべく3系のことは意識せずに進めていきます。

>>> a = 1
>>> type(a)
<type 'int'>
>>> b = "2"
>>> type(b)
<type 'str'>
>>> c = a + int(b)
>>> print(c)
3
>>> c * c #乗法
9
>>> c ** c #べき乗
27
>>> c % 2 #剰余
1
>>> c / 2 #除法
1
>>> c / 2.0 #型変換は自動的に行われないらしい
1.5
>>> type(3/2)
<type 'int'>
>>> type(3/2.0)
<type 'float'>
>>> type(2147483647)
<type 'int'>
>>> type(2147483648)
<type 'long'>

変数への代入、型の確認・変換、四則演算はこんなところ。他にもブール型、None型?、複素数型なんてものもあるようです。

注意すべきは整数同士の割り算をする場合、明示的に小数点をつけておかないと、思ったのとは違う結果になってしまうこと。

>>> a = [1,2,3,4,5,"6","あいう",[7,8,9]]
>>> for i in a:
... print(i)
  File "<stdin>", line 2
    print(i)
        ^
IndentationError: expected an indented block

Pythonではインデントも文法に組み込まれているため、そのあたりの規則を守れない悪い子は怒られる!

>>> for i in a:
...     print(i) #Pythonではインデント重要
... 
1
2
3
4
5
6
あいう
[7, 8, 9]

リストに色々な型を入れられるってのは面白いですね。

>>> a = [1, 2] #変更可能なリスト
>>> b = (1, 2) #変更できないタプル
>>> print a, b
[1, 2] (1, 2)
>>> a.append(3)
>>> b.append(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'
>>> print a, b
[1, 2, 3] (1, 2)

あとはキーバリューを扱う辞書型、集合を扱うセット型なんかもあるようです。

今回はサラッと流しながら確認したので、次からは実際にコードを読んだり書いたりしながら使い方を覚えていくことにします。

再開

突然音沙汰なくって申し訳ありませんでした。

家の事情により職業プログラマーを断念しましたが、時間が経つにつれ続けていきてーって気持ちが強くなってきたので、ちょっとリハビリでもしていこうと思います。

2010年の課題

新年あけましておめでとうございます。

昨年様々な勉強会に参加し、素晴らしい技術者の方々と交流を持ったことで、自分の目指すべき地点、課題が見えてきたので、今年はそれを一つ一つクリアしていきたいと思っています。以下に羅列。

1. プログラミング基礎能力の強化

私がプログラミングを始めて1年半弱、実務の中で目の前の課題を解決するためにコードを書いてきたので、オブジェクト指向だとか、コンピュータサイエンスの基礎だとかいった知識が欠落しています。

今年は特にオブジェクト指向、軸にする言語と決めているJava周りを強化していきます。

具体的には

あたりの書籍を読んでいく予定です。Effective Javaは正確には2周目ですが、前回さっぱり理解できなかったのでリベンジ。

他にオススメがあれば、教えていただけると幸いです。

2. クラウドコンピューティングの情報収集

上の課題に絡んできますが、私は遅れて業界に入ってきたため、業務で勝負できる土台を何も持っていません。その土台を比較的新しいクラウドコンピューティングという技術で補っていければ、と考えています。

名古屋で定期的に行っていくGoogle App Engine勉強会のため、Google App Engineについての学習は勿論、将来業務にクラウドコンピューティング絡んでくることを予想して、Amazon EC2/S3、Windows Azureといったサービスについても触れておきたいです。

Amazon EC2については、Reserved Instancesで長期契約をしたため、環境構築や仮想サーバの運用について時々書いていこうと思います。

3. 技術ネタ以外の情報収集

テレビを「そーい!」と捨て去り、一般のニュースも殆ど見なくなってしまったため、世間の情報に恐ろしく疎くなってしまった2009年。

今年はリア充に近づくべく、経済誌や情報誌なども読んでおこうと思います。

4. コミュニティ活動

昨年末にGoogle App Engineの勉強会を主催、また名古屋Scala勉強会を共同主催、名古屋アジャイル勉強会スタッフとして活動、これらの活動を継続して行っていきたいです。

他に各勉強会への参加や、今年お世話になった名古屋のコミュニティへ何か貢献できるよう活動していきます。

5. レコメンデーションエンジン実装

集合知イン・アクション」と「集合知プログラミング」を教本に、レコメンデーションエンジンの実装過程を通じて検索、クローラ、テキスト解析等の基礎技術に触れておきたいです。

かなり敷居の高い課題ですが、数年掛けて粘り強くやっていきます。

6. 他言語の習得

Java以外の引き出しも用意しておきたいため、昨年はGroovyとScalaに手を出しましたが、それに加えて今年はPythonもちょこっと手を出していこうと思います。

GroovyとScalaはちょっとしたスクリプトJavaの補助言語として。Pythonは読みたい本がPythonで書かれているから、という理由ですので、それぞれの用途に十分な条件を満たすレベルに留め、足を突っ込みすぎて器用貧乏にならないよう気をつけたいところです。

7. ランニング

1ヶ月あたり50kmが目標。

まとめ

以上、7つの課題は下に行くほど趣味の度合いが強くなっているため、優先順位も上からになります。

ということで、今年もよろしくお願い致します。