wikipediaのタイトルの読み仮名を取得する

どうも、クソアプリ Advent Calendar 2015の25日目を酔った勢いだけでとったじょんすみすです。

アプリとか作れないので昨日まで何を書くか悩んでいた

さて、最近は人工知能とか機械学習とかが流行ってますね。 みなさん魔法の杖かのように「機械学習でやりましょう!」とか「人工知能で職がなくなる」とか言っております。

ところで、有名な言葉に「データサイエンティストは21世紀で最もセクシーな職業」というものがあり、 どうやらデータサイエンティストになるにはセクシーな魔法使いである必要があるようです。

魔法使いになるには30歳まで童貞でいる必要があるので、セクシーな30歳童貞とかまさにユニコーンですね。 なお、私はユニコーンになる条件を満たしておりません(セクシー、30歳以上、童貞のどれを満たしていないかは想像にお任せします)

そんなわけで、本題に入りたいのですが、 機械学習やAIのような難解な数式を持ち出さなくても人間の経験則だけでこんなことが簡単にできちゃう事例を紹介します。

勘と経験だけで人は30万単語の読みを把握できる

エンジニアたるものコードで語りましょう。

# -*- coding: utf-8 -*-                                                                                                           
require 'rexml/document'

data = ''
File.open('jawiki-latest-abstract.xml').each do |line|
  # ファイル全体を読み込んでxmlとして処理するにはデータが大き過ぎるので                                                           
  # 一行ずつ読み込んでdocタグ単位で処理                                                                                           
  data = '' if line.include?("<doc>")
  data += line
  if line.include?("</doc>")
    doc = REXML::Document.new(data)

    # タイトルから前後の余計な文字列を取る                                                                                        
    # 末尾は「(曖昧回避)」などが含まれている場合がある                                                                            
    title =  doc.elements['doc/title'].text.gsub("Wikipedia: ", "").gsub(/\(.+\)$/, '').strip

    abstract = doc.elements['doc/abstract'].text
    next if abstract.nil?

    # 最初の括弧内が読み仮名、英語表記、略語である可能性が高い                                                                    
    kana = abstract.scan(/(.*?)/)
    if !kana.empty?
      # 読み仮名、英語表記、略語が複数ある場合によく使われる区切り文字                                                            
      kana = kana[0].slice(1...-1).split(/[,:、]/)

      kana.each do |i|
        # 仮名表記のみを取り出すことで読み仮名のみに限定                                                                          
        if !i.empty? && /^[ぁ-んァ-ン・ \-]+$/.match(i)
          # 一部いらんもじ削除                                                                                                    
          i = i.strip.gsub(/([・-]|\s)/, '')
          # カタカナをひらがなに統一                                                                                              
          hira = i.tr('ァ-ン', 'ぁ-ん')
          puts "#{title}\t#{hira}" if !hira.empty?
        end
      end
    end
  end
end

なんと、このコードはすべてemacsで書かれています!vimは一度も起動してません!

これはwikipediaのダンプデータにあるアブストラクト(※リンクをクリックすると1.7GBのxmlを取得します)を利用して簡単なルールだけでタイトルに対応する読み仮名を抽出するものです。

みなさまにおかれましては寄付をされているかは存知あげませんが普段からよくwikipediaをお使いのことと思われます。で、このwikipediaでは

例えば「近藤うどん子」に関する内容の場合、

近藤うどん子(こんどううどんこ)とは〜〜である。

のような形式で始まっているものの多いこと!おそらく人間のサガというやつでしょう。

※2015/12/25現在、wikipediaに近藤うどん子に関する記事はございません。

その性質を使うだけでおよそ30万語の読み仮名データを取得できました。一例を見てみましょう。

形式言語        けいしきげんご
文脈自由言語    ぶんみゃくじゆうげんご
正規言語        せいきげんご
自然言語処理    しぜんげんごしょり

のようなものや、

イスラエルの失われた10支族      いすらえるのうしなわれたじゅうしぞく
グラム・シュミットの正規直交化法        ぐらむしゅみっとのせいきちょっこうかほう
商法中署名スヘキ場合ニ関スル法律        しょうほうちゅうしょめいすべきばあいにかんするほうりつ
NHKデジタル衛星ハイビジョン     えぬえいちけいでじたるえいせいはいびじょん
日本国政府と中華人民共和国政府の共同声明        にほんこくせいふとちゅうかじんみんきょうわこくせいふのきょうどうせいめい

のような長いもの、

7       しち
7       ひち
7       ち
7       なな

のような同じ文字で別な読みがあるものなどとれています。

中には

SUZUKIハッピーモーニング・いってらっしゃいシリーズ      すずき
ハーディ・ガーディ      より

のような、「いや、おい!」とい言いたくなるものもありますが、まぁ仕方ないでしょう。

ちなみに、はてなキーワードのデータだと最初からキーワードと読みがセットになっているものがおよそ40万語、 ニコニコデータセットの大百科だと18万語ほど取得できます。

この処理には1.7GBあるデータをダウンロードする必要があるのと、1時間以上の処理時間が必要なので、 やってみた割にはあまり効果がないと言えるでしょう

なお、欲しい方がいるかはわかりませんが、こちらにあげておきました。 13MBあります。

で、何に使えるか?

クソアプリアドベントカレンダーのネタなのにこれを考えるのは少々無粋です。

wikipediaのタイトル自体は形態素解析の辞書に追加される例などが見受けられますが、 これに読み仮名も付与できるわけですね。

しかし、はてなキーワードより語数が少なく、ooの一覧なども抽出されている上に、 最近ではmecab-neologdというものもあります。

また、辞書の追加においては解析対象のドメインに特化したものが必要となることが多いので、その点ニコニコ大百科の方が利用シーンが多いと言えるでしょう。

そもそも世の中には便利なルビ振りAPIとかありますね。 例えばYahooのとか

なので、皆さんで勝手に御考え下さい。
ちなみにこの程度の内容であれば過去既にだれかやっていると思いますよ。

あとがき

実は他にもネタがあったんですが。。

今年は凛ちゃんの年だったので、何度かやっていた「星空凛」、「渋谷凛」、「遠坂凛」、「松岡凛」の四方に対する2chでの個別キャラスレの会話内容から、どの凛ちゃんに対する話かを予測するとかよくやってました。

こちらはslideshareに上がってるので興味がある人は頑張って探してみてくださいw(半年以上ぶりのブログ更新のためこれらに関する記事を書いていないかった)

ついでに来年やりたいネタメモ

CNNでアニメキャラの顔認識とRNNを利用したキャプションをつけるやつを使って、
キャラの画像とそのシーンでのセリフを学習させれば、キャラの性格や口癖を反映させた文章が生成できないだろうか?

というのがありますので、恵まれない私にクリスマスプレゼントとしてGPUを買ってくれる人を募集しています。 これが今回一番主張したかったことです!(というか必要なデータどうやって集めるんだこれ・・・)