python/集合知3章

2009/02/08からのアクセス回数 5304

はじめに

pythonを使っていて感じるのは、便利だけどパッケージがマシンに依存し過ぎている ように思われます。

例えば、スクリプトを別のマシンで動かそうとしたときに、パッケージのインストールから はじめなくてはならないときに痛烈に感じます。

そこで、ここではjythonとjavaを使ってpythonのマシン依存部分をjavaのクラスとjythonの スクリプトでラップしてみようと思います。

日本語の分かち書き

python/集合知3章と同様に、ブログに対する日本語処理からはじめます。

senのインストール

chasenと同様の機能を持つjavaのライブラリにSenがあります。 残念ながら、maven2のパッケージとして提供されていないので、java.netのsenのドキュメント&ファイルページからsen-1.2.2.1.zipをダウンロードしてください。

  • ZIPファイルの解凍

ここでは、

  • ダウンロードしたファイルは、~/Downloadedディレクトリ
  • 解凍先は、~/localディレクトリ

にあるものとして説明します。

  • unzipで解凍します
$ cd ~/local/
$ unzip ~/Downloaded/sen-1.2.2.1.zip
$ cd sen-1.2.2.1/
  • 辞書の作成 つぎにantを使って辞書を作成します。
  • 辞書の作成にはperlが必要です。ここでは/usr/bin/perlを使います。
$ cd dic
$ ant -Dperl.bin=/usr/bin/perl
  • jarファイルのmaven2への登録 最後にsen.jarファイルをmaven2で利用できるようにローカルディポジトリに登録します。
$ cd ../lib
$ mvn install:install-file -Dfile=./sen.jar -DgroupId=sen \
           -DartifactId=sen -Dversion=1.0 -Dpackaging=jar

pythonlibの作成

作成したライブラリは1つのjarにまとめておくとjythonから利用するときに便利です。

ここでは、pythonlibというEclipseのプロジェクトをmaven2を使って作成します。

  • プロジェクトの作成

最初にjythonlibのプロジェクトを作成します。

$ mvn archetype:create -DgroupId=jythonlib -DartifactId= jythonlib -Dversion=0.1
  • pom.xmlの編集

pom.xmlを編集して、sen.jar, common-logging.jarを使えるようにします。 以下の定義をdependenciesに追加

    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1.1</version>
    </dependency>
    <dependency>
      <groupId>sen</groupId>
      <artifactId>sen</artifactId>
      <version>1.0</version>
    </dependency>

次にbuildを追加し、javaのバージョン、UTF-8の設定、jarファイルの設定、依存ライブラリのコピーをセットします。

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>    
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
           <archive>
            <manifest>
              <mainClass>jythonlib.Sen</mainClass>
              <packageName>jythonlib</packageName>
              <addClasspath>true</addClasspath>
              <addExtensions>true</addExtensions>
              <classpathPrefix>./lib</classpathPrefix>
            </manifest>
          </archive>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}/lib</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>  
  </build>

この設定は、結構役に立ちますから、覚えておいた方がいいですよ。

  • Eclipseプロジェクトに対応 以下のコマンドで、Eclipseの.projectと.classpthを作成します。
$ mvn eclipse:eclipse -DdownloadSources=true

Senクラスの作成

senの形態素解析を実行し、jythonにその結果を返すクラスSen.javaを作成します。

変換部分は、

	private String[] parts = {"形容詞", "形容動詞", "副詞", "連体詞", "名詞", "動詞"};
	public List<String> sparse(String text) {
		List<String> list = new ArrayList<String>();
		try {			
			StringTagger tagger = StringTagger.getInstance();
			Token[] token = tagger.analyze(text);
			String	term = null;
			for (int i = 0; i < token.length; i++) {
				// 未知語、英語の単語
				if ((term = token[i].getTermInfo()) == null) {
					list.add(token[i].getSurface());
				}
				else {
					for (String part : parts) {
						if (term.startsWith(part)) {
							list.add(token[i].getBasicString());
							break;
						}						
					}
				}
			}

		} catch (Exception e) {
		}
		return (list);
	}

と簡単です。

Jythonとjava間の日本語処理

jythonとjavaとの日本語は、結構大変です。ここでは以下の方針で文字を渡すことに します。

  • jythonからjavaへは、UTF-8でエンコーディングされたバイト文字列を渡す javaでの変換は以下のようになります。
    jTxt = String(txt, "utf-8")
    
  • javaからjythonへは、unicodeにエンコーディングされた文字列を渡す javaでの変換は以下のようになります。
    uTxt = String(word.getBytes('utf-8'), 'iso-8859-1')
    

sen用のsplitメソッドをsplit.pyに以下のように定義します。

# -*- coding: utf-8 -*-
import japanese
import codecs
import jarray
import jythonlib.Sen
import java.lang.String
from java.lang  import *

parts = ["形容詞", "形容動詞", "副詞", "連体詞", "名詞", "動詞"]
parts = jarray.array([String(part, "utf-8") for part in parts], java.lang.String)

def split(txt):   
    jTxt = String(txt, "utf-8")
    sen = jythonlib.Sen(parts)
    words = sen.sparse(jTxt)
    outList = []
    for i in range(len(words)):
        word = String(words.get(i))
        outList.append(String(word.getBytes('utf-8'), 'iso-8859-1'))
    return outList

動作確認

senを使った分かち書きのテストをします。

# -*- coding: utf-8 -*-
import japanese
import split

txt = "オリジナルのソースは、原書著者TobesのページからPCI_Code.zipと してダウンロードできます。"
print txt
words = split.split(txt)
for word in words:
    print word

を実行すると、

オリジナルのソースは、原書著者TobesのページからPCI_Code.zipと してダウンロードできます。

オリジナル
ソース
原書
著者
Tobes
ページ
PCI
_
Code
.
zip
する
ダウンロード
できる

と出力されます。

chasenと比べると英語の文字も正しく処理されること、「から」が名詞ではなく正しく助詞? として認識されています。

コメント

この記事は、

選択肢 投票
おもしろかった 0  
そうでもない 0  
わかりずらい 0  

皆様のご意見、ご希望をお待ちしております。


(Input image string)


トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-02-08 (日) 20:53:44 (3230d)
SmartDoc