Pythonのunicodedata.normalize('NFKC', x)で正規化される文字一覧

Pythonのunicodedata.normalize('NFKC', x)で正規化されて変わる文字ってどんなのがあるんだろうと思って一覧を作ってみました。

https://gist.github.com/ikegami-yukino/8186853

左が変更前の文字、右が変更後の文字(アラビア文字は左右が逆になります)、括弧内の数値はUnicode IDを表します。

(自分がわかる範囲の)ほとんどの変換結果は納得できますが、一つだけ [65374] 〜 から [126] ~に変換されるのはどうかなあと思いました。たとえばインタ〜ネットがインタ~ネットになったり。normalizeする前に〜をーに変換する前処理を加えた方がよさそう。


あとこの変換結果の前後を逆にして、メートルを㍍にするような変換テーブルを作るとTwitterみたいな文字数制限のあるとき用の文章を作るときの文字数節約に使えるかも。

Wikipedia見出しリストから不要な見出しをカットする

検索サイトで「wikipedia mecab」と検索するとWikipediaの見出しリストを整形してMeCab用辞書として使う記事が何件かhitします。
しかし、Wikipediaの見出しは形態素解析用に作られたわけではないので、形態素として扱うと不都合になることがあります。
たとえば、文書から名詞だけを抽出して文書をカテゴリに分類したいといったときに、「ロシアの音楽」という文字列を「ロシアの音楽/名詞」と解釈するよりも「ロシア/名詞 の/助詞 音楽/名詞」と解釈したほうが汎化できるので嬉しいです。

そのため不要な見出しを除去する処理を行うことにします。
まず、見出しリストをざっと見て「<国名>の法律」「<歌手>のディスコグラフィ」などの「AのB」パターンが多いことに着目しました。
そこで、AのBパターンをざっくりと抽出します。

#! /usr/bin/env python
# -*- coding: utf-8 -*-
from collections import Counter
import re
 
suffixes = Counter()
re_anob = re.compile(u'(?P<A>.+[^の])の(?P<B>[^の].+)')
re_hiragana = re.compile(u'[ぁ-&#12438;]+')
 
def extract_anob(text):
    match = re_anob.match(text)
    if match and is_valid_b(match.group('B')):
        suffixes[match.group('B')] += 1
 
def is_valid_entry(entry):
    return False if '_(' in entry else True
 
def is_valid_b(b):
    return False if re_hiragana.match(b) else True
 
if __name__ == '__main__':
    import optparse
 
    parser = optparse.OptionParser()
    parser.add_option("-f", "--filename", help="the path of input file")
    (opts, args) = parser.parse_args()
 
    for line in open(opts.filename, 'r'):
        line = line.strip().decode('utf8')
        if is_valid_entry(line):
            extract_anob(line)
    for k,v in suffixes.most_common(200):
        print k,v

AのBパターンのBの出現回数上位200件がこちら。

一覧 2256
戦い 1581
人物一覧 596
登場人物 467
歴史 452
法則 322
国旗 280
国歌 261
定理 256
国章 238
スポーツ 221
作品 199
通貨 198
地方行政区画 157
鉄道 156
音楽 153
大統領 150
世界遺産 149
軍事 146
冒険 145
廃校一覧 145
オールナイトニッポン 143
選手一覧 140
行政区画 131
航空 128
物語 125
映画 120
政治 120
同位体 117
野球 116
首相 116
政党 114
メジャーリーグベースボール 113
ワールドシリーズ 112
楽曲一覧 111
国会 110
海戦 101
宝塚歌劇公演一覧 99
ディスコグラフィ 93
日本公開映画 90
年度別成績一覧 90
世界 88
手紙 86
MLBオールスターゲーム 81
関係 80
経済 79
交通 79
逆襲 78
大冒険 77
政党一覧 77
ゲームタイトル一覧 77
年表 77
連続ドラマ 76
伝説 75
時間 75
バレーボール 73
原理 73
エピソード一覧 72
歴代選手・スタッフ一覧 71
式内社一覧 69
反乱 69
アニメ 68
奇跡 66
F1世界選手権 65
ロードレース世界選手権 65
日本シリーズ 64
ユニフォーム 64
パラドックス 61
NBA 61
教育 61
登場人物一覧 61
権利 60
恋人 59
秘密 58
合戦 56
事件簿 56
女性史 54
郡一覧 52
虐殺 52
料理 52
高等学校一覧 52
ユーロビジョン・ソング・コンテスト 52
資格者配置路線 52
アメリカ合衆国上院議員 51
国鉄 50
有名人一覧 50
廃止市町村一覧 50
MLBドラフト 49
空軍 49
悲劇 48
廃園一覧 48
NFL 48
原則 47
登場キャラクター 47
ナショナルリーグチャンピオンシップシリーズ 46
肖像 46
市町村章一覧 46
野望 46
地理 45
文化 45
アメリカンリーグチャンピオンシップシリーズ 45
県道一覧 45
騎士 44
日々 43
文学 42
テーマ 41
世界ラリー選手権 41
誓い 41
公式 41
大学一覧 41
ニュース 40
灯台一覧 40
海軍 39
二級水系一覧 39
比較 39
日本競馬 38
方程式 37
国・地域別メダル受賞数一覧 37
王様 37
少女 37
時代 37
博物館 36
季節 36
オールナイトニッポンR 36
野鳥一覧 36
町名 36
中で 35
陸軍 35
自由 35
天使 34
観光地 34
カメラ製品一覧 34
人々 34
女王 33
議会 33
森公園 33
殺人 33
和約 33
科学 32
自転車競技 32
チーム記録 32
警察 31
陰謀 31
大統領一覧 31
部屋 31
歴代監督一覧 31
祈り 31
下で 30
促進に関する法律 30
問題 30
花嫁 30
政変 30
日本 30
NBAドラフト 30
サッカー選手一覧 30
約束 29
迷宮 29
記憶 29
リスト 28
韓国シリーズ 28
競馬 28
呪い 28
宇宙飛行 28
元素 28
相撲 28
ラジオ 27
事件 27
JSL 27
図書館一覧 27
聖母 27
スーパーバイク世界選手権 26
ワイン 26
渡し 26
作品一覧 26
神話 26
日記 26
青春 26
理論 26
用語一覧 26
宗教 25
女神 25
挑戦 25
憲法 25
ユーロ硬貨 25
電車 25
秘宝 24
殿堂 24
戦争 24
企業一覧 24
通り 23
兵器 23
結婚 23
Jリーグ 23
全日本F3選手権 23
王国 23
サッカー 23
復讐 23
誕生 22
紋章 22
アリス 22

右の数字は出現回数です。

このうち一語の固有名詞として扱ったほうがいいもの(たとえば、**の冒険とか**の紋章とか)を人手で判断しました。
判断の補助としてmarisa-trieを使ってsuffixの検索を行うスクリプトを使いました。

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import marisa_trie
import os
 
def is_valid_entry(entry):
    if '_(' in entry:
        return False
    return True
 
def build_trie(filename):
    reversed_entries = []
    for line in open(filename, 'r'):
        line = line.strip().decode('utf8')
        if is_valid_entry(line):
            reversed_entries.append(line[::-1])
    trie = marisa_trie.Trie(reversed_entries)
    trie.save('wikipedia_reverse.marisa')
 
if __name__ == '__main__':
    import optparse
 
    parser = optparse.OptionParser()
    parser.add_option("-f", "--filename", help="the path of input file")
    (opts, args) = parser.parse_args()
 
    if not os.path.exists('wikipedia_reverse.marisa'):
        build_trie(opts.filename)
    trie = marisa_trie.Trie()
    trie.load('wikipedia_reverse.marisa')
    while True:
        text = raw_input('>').decode('utf8')
        for i in trie.keys(text[::-1]):
            print i[::-1]


こうした作業によってできたリストがこちらです。見出しリストをMeCab用辞書に整形するときにこれを読み込んでlist型にして'文字列'.endswith(wikipedia_stop_suffixes)とかやって不要な見出しを弾くといいと思います。

一覧
の登場人物
の歴史
の国旗
の国歌
の国章
のスポーツ
の作品
の通貨
の鉄道
の音楽
の大統領
の世界遺産
の軍事
のオールナイトニッポン
の航空
の映画
の政治
の同位体
の野球
の首相
の政党
のメジャーリーグベースボール
のワールドシリーズ
の国会
のディスコグラフィ
の日本公開映画
のMLBオールスターゲーム
の関係
の経済
の交通
の年表
の連続ドラマ
のバレーボール
のアニメ
の奇跡
のF1世界選手権
のロードレース世界選手権
の日本シリーズ
のユニフォーム
のパラドックス
のNBA
の教育
の女性史
の料理
のユーロビジョン・ソング・コンテスト
の資格者配置路線
のアメリカ合衆国上院議員
の国鉄
のMLBドラフト
の空軍
のNFL
の登場キャラクター
のナショナルリーグチャンピオンシップシリーズ
の地理
の文化
のアメリカンリーグチャンピオンシップシリーズ
の文学
の世界ラリー選手権
のニュース
の海軍
の比較
の日本競馬
のオールナイトニッポンR
の町名
の陸軍
の観光地
の女王
の議会
の科学
の自転車競技
のチーム記録
の警察
の促進に関する法律
の問題
の政変
のNBAドラフト
のリスト
の韓国シリーズ
の宇宙飛行
の元素
の相撲
の年のラジオ
の事件
のJSL
のスーパーバイク世界選手権
の憲法
のユーロ硬貨
の電車
の戦争
の通り
の兵器
のJリーグ
の全日本F3選手権
のサッカー

今回のスクリプトや結果はgistにも置いてます。
https://gist.github.com/ikegami-yukino/8042385

ただ、これだけだとまだまだ不要見出し残ってるので、あとでまた何か書くかも。

SWIGによるOLLのPythonバインディング

SWIGによってオンライン機械学習ライブラリOLLをPythonで使うモジュールを公開しました( ´ ▽ ` )ノ
https://pypi.python.org/pypi/oll
前回のファイルを経由するのとは違ってSWIGでOLLを使うので効率的です。

pipが入っていれば以下のコマンドでインストールできます(要C++コンパイラ)。

$ pip install oll

ソースコードは以下URLにて公開しています。
https://github.com/ikegami-yukino/oll-python

PythonでOLLを使う

オンライン機械学習ライブラリのOLLPythonで使うためのクライアントモジュールを公開しました!
https://pypi.python.org/pypi/oll_client

これはPythonでoll_lineの入出力を扱うモジュールです。
swigとかよくわからないのでoll_lineへの入力は標準入力を、出力はファイルから読み込むという強引な実装で、一時ファイルを生成するかっこ悪い感じになってます

もっと効率的なOLLモジュールを作ったのでそっちを推奨します。http://d.hatena.ne.jp/expectorate/20131011/1381518642

ソースコードは以下URLにて公開しています。
https://gist.github.com/ikegami-yukino/6102212

ショートカットキーで漢字をひらがなに変換 for Mac

MacAutomatorから「選択した文字列から漢字をひらがなに変換する」サービスを作ってショートカットキーで呼び出す方法を紹介します。
実行にはMeCabnkfのインストールが必要になります。

手順

  • Automatorの起動
  • [Ctrl]と[Space]同時押しで出てくるSpotlightからAutomatorって入れると早い
  • サービスを作る
  • ユーティリティ > "シェルクスクリプトを実行"というアクションを選んで右のあいてることろにドラッグアンドドロップ
  • 以下のコマンドを入力
    • パスは適宜変更してください
echo $1| /usr/local/bin/mecab -E "" --node-format="%f[7] "| /opt/local/bin/nkf -w --hiragana


  • "選択されたテキストを出力で置き換える"にチェック
  • "入力の引渡し方法"を”引数として”にする
  • 名前をつけて保存
  • ショートカットキーの設定
    • "システム環境設定" を開いて、"キーボード"項目の"キーボードショートカット"タブをクリック
    • 左カラムのサービスを選ぶと右カラムにさっき保存したサービスがあるので、すきなショートカットキーを設定

参考: Mac を使っているなら必ず使うべき2つの機能 "Automator" と "サービス" - kurainの壺

Mountain Lionに入れるもの

備忘録

MacPortsから

ライブラリ

sudo pip install beautifulsoup4
sudo pip install matplotlib
sudo pip install python-tumblpy
sudo pip install tweepy
easy_install flickrapi

エディタ

ChocolatePapaya

茶色くて見やすいvim用テーマ
http://vim.sourceforge.net/scripts/script.php?script_id=1922
MacVimへの適用

$ mkdir ~/.vim
$ mkdir ~/.vim/colors
$ cp ~/Downloads/ChocolatePapaya.vim ~/.vim/colors/
$ echo colorscheme ChocolatePapaya > .gvimrc

ディスクからインストール

その他

MendeleyDesktop

http://www.mendeley.com/

f.lux

it makes the color of your computer's display adapt to the time of day, warm at night and like sunlight during the day.

https://justgetflux.com/

TNEF's Enough

TNEF's Enough allows Macs to read and extract files from Microsoft TNEF stream files. The files are usually received by SMTP based e-mail programs from Microsoft Exchange and Microsoft Outlook users.

http://www.joshjacob.com/mac-development/tnef.php

VLC

VLCはフリーなマルチプラットフォーム対応のマルチメディアプレイヤーであり、DVD、オーディオCD、VCDや様々なストリーミングプロトコルを再生可能なフレームワークです。

http://www.videolan.org/vlc/

What’s Up!

What’s Up!はDynamic DNSサービスのIPアドレスを自動更新するDynamic DNSクライアントです。

http://soft.macfeeling.com/what_s_up.html

AppStoreから入手

  • Echofon
  • The unarchiver
  • WinArchiver Lite
  • Microsoft Remote Desktop
  • スケッチ風ドロー

コマンドラインツール

Byobu

Byobu is a GPLv3 open source text-based window manager and terminal multiplexer.

http://byobu.co/

Pythonで少し速くひらがな・カタカナ・半角・全角文字を相互変換する

NLPをやってると文字の正規化処理でひらがな・カタカナ・半角・全角変換することがあります。
そこでPythonでひらがなからカタカナ、カタカナからひらがな、半角文字から全角文字、全角文字から半角文字に高速変換するライブラリjctconvをPyPIにアップしました。
https://pypi.python.org/pypi/jctconv/


そこでjctconvと既存の文字種変換モジュールで比較してみました。

# -*- coding: utf-8 -*-

# 他のひらがなカタカナ変換と比較
if __name__ == '__main__':
	import time

	loop = 100000

	print u'ひらがなからカタカナに変換'
	text = u'ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをんァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ'

	# jctconv(わたしのスクリプト)
	import jctconv
	start = time.clock()
	for i in xrange(loop):
		jctconv.hira2kata(text)
	print '\tjctconv:',
	print time.clock()-start

	# http://d.hatena.ne.jp/mohayonao/20101213/1292237816
	import mohayonao
	start = time.clock()
	for i in xrange(loop):
		mohayonao.katakana(text)
	print u'\tmohayonaoさん:',
	print time.clock()-start

	# https://github.com/yuka2py/cnvk
	import cnvk
	start = time.clock()
	for i in xrange(loop):
		cnvk.convert(text, cnvk.HIRA2KATA, cnvk.Z_KATA)
	print '\tcnvk:',
	print time.clock()-start

	# http://pypi.python.org/pypi/jcconv/0.1.6
	import jcconv
	start = time.clock()
	for i in xrange(loop):
		jcconv.hira2kata(text)
	print '\tjcconv:',
	print time.clock()-start
	
	
	print u'\n半角から全角に変換'
	text = u'アイウエオあいうえお'
	
	# jctconv(わたしのスクリプト)
	import jctconv
	start = time.clock()
	for i in xrange(loop):
		jctconv.normalize(text,'NFKC')
	print '\tjctconv:',
	print time.clock()-start

	# https://github.com/yuka2py/cnvk
	import cnvk
	start = time.clock()
	for i in xrange(loop):
		cnvk.convert(text, cnvk.Z_KATA)
	print '\tcnvk:',
	print time.clock()-start

	# http://pypi.python.org/pypi/jcconv/0.1.6
	import jcconv
	start = time.clock()
	for i in xrange(loop):
		jcconv.half2kata(text)
	print '\tjcconv:',
	print time.clock()-start

	# http://pypi.python.org/pypi/jcconv/0.1.6
	import zenhan
	start = time.clock()
	for i in xrange(loop):
		zenhan.h2z(text)
	print '\tzenhan:',
	print time.clock()-start

	# http://pypi.python.org/pypi/jcconv/0.1.6
	import unicodedata
	start = time.clock()
	for i in xrange(loop):
		unicodedata.normalize('NFKC', text)
	print '\tunicodedata:',
	print time.clock()-start

MacBook Air2012全部載せ(Intel Core i7 2.0Ghz / DDR3-8GB)で実行
結果

ひらがなからカタカナに変換
	jctconv: 5.259766
	mohayonaoさん: 8.502345
	cnvk: 15.094356
	jcconv: 34.587817

半角から全角に変換
	jctconv: 0.421827
	cnvk: 6.358533
	jcconv: 29.451795
	zenhan: 1.638667
	unicodedata: 0.251975

素のunicodedata以外に勝ったヽ(´ー`)ノ