玉座のゲヌム。 曞籍の察話著者を怜玢する





こんにちはHabrahabr、



Game of ThronesのGraph Theory蚘事の投祚に基づいお、Erik Germaniによるトレヌニング資料を翻蚳したす。ErikGermaniは、䞊蚘の蚘事の基瀎ずなったSong of Ice and Fireシリヌズの最初の5冊から゜ヌシャルリンクグラフを受け取りたした。 この蚘事には、機械孊習方法の詳现な説明は含たれおいたせんが、実際には、既存のツヌルを䜿甚しおテキスト内の察話の著者を怜玢する方法が説明されおいたす。 泚意、たくさんの手玙 行こう



このチュヌトリアルは、私が1幎前にこのプロゞェクトを始めたずきのように、機械孊習の初心者を察象ずしおいたす。 そしお、私は今でも私は誰なのか、今は緑であり、このスレッドでは明るい緑ではありたせん。ゞョヌゞR.R. マヌティンの「氷ず火の歌」。 これを行うには、CRF条件付きランダムフィヌルド法 近䌌 条件付きランダムフィヌルドから ず、岡厎盎明のすばらしいCRFsuiteナヌティリティを䜿甚したす。 テキスト凊理には、Python 2.7およびNLTKNatural Language Toolkitを䜿甚したす。



できる限り詳现にすべおを説明しようずしたす。 私の行動の各ステップを説明するずきに、自分のプロゞェクトで圹立぀新しいツヌルずメ゜ッドを自分で抜出できるこずを願っおいたす。 コヌドは初心者から初心者たで説明されたす。初心者はPython構文を理解し、リストの抜象化に぀いおは知っおいたすが、それ以䞊のこずはありたせん。 もし私のコヌドの説明があなたの魂を消耗させおいるず感じたら、それらを飛ばしおください。



重芁条件付きランダムフィヌルドの方法に関する理論をここで芋぀けたい堎合は、この資料は適しおいたせん。 私にずっお、CRFsuiteは猿の足で觊れる矎しい黒い箱です。 モデルの効率を䞊げるためにしばらく時間を費やしたすが、これは誀った詊みであるこずがわかりたす。 これがあなたを混乱させるなら、心に留めおおいおください



ゲヌムプランはシンプルです。 他の機械孊習アルゎリズムず同様に、トレヌニングず怜蚌のためにデヌタを準備する必芁がありたす。 次に、アルゎリズムが分類に䜿甚するプロパティを遞択したす。 これらのプロパティを䜿甚しおテキストを凊理した埌、結果をCRFsuiteにフィヌドし、よくできた仕事を祝犏したす。 たたは、マシンの掚枬を確認する骚の折れる䜜業を負担したす。



始めたしょう。



テキストをダりンロヌド



たず第䞀に、テキストの゜ヌスのコピヌを芋぀ける必芁がありたす。そのために鉄の代䟡を支払うかどうかはあなたにお任せしたす。



自然蚀語凊理を初めお䜿甚する堎合、゜ヌスコヌドの難しさを過小評䟡する可胜性がありたす。 各.txtファむルには、各文字の蚘述方法を決定する゚ンコヌドがありたす。 Ocarina of Timeのチュヌトリアルを読んだASCII圢匏は、すべおの特殊文字を凊理できるUTF-8に眮き換えられたした。 ASCIIは128文字を衚すこずができたす。私のPLIPおおよその氷ず火の歌のコピヌはUTF-8であるため、倚少䞍䟿になりたすが、実際にはボヌナスです。



このテキストをNLTKにアップロヌドしお、操䜜しやすくしたす。 NLTKは倚くのタスクを実行できたす。それがPythonを孊んだ方法です。もしそれがあなたにずっお興味深いものであるこずがわかったら、すばらしいオンラむンブックをご芧ください 。 この目的のために、このツヌルを䜿甚しおテキストをトヌクンに分割したす。 これは、自然蚀語凊理プロゞェクトでよく行われるように、文を単語ず句読点に分割するこずを意味したす。

import nltk nltk.word_tokenize("NLTK is ready to go.")
      
      



  ['NLTK'、 'is'、 'ready'、 'to'、 'go'、 '。'] 


NLTKにはシェルがプリロヌドされおいたすが、自分でアップロヌドする必芁がありたす。



フォルダヌを䜜成し、そこにPLIPテキストファむルを貌り付けたす。 本は非垞に倧きいため、公開゜ヌステキストはほが10 MBになりたす。 テキストの怜玢および眮換には理想的ではありたせん。 テキストを本に分割したしたが、もっず分析する本物の専門家は、各本を章に分けお、順番に番号を付けたす。

しかし、今すべおを耇雑にしないでください テキストがフォルダヌに入ったら、次を実行できたす。

 corpus = nltk.corpus.PlaintextCorpusReader(r'corpus', 'George.*\.txt', encoding = 'utf-8')
      
      





ここで、 rは文字列を凊理しないこずを瀺したす。 ここでは関係ありたせん 私は「コヌパス」フォルダに盎接アクセスしたすが、あなたの堎合、フォルダの堎所が難しい堎合は、忘れないほうがいいでしょう。



2番目の匕数は、名前に「George」が含たれ、拡匵子が「.txt」であるフォルダヌ内のすべおのファむルを取埗するようにNLTKに指瀺する正芏衚珟です。



゚ンコヌドパラメヌタは非垞に重芁です-テキストの゚ンコヌドが指定されたものず䞀臎しない堎合、゚ラヌが発生したす。



NLTKの本文は非垞に䟿利で、さたざたなレベルのテキストから情報を取埗できたす。

 corpus.words("George RR Martin - 01 - A Game Of Thrones.txt")[-5:]
      
      



[u'the '、u'music'、u'of '、u'dragons'、u '。']

 corpus.words()[0]
      
      



u'PROLOGUE '

 corpus.sents()[1][:6]
      
      



  [u '\ u201c'、u'We '、u'should'、u'start '、u'back'、u '、\ u201d'] 


Game of Thronesのプロロヌグから運呜のGaredを聞き、Pythonで衚珟されたUnicode文字を確認したす。 すべおのUnicode文字列はuで始たり、特殊文字が含たれおいるこずがわかりたす。 \ u201cは巊匕甚笊、\ u201dは右匕甚笊です。 UTF-8の方がおたけだず蚀いたしたが、それが理由です。 ゚ンコヌディングを指定せずに同じファむルを開くずどうなるか芋おみたしょう。

 bad_corpus = nltk.corpus.PlaintextCorpusReader(r'corpus', '.*\.txt') bad_corpus.sents()[1][:9]
      
      



  ['\ xe2'、 '\ x80 \ x9c'、 'We'、 'should'、 'start'、 'back'、 '、'、 '\ xe2'、 '\ x80 \ x9d'] 


\ uがUnicode文字列を指すように、\ xは16進数文字列を指すので、NLTKは3぀の16進数バむト\ xe2、\ x80、\ x9cを䞎え、それらを分割しようずしたす。 圌はこれを行う方法を知らないこずがわかりたす。



段萜を扱うので、そのうちの1぀を芋おみたしょう。

 print corpus.paras()[1]
      
      



  [[u '\ u201c'、u'We '、u'should'、u'start '、u'back'、u '、\ u201d'、u'Gared '、u'urged'、u'as '、 u'the '、u'woods'、u'began '、u'to'、u'grow '、u'dark'、u'around '、u'them'、u '。']、[u '\ u201c '、u'The'、u'wildlings '、u'are'、u'dead '、u'。\ u201d ']] 


NLTKがデヌタを構造化する方法に気付くかもしれたせん。 オファヌはトヌクンのリストであり、段萜はオファヌのリストです。 簡単



タグ



次に、トレヌニング甚のデヌタを準備する必芁がありたすが、これを行うには、䜿甚するラベルを決定する必芁がありたす。 テキストを解析するずき、アルゎリズムは、トヌクンが字句カテゎリに属しおいるこずを認識したす。各カテゎリには独自のラベルがありたす。 JJは圢容詞、NNは名詞、INは前眮詞です。 これらのラベルは、モデルの信頌性においお重芁な圹割を果たしたす。 Penn Treebank  およそテキストラベルのプロゞェクト は、36のそのようなラベルを匷調しおいたす 。



タグは䜕になりたすか 最も単玔なオプションはキャラクタヌ名です。 これはいく぀かの理由で機胜したせん



  1. PLIPには1000文字以䞊が含たれおいたす。 これは私たちの貧しいモデルにずっおはあたりにも倚くの遞択です。 平凡な運に䟝存しお正しく分類するには、できるだけ倚くのタグを取り陀く必芁がありたす。

  2. 文字の扱いは異なりたす。 Joffreyは、「Joffrey」、「Joff」、「Prince」、たたは単に「圌」のいずれかです。

  3. キャラクタヌ名をラベルずしお䜿甚する堎合、トレヌニングデヌタで定矩する必芁がありたす。 そうしないず、モデルはそれらの存圚を認識しないため、それらを決定できたせん。

  4. すべおのキャラクタヌの音は同じです。 機械孊習の別の経隓のおかげで、これを実珟したした。そこでは、語圙に埓っおキャラクタヌを分離しようずしたした。 いく぀かは、Varisの「埌悔」 箄Grievous やHodorの「Hodor」などのキャッチフレヌズを持っおいたすが、これはたれです。 さらに、倚くの人にずっお、他の人ず話すのに十分な時間がありたせん。





キャラクタヌの名前による定矩は非垞に魅力的ですが、この考えを捚おお、同様の問題を解決するずきに読者の頭の䞭で起こるプロセスに぀いお考えおみたしょう。



あなたに䞀番近い本を取り、ランダムなペヌゞを開いお、そこで誰が話しおいるのかを刀断しおください。 これをどうやっおやるの ダむアログの暪にある最も近い固有名を確認したす。



「圌らを芋るだろう」ずガヌドは答えた。



[...]



ワむマヌル・ロむスirは無関心に空を芋䞊げた。 「倜は毎日同じ時間です。 暗闇はあなたの勇気を奪いたすか」


ただし、ダむアログのすべおの行がマヌクされおいるわけではありたせん。 さらに芋お、芋おください



「䜓の䜍眮に気付いた」


䞊の段萜ず䞋の段萜をご芧ください。 䞊に2぀ありたす。



「そしお歊噚」



「いく぀かの剣ず匓。 1぀は、2本の刃を持぀残酷な鉄のhadでした...残酷な鉄。 圌はこの男の隣の地面に圌の手元に暪たわりたした。」


ヒントの䞀滎ではありたせん。 以䞋の2぀の段萜



肩をすくめたす。 「䞀人は厖の近くに座っおいた。 残りは地面か䜕かにありたした。」



「たたは、圌らは眠った」ずロむスは瀺唆した。


りィルは自問しないこずを知っおいるので、圌はこの挔説の著者ではないず蚀うこずができ、倚くのダむアログはいく぀かの段萜に広がっおいるため、最初の行の著者はロむスであるず仮定したす。



このスキヌムは、モデルをマヌクするのに圹立ちたす。 テキストの暪に自分の名前を識別するように圌女に教えたす。名前がない堎合は、近くの段萜を調べたす。 次に、タグは次のようになりたす。



PS±2、FN±2、NN±2、その他。



PS-スピヌカヌの埌。 段萜のラベルがPS -2の堎合、ダむアログの名前を話す郚分が2段萜䞊にあるこずを意味したす。 FN 1の堎合、次の段萜の名。 NN 0は、少なくずも2぀の名前が察話の前にあり、察話に最も近い名前が必芁であるこずを意味したす。



たた、ダむアログのテキストで参照される文字に぀いお、ADR±2を決定したす。



マヌク



次に、トレヌニングデヌタを準備したす。 このSublimeTextで圹立ちたす。 「ゲヌムオブスロヌンズ」ずいうテキストを開き、巊偎の匕甚笊を匷調衚瀺し、[怜玢]-> [すべおをすばやく怜玢]を遞択し、ホヌムキヌを2回抌したした。 これで、カヌ゜ルはダむアログのある各段萜の先頭近くにありたす。 次に、「{}」ず入力したした。 なぜなら テキストには䞭括匧はありたせん。その埌、それらを䜿甚しお、今埌䜿甚するメモを残すこずができたす。



正芏衚珟<= \ {= \}を䜿甚しお、䞭括匧を飛び越えたす。 この蚭蚈に䌚っおいない堎合、それらは前向きな回顧的か぀䞻芁なチェックず呌ばれたす。 括匧で囲たれた最初の匏により、SublimeTextは先頭に開始䞭括匧バックスラッシュで゚スケヌプされたがある行の匷調衚瀺を開始したす。 次の匏は、右䞭括匧がある堎合に停止を瀺したす。 ご芧のずおり、䞡方の匏はa= Constructで構成され、最初の匏のみに<も含たれおいたす。



F3を抌すず、ブラケット間を移動できたす。これは、WindowsのSublimeTextで次のブラケットを芋぀けるためのホットキヌです。 この皮の最適化は重芁です 箄1,000個のダむアログにタグを付けたす。 少なくずも私はそんなにやりたした。 思ったほど難しく、時間もかかりたせんでした。 たぶん私は嘘を぀いおいたすが、たった1幎埌に終わったからです。



始める前に、1぀の発蚀をしたいず思いたす。䜍眮ラベルPS、FN、NNを䜿甚するか、すべお同じ文字名を䜿甚するかを考えおください。 名前を䜿甚しないこずは既に述べたしたが、䜍眮ラベルを䜿甚する堎合は、このトレヌニングデヌタを察応するモデルに関連付けたす。 Johnのダむアログに「Jon」ずいうラベルを付けるず、将来的にラベルを定䜍眮のものに倉曎したり、より適切に他のラベルを䜿甚したりするこずができたす。



単䞀の答えはないず思いたす。 昚幎、私はキャラクタヌ名でタグ付けしたした。 次に、あいたいさを远加する予備的な操䜜を行う必芁がありたす。 Eddardの名前が䞊の2぀の段萜ず䞋の1぀の段萜に衚瀺される堎合、どちらを遞択したすか これはモデルの動䜜に盎接圱響し、それを行うずプロセスがさらに䞍正確になりたす。 したがっお、䜕をアドバむスすればよいかわかりたせん。 手動タグの芳点からは、キャラクタヌの名前を曞く方が簡単なようですが、自動化の芳点からは、䜍眮タグを持぀方がはるかに䟿利です。



プロパティの取埗



さお、テキストの䞀郚にタグを付けたした。 自然蚀語凊理ぞのコミットメントを称賛したす。 ここで必芁なのは、段萜を匕数ずしお受け取り、興味のあるプロパティでマヌクするいく぀かの関数を曞くこずです。



どのプロパティを通知したすか モデルの正確性を担圓する䞻力は、次の機胜です。PS、FN、たたはNNが珟圚の段萜たたは隣接する段萜に存圚するかどうか。



名前怜玢



最初の機胜は、適切な名前を芋぀けるこずです。 これは、品詞を定矩するこずで実行できたす。



 sentence = corpus.paras()[33][0] print " ".join(sentence) print nltk.pos_tag(sentence)
      
      



  「そのような雄匁さ、Gared」Ser Waymarは芳察した。
 [u '\ u201c'、 'NN'、u'Such '、' JJ '、u'eloquence'、 'NN'、u '、'、 '、'、u'Gared '、' NNP '、u'、\ u201d '、' NNP '、u'Ser'、 'NNP'、u'Waymar '、' NNP '、u'observed'、 'VBD '、u'。 '、'。 '] 


SerずWaymarに近いNPPは、これらが固有名であるこずを意味したす。 しかし、欠点もありたす

  1. ゚ラヌが発生したす。 終わりの匕甚が適切な名前になったこずに泚意しおください。

  2. 品詞の識別には時間がかかりたす。



 %timeit nltk.pos_tag(sentence)
      
      



  100ルヌプ、ベスト3ルヌプあたり8.93ミリ秒 


 asoiaf_sentence_count = 143669 ( asoiaf_sentence_count * 19.2 ) / 1000 / 60
      
      



  45.974079999999994 


PLIPには、凊理するための倚くの段萜があり、品詞がテストおよびリファクタリングプロセスを遅延させるず刀断するのに45分以䞊かかりたす。 もちろん、すべおを䞀床分析しお、䜕が起こったのかを匕き続き確認できたす。 ただし、このためには、さらに別のデヌタ構造に察凊する必芁があり、そのような定矩は、゜ヌステキストが倉曎されるたびにやり盎す必芁がありたす。 そしおこれは避けられたせん。



幞いなこずに、キャラクタヌ名を決定するために品詞に連絡する必芁はありたせん。 これは、分析のためにPLIPを遞択する利点の1぀です。すでに受信したデヌタが倧量にありたす。 それらのいく぀かを削りたしょう。



既存の情報



Wiki Songs of Ice and Fireであるこずがわかりたした 。 ヒヌロヌ名のリストを含むペヌゞを文字通りコピヌするこずで、キャラクタヌ名のほが網矅的なリストを埗たした。 結果はここで芋぀けるこずができたす 。 これで十分な堎合は、蚘事の次の章で説明したす。 ペヌゞからデヌタを自動的に抜出する方法に興味がある人のために、他のプロゞェクトで䜿甚したいく぀かの方法を玹介したす。



Wget



既知のリンクをたどる必芁がある堎合に非垞にシンプルな優れたナヌティリティ 。 リンクをバむパスする方法に぀いお考える必芁はありたせん。リストを含むファむルを䜜成し、次のように-iフラグを䜿甚しお転送するだけです。

 wget -i list_of_links.txt
      
      





必芁条件



Pythonには、個々のペヌゞでの䜜業に適した芁求ラむブラリがありたす。

 import requests r = requests.get("http://awoiaf.westeros.org/index.php/List_of_characters") html = r.text print html[:100]
      
      



  <DOCTYPE html>
 <html lang = "en" dir = "ltr" class = "client-nojs">
 <head>
 <メタ文字セット= "UTF-8" />
 <タむトル 


解析



htmlをダりンロヌドしたら、リンクにアクセスするために、䞍芁なタグからペヌゞを剥離する必芁がありたす。 BeautifulSoupは、面倒なこずなくリンクを取埗できるHTMLパヌサヌです。 むンストヌルず解析埌、次を実行するだけですべおのリンクを芋぀けるこずができたす。

 parsed_html.find_all("a")
      
      





ここでそれに぀いおもっず読むこずができたす 。



lxmlラむブラリを䜿甚する別の方法に぀いお説明したいず思いたす。 このラむブラリを䜿甚するず、Xpathを操䜜できたす。 Xpathは初めおですが、これはツリヌ構造をナビゲヌトする匷力な方法です。

 import lxml.html tree = lxml.html.fromstring(html) character_names = tree.xpath("//ul/li/a[1]/@title") print character_names[:5]
      
      



  ['Abelar Hightower'、 'Addam'、 'Addam Frey'、 'Addam Marbrand'、 'Addam Osgrey'] 


䞊からXpath匏を尋ねるず、次のようになりたす。

 tree.xpath("//ul        #                 /li        #               /a[1]      #     .            /@title    #   title          ")
      
      





次に、結果の䞭から名前を匷調衚瀺し、名前ずは関係のない名前を削陀する必芁がありたす。 PLIPペヌゞを芋るだけで、「Myrのテ゚ナ」のような芁玠に気付きたした。 モデルが「of」粒子をダむアログに䞀臎させないようにしたす。



NLTKはこれに圹立ちたす。 「悪い」単語-ストップワヌドを含むテキスト本文がありたす。 テキストを特城付ける意味がないほど䞀般的なもの。

 particles = ' '.join(character_names).split(" ") print len(set(particles)) stopwords = nltk.corpus.stopwords.words('english') print stopwords[:5] particles = set(particles) - set(stopwords) print len(particles) #     . .. Aegon I   ,   #  I    .    . "I" in particles
      
      



  2167
 ['i'、 'me'、 'my'、 'myself'、 'we']
 2146
本圓 


最埌に、デニス、ブラックフィッシュ、ゞョフなど、芋逃したニックネヌムを远加する必芁がありたす。 名前のリストに満足したら、将来の䜿甚に備えおファむルに保存したす。



名前を怜玢したす。 パヌト2



品詞を䜿甚しお名前を芋぀けるずいう考えを捚お、名前のリストを取埗したした。 トヌクンのシヌケンスを抜出し、名前のリストでそれらを芋぀けるこずができるかどうかを確認したす。 最埌に、コヌドを䜜成したす。

 import itertools from operator import itemgetter particles = [particle.rstrip('\n') for particle in open('asoiaf_name_particles.txt')] tokens = [u'\u201c', u'Such', u'eloquence', u',', u'Gared', u',\u201d', u'Ser', u'Waymar', u'observed', u'.'] def roll_call(tokens, particles):   speakers = {}   particle_indices = [i for (i, w) in enumerate(tokens) if w in particles]   for k, g in itertools.groupby(enumerate(particle_indices), lambda (i,x): ix):       index_run = map(itemgetter(1), g)       speaker_name = ' '.join(tokens[i] for i in index_run)       speakers[min(index_run)] = speaker_name   return speakers
      
      





この関数は、昚幎このプロゞェクトを行ったずきに䜿甚できなかったラムダ匏を䜿甚したす。 そのずき私が䜿甚したスクリプトはひどく読みにくいため、あえお公開するこずはしたせんでした。 さらに、このスクリプトでは、初心者が新しいこずを孊ぶこずができるず思うので、これに぀いおもう少し説明したす。



Itertoolsは泚目に倀するツヌルです。 私はよく入れ子や眮換を取り陀くためにそれを䜿甚したす。 その䞭で、 groupby関数が必芁です。 執筆時点でこの関数の新しいバヌゞョンがリリヌスされたため、私はdropwhileずtakewhileよりも完党にgroupbyを奜みたした。これを再垰的に䜿甚したした。



プログラミングするずき、 roll_call関数は芋぀けた名前の䜍眮を知っおいるべきだず思いたした。 そこで、名前のシリアル番号をすべお保持するこずにしたした。 これは、機胜コヌドの3行目で確認できたす。



 particle_indices = [i for (i, w) in enumerate(tokens) if w in particles]
      
      





Enumerateは、Pythonを玹介されたずきに非垞に圹立ちたした。 リストを取埗し、各芁玠に察しお䞀連のシリアル番号ず芁玠自䜓を返したす。



4行目は、すべおの資料の䞭でコヌドの最も扱いにくい郚分であり、私はそれを曞きたせんでした。 ラむブラリのドキュメントから盎接取埗されたす 。

 for k, g in itertools.groupby(enumerate(particle_indices), lambda (i,x): ix):
      
      





Groupbyはリストを調べ、ラムダ関数の結果に応じお芁玠をグルヌプ化したす。 ラムダは匿名関数です。 roll_callずは異なり、事前に定矩する必芁はありたせん。 これは、匕数を取り倀を返すコヌドの䞀郚にすぎたせん。 この堎合、シリアル番号から数字を匕くだけです。



それがどのように機胜するかを芋おみたしょう。

 print tokens particle_indices = [i for (i, w) in enumerate(tokens) if w in particles] print particle_indices for index, location in enumerate(particle_indices):   lambda_function = index-location   print "{} - {} = {}".format(index, location, lambda_function)
      
      



  [u '\ u201c'、u'Such '、u'eloquence'、u '、'、u'Gared '、u'、\ u201d '、u'Ser'、u'Waymar '、u'observed'、u '。']
 [4、6、7]
 0-4 = -4
 1-6 = -5
 2-7 = -5 


これはgroupbyのトリックです 。むンデックスには順番に番号が付けられるため、リスト内の項目も次々ず移動する堎合、ラムダの結果は同じになりたす。



groupbyは-4を芋お、グルヌプに倀4を割り圓おたす。 6番目ず7番目の芁玠は䞡方ずも-5を持ち、それぞれグルヌプ化されたす。



これで、耇合名の堎所がわかり、それらを䜿甚する必芁がありたす。 groupbyは䜕を返したすか キヌ、ラムダの結果、およびグルヌプ自䜓、 グルヌパヌオブゞェクト。 次に、 map関数を䜿甚しおitemgetter1を適甚し、バンドルから芁玠を抜出し、グルヌプのすべおの芁玠に適甚したす。したがっお、元のトヌクンリストに名前のリストを䜜成したす。



groupbyの埌、芋぀かった名前を抜出し、 スピヌカヌの連想配列に保存するだけです。

 roll_call(tokens, particles)
      
      



  {4u'Gared '、6u'Ser Waymar'} 


最適化



この関数の速床を、品詞を䜿甚した方法ず比范しおみたしょう。



 %timeit roll_call(tokens, particles)
      
      



  100ルヌプ、ベスト3ルヌプあたり3.85 ms 


悪くない、5-6倍高速。 しかし、 setを䜿甚しお結果を改善できたす。 セットは 、アむテムがリストにあるかどうかをほが瞬時にチェックしたす。

 set_of_particles = set(particle.rstrip('\n') for particle in open('asoiaf_name_particles.txt')) %timeit roll_call(tokens, set_of_particles)
      
      



  10000ルヌプ、最高3ルヌプあたり22.6 µs 


ギリシア文字を高速で芋るず、自分が良いこずを理解したす。



䌚話名の怜玢



ここで、ダむアログのテキストの前、䞭、埌の文字の名前を芋぀けるために、適切な堎所で䞊蚘の関数を呌び出すプログラムを䜜成する必芁がありたす。 これらすべおを、私たちのためにキャラクタヌ名の完党なリストを収集できるクラスに入れ、それをプロパティを抜出するための別のアルゎリズムに枡しおから、CRFsuiteに枡したす。



しかし、最初に、デヌタを敎理したいず思いたす。



XMLパヌサヌ



Xpathを䜿甚した1行のコマンドが成功した埌、テキストファむル甚のXMLパヌサヌを䜜成するこずにしたした。 この圢匏を遞択するこずには倚くの意味がありたす。 PLIPは、パラグラフで構成される章があり、その䞭にはダむアログが含たれる倚数の本がありたす。それらを慎重にマヌクする必芁がありたす。 テキストをXMLに翻蚳しおいなかった堎合最初は翻蚳しおいなかった堎合、ラベルはテキスト自䜓を散らかしおいたでしょう。



以䞋のスクリプトに぀いおは黙っおおく方が奜きです。Pythonでの最初のステップ、巚倧な関数、束葉杖、長い名前の倉数を思い出させおくれたす。

 from lxml import etree import codecs import re def ASOIAFtoXML(input): #   input           . root = etree.Element("root") for item in input:   title = item["title"]   current_book = etree.Element("book", title=item["title"])   root.append(current_book)   with codecs.open(item["contents"], "r", encoding="utf-8") as book_file:       #  ,      .       current_chapter = etree.Element("chapter", title="Debug")       for paragraph in book_file:           paragraph = paragraph.strip()           if paragraph != "":               title_match = re.match("\A[AZ\W ]+\Z", paragraph)               if title_match:                   current_chapter = etree.Element("chapter", title=title_match.group())                   current_book.append(current_chapter)               else:                   current_graf = etree.SubElement(current_chapter, "paragraph")                   while paragraph != "":                       current_dialogue = current_graf.xpath('./dialogue[last()]')                       speaker_match = re.search("(\{(.*?)\} )", paragraph)                       if speaker_match:                           speaker_tag = speaker_match.group(1)                           speaker_name = speaker_match.group(2)                           paragraph = paragraph.replace(speaker_tag, "")                       open_quote = paragraph.find(u"\u201c")                       if open_quote == -1:                           if current_dialogue:                               current_dialogue[0].tail = paragraph                           else:                               current_graf.text = paragraph                           paragraph = ""                       elif open_quote == 0:                           current_dialogue = etree.SubElement(current_graf, "dialogue")                           if speaker_name:                               current_dialogue.attrib["speaker"] = speaker_name                           close_quote = paragraph.find(u"\u201d") + 1                           if close_quote == 0:                               #  find  -1   ,    0                               #        .                                 #      .                               close_quote = len(paragraph)                           current_dialogue.text = paragraph[open_quote: close_quote]                           paragraph = paragraph[close_quote:]                       else:                           if current_dialogue:                               current_dialogue[0].tail = paragraph[:open_quote]                           else:                               current_graf.text = paragraph[:open_quote]                           paragraph = paragraph[open_quote:]   return root tree = ASOIAFtoXML([{"title": "AGOT", "contents": "corpus/train_asoiaf_tagged.txt"}]) #      . # et = etree.ElementTree(tree) # et.write(codecs.open("asoiaf.xml", "w", encoding="utf-8"), pretty_print=True)
      
      





䞊蚘のコヌドの本質lxmlを䜿甚しおツリヌを䜜成し、テキストを1行ず぀確認したす。その行が章の名前倧文字、句読点、スペヌスずしお認識されおいる堎合、珟圚の本の䞊郚に新しい章を远加したす。章の本文を読み終えたらすぐに、別の正芏衚珟を䜿甚しお段萜を読み、だれが䌚話を話したかを刀断し、それを䌚話の察応する頂点に远加したす。以前は、もちろん既にラベル付けされおいなければなりたせん。



XMLに関する興味深いメモ。これは階局構造であるため、その性質䞊、厳密な分岐が必芁であり、最䞊郚が最䞊郚にありたす。しかし、これは散文ではそうではありたせん。散文では、察話はテキスト内にありたす。 lxmlは゜リュヌションを提䟛したすテキストずテヌル。したがっお、XML頂点はテキストを栌玍したすが、このテキストは次の頂点が远加された埌に䞭断されたす。

 markup = '''<paragraph>Worse and worse, Catelyn thought in despair. My brother is a fool. Unbidden, unwanted, tears filled her eyes. <dialogue speaker="Catelyn Stark"> “If this was an escape,”</dialogue> she said softly, <dialogue speaker="Catelyn Stark">“and not an exchange of hostages, why should the Lannisters give my daughters to Brienne?”</dialogue></paragraph>''' graf = lxml.etree.fromstring(markup) print graf.text
      
      



さらに悪いこずに、カテリンは絶望的に考えたした。私の兄匟はばかです。
目に芋えない、䞍必芁な涙が圌女の目を満たした。 


 print graf[0].text
      
      



 「これが脱出だったなら」 


残りの「圌女は穏やかに蚀った」はどうなりたすか倉数の頂点の末尟に保存したす。

 print graf[0].tail
      
      



 圌女はそっず蚀った、 


など、ダむアログの各頂点に残りのテキストを远加したす。



その結果、ダむアログ䜜成者の怜玢が必芁なずきに倧幅に簡玠化されたす。そしお今すぐ必芁です

 class feature_extractor_simple:   """Analyze dialogue features of a paragraph. Paragraph should be an lxml node."""   def __init__(self, paragraph_node, particles, tag_distance=0):       self.paragraph = paragraph_node       self.particles = set(particles)       self.tag_distance = tag_distance       self.raw = ''.join(t for t in self.paragraph.itertext())       self.tokens = self.tokenize(self.raw)   def tokenize(self, string):       return nltk.wordpunct_tokenize(string)   def find_speakers(self, tokens):       speakers = {}       particle_indices = [i for (i, w) in enumerate(tokens) if w in self.particles]       for k, g in itertools.groupby(enumerate(particle_indices), lambda (i,x): ix):           index_run = map(itemgetter(1), g)           speaker_name = ' '.join(tokens[i] for i in index_run)           speakers[min(index_run)] = speaker_name       return speakers   def pre_speak(self, prior_tag="FN", near_tag="NN"):       #   .       features = {}       if self.paragraph.text is not None:           speakers = self.find_speakers(self.tokenize(self.paragraph.text))           if len(speakers) > 0:               features.update({"{} {}".format(prior_tag,self.tag_distance): speakers.values()[0]})           if len(speakers) > 1:               features.update({"{} {}".format(near_tag,self.tag_distance): speakers[max(speakers.keys())]})       return features   def dur_speak(self, tag="ADR"):       #  .       features = {}       for dialogue in self.paragraph.itertext("dialogue", with_tail=False):           tokens = self.tokenize(dialogue)           named = self.find_speakers(tokens)           addressed = {k: v for (k, v) in named.items() if tokens[k-1] == "," or tokens[k + 1 + v.count(" ")].startswith(",")}           if len(addressed) > 0:               features.update({"{} {}".format(tag, self.tag_distance): addressed[max(addressed.keys())]})       return features   def post_speak(self, tag="PS"):       features = {}       #   .       tails = [line.tail for line in self.paragraph.iterfind("dialogue") if line.tail is not None]       for tail in tails:           tokens = self.tokenize(tail)           speakers = {k: v for (k, v) in self.find_speakers(tokens).items() if k <= 1}           if len(speakers) > 0:               features.update({"{} {}".format(tag, self.tag_distance): speakers[min(speakers.keys())]})               break       return features
      
      





これらの機胜に関するいく぀かの蚀葉。



Pythonを初めお䜿甚する堎合は、クラスを恐れないでください。通垞の関数を䜜成し、selfを匕数ずしお枡すだけです。これにより、関数が珟圚凊理しおいるオブゞェクトがPythonに通知されたす。クラスはクロヌンファクトリのようなものであり、オブゞェクトはクロヌンです。すべおのクロヌンは同じDNAを持ち、これらは方法ず倉数ですが、人生の経隓のために、性栌は異なりたす。このコンテキストでは、クロヌンは送信されたデヌタです。



クラスには、オブゞェクト倉数を初期化できる特別な関数__init__もありたす。

リラックスできるようになりたした デヌタは特別なクラスの手にありたす。そしお、あなたは圌の行動を抜象化したので、指をクリックするだけで、圌によっお凊理された情報を埗るこずができたす。

 paragraph = tree.xpath(".//paragraph")[32] example_extractor = feature_extractor_simple(paragraph, particles) print example_extractor.raw print example_extractor.pre_speak() print example_extractor.dur_speak() print example_extractor.post_speak()
      
      



「そのような雄匁さ、Gared」Ser Waymarは芳察した。「あなたがあなたの䞭にそれを持っおいるずは思わなかった。」
 {}
{'ADR 0'u'Gared '}
{'PS 0' 'Ser Waymar'} 


䞀郚の機胜の動䜜に混乱しおいる堎合は、それらの機胜に぀いお簡単に説明したす。䞊蚘のすべおがあなたに受け入れられるように芋えるなら、あなたは䜕をすべきかを知っおいたす、次の章で䌚いたしょう。



連想配列の扱いにくい操䜜がありたす。これは、Pythonで順序付けられおいないためです。家を出るずきにポケットに鍵がなく、ドアをロックしおいるず感じる気持ちを思い出させたす。堎合によっおは、最初の文字を取埗するか最埌の文字を取埗するかを垞に確認する必芁がありたした。キヌの倀を芋お、最小/最倧を遞択したす。



pre_speak



䞊で蚀ったように、テキスト属性には、ダむアログの最初の行たでのすべおのテキストが含たれおいたす。その䞭のキャラクタヌの名前を芋぀けるだけです。



dur_speak



名前が倚くの行で構成されるダむアログの本文にある堎合、それらすべおを確認する必芁がありたす。

 for dialogue in self.paragraph.itertext("dialogue", with_tail=False)
      
      





機胜itertextでlxmlのは、あなたがすべおのテキストトップを取埗するこずができたす。たた、フラグwith_tail = Falseを蚭定しお、「テヌル」のない頂点のみを怜玢したす。これは、ダむアログのテキストのみを意味したす。



キャラクタヌの名前を芋぀けたらすぐに、コンマで区切られたキャラクタヌのみを遞択する必芁がありたす。これにより、アピヌルを芋぀けるこずができたす。たずえば、「ネッド、玄束しおください。」/「玄束しお、ネッド。」



私は、ダむアログで芋぀かった姓が次の段萜で答える可胜性が非垞に高いず内郚から感じおいるので、蚘茉されおいる姓で宛先を曞き換えたす。



post_speak



この機胜では、ダむアログの埌の最初の文字のみが必芁です。したがっお、サむクルが芋぀かるずすぐに䞭断したす。



関数は、閉じ匕甚笊の埌の最初の2぀のトヌクンを調べたす。そのため、次のようなダむアログが衚瀺されたす。

「さようなら」ずゞョンは蚀った。


初心者プログラマヌ向けのヒントリストを䜜成するずきにフェッチ関数を呌び出すこずができたす。

 tails = [line.tail for line in self.paragraph.iterfind("dialogue") if line.tail is not None]
      
      





これにより、ダむアログを1行で取埗できたした。条件を指定するだけで、テヌルなしですべおの結果を削陀できたす



CRFsuite



おそらく、これはあなたにずっお最も興味のある郚分でしょう。条件に応じおランダムなフィヌルドが含たれおおり、コマンドラむンから起動されたすが、内郚からどのように機胜するかを確認する方法はありたせん。



しかし実際、CRFsuiteは非垞にシンプルで興味深い郚分です。資料を曞いおいるずきに、圌はPythonのラむブラリを持っおいるこずがわかりたしたが、今は物事を耇雑にせず、コマンドラむンを䜿甚しお実行可胜ファむルを䜿甚したす。



次の本「Winds of Winter」が



日の目を芋るず、モデルを曎新する予定です。しかし、これが起こるたであず数幎ありたすCRFsuiteが必芁ずするのは、次のようなタブ区切りのプロパティを持぀テキストです。



 FN 0 Graf Sent Len = 4 FN 1 = True FN -2 = True FN 0 = True NN 1 = True 


これは、トレヌニングデヌタの圢匏です。最初の属性は正解です。埌続のすべおのプロパティ。芋た目は䌌おいるかもしれたせんが、コロンは䜿甚しないでください-これは重み付けされたプロパティのためであるため、誀った解釈に぀ながる可胜性がありたす。



crfsuite.exeがある堎所でコマンドラむンを開き、そこに次を入力する必芁がありたす。

 crfsuite learn -m asoiaf.model train.txt
      
      





これにより、すべおの頭脳であるモデルが䜜成されたす。あなたは圌女に奜きなものを䜕でも呌ぶこずができたす、私は私のasoiafず呌びたした。モデルの粟床を確認するには、次を入力したす。

 crfsuite tag -qt -m asoiaf.model test.txt
      
      





タグ付けのためにモデルを実際に実行するには、次を入力したす

 crfsuite tag -m asoiaf.model untagged.txt
      
      





untagged.txtはのように芋えるずすべきであるtrain.txtが、最初に正しい答えを属性ではない、すなわち、このようなもの



 NN -1 = True FN 0 = True FN 2 = True FN -1 = True NN 0 = True 


ここで詳现を確認できたす。



モデルの粟床を向䞊させるこずができる倚くのプロパティをいじっおみたしょう。最も単玔なものから始めたしょう。段萜内および段萜の近くの䜍眮ラベルの䜍眮を決定するブヌル倀を䜿甚したす。



繰り返しになりたすが、プロパティを抜出するためのクラスは、最初にいく぀かの新しい機胜が远加されたした。

 class feature_extractor:   """Analyze dialogue features of a paragraph. Paragraph should be an lxml node."""   def __init__(self, paragraph_node, particles, tag_distance=0):       self.paragraph = paragraph_node       self.particles = set(particles)       self.tag_distance = tag_distance       self.raw = ''.join(t for t in self.paragraph.itertext())       self.tokens = self.tokenize(self.raw)       self.speaker = self.xpath_find_speaker()   def features(self):       features = {}       features.update(self.pre_speak())       features.update(self.dur_speak())       features.update(self.post_speak())       return features   def local_features(self):       #               features = []       if self.tokens.count(u"\u201c") == 0:           features.append("NoQuotes=True")       prior = self.paragraph.getprevious()       try:           last_dialogue = list(prior.itertext("dialogue", with_tail=False))[-1].lower()           hits = [w for w in ['who', 'you', 'name', '?'] if w in last_dialogue]           if len(hits) > 2:               features.append("Who Are You?=True:10.0")       except (AttributeError, IndexError):           pass       try:           dialogue = list(self.paragraph.itertext("dialogue", with_tail=False))[0].lower()           for token in ['name', 'i am', u'i\u2019m']:               if token in dialogue:                   features.append("My Name=True:10.0")                   break       except (AttributeError, IndexError):           pass       if self.tokens[0] in self.particles:           features.append("FirstSpeakerIndex0=True")       if self.paragraph.text is not None:           name_precount = len(self.find_speakers(self.tokenize(self.paragraph.text)))           if name_precount > 2:               features.append("Many Names Before=True")           conjunctions = set([w.lower() for w in self.tokenize(self.paragraph.text)]).intersection(set(['and', 'but', 'while', 'then']))           if len(conjunctions) > 0 and self.paragraph.find("dialogue") is not None:               features.append("Conjunction in Head=True")       short_threshold = 10       if len(self.tokens) <= short_threshold:           features.append("Short Graf=True")       dialogue_length = sum(map(len, self.paragraph.xpath(".//dialogue/text()")))       dialogue_ratio = dialogue_length / len(self.raw)       if dialogue_ratio == 1:           features.append("All Talk=True")       elif dialogue_ratio >= 0.7:           features.append("Mostly Talk=True")       elif dialogue_ratio < 0.3 and not self.tokens < short_threshold:           features.append("Little Talk=True")       return features   def feature_booleans(self):       bool_features = []       for tag in ["PS", "FN", "NN", "ADR", ]:           label = "{} {}".format(tag, self.tag_distance)           if label in self.features().keys():               bool_features.append("{}=True".format(label))           else:               bool_features.append("{}=False".format(label))       return bool_features   def tokenize(self, string):       return nltk.wordpunct_tokenize(string)   def find_speakers(self, tokens):       speakers = {}       particle_indices = [i for (i, w) in enumerate(tokens) if w in self.particles]       for k, g in itertools.groupby(enumerate(particle_indices), lambda (i,x): ix):           index_run = map(itemgetter(1), g)           speaker_name = ' '.join(tokens[i] for i in index_run)           speakers[min(index_run)] = speaker_name       return speakers   def xpath_find_speaker(self):       speakers = self.paragraph.xpath(".//@speaker")       if speakers == []:           return "NULL"       else:           return speakers[0]   def pre_speak(self, prior_tag="FN", near_tag="NN"):       #          features = {}       if self.paragraph.text is not None:           speakers = self.find_speakers(self.tokenize(self.paragraph.text))           if len(speakers) > 0:               features.update({"{} {}".format(prior_tag,self.tag_distance): speakers.values()[0]})           if len(speakers) > 1:               features.update({"{} {}".format(near_tag,self.tag_distance): speakers[max(speakers.keys())]})       return features   def dur_speak(self, tag="ADR"):       #          features = {}       for dialogue in self.paragraph.itertext("dialogue", with_tail=False):           tokens = self.tokenize(dialogue)           named = self.find_speakers(tokens)           addressed = {k: v for (k, v) in named.items() if tokens[k-1] == "," or tokens[k + 1 + v.count(" ")].startswith(",")}           if len(addressed) > 0:               features.update({"{} {}".format(tag, self.tag_distance): addressed[max(addressed.keys())]})       return features   def post_speak(self, tag="PS"):       features = {}       #          tails = [line.tail for line in self.paragraph.iterfind("dialogue") if line.tail is not None]       for tail in tails:           tokens = self.tokenize(tail)           speakers = {k: v for (k, v) in self.find_speakers(tokens).items() if k <= 1}           if len(speakers) > 0:               features.update({"{} {}".format(tag, self.tag_distance): speakers[min(speakers.keys())]})               break       return features paragraph = tree.xpath(".//paragraph")[-1] example_extractor = feature_extractor(paragraph, particles) print example_extractor.raw print example_extractor.features() print example_extractor.local_features() print example_extractor.feature_booleans()
      
      



 そしお圌らの手に、短剣。
 {}
[「NoQuotes = True」、「Short Graf = True」、「Little Talk = True」]
[「PS 0 = False」、「FN 0 = False」、「NN 0 = False」、「ADR 0 = False」] 


昚倜、文曞化されおいない機械孊習の狂気の䞭で、私は倚くの特性を改善しようずしたした。以䞋は、公開可胜なドラフトの䞀郚です。



オプション1真の䜍眮ブヌル倀のみ

ラベルカりントリコヌル
PS 0  207    0.9949
FN 0   185    0.95
NULL   118    0.3492
OTHER  56     0.3939
PS - 2 44     0.5238
Item accuracy: 430 / 678 (0.6342) 


さらに、このような統蚈の倚くに䌚うので、それらの意味をすぐに刀断したしょう。



私たちが人々を芋お倕食にいるず想像しおください。ランダムな通行人がむルミナティかどうかを刀断するように頌みたした。あなたは、陰謀理論を完党に信じおいる人ずしお、dump子を食べ終わらせ、通行人にタグを付け始めたす。ここでは考慮されない倀である



粟床およそPrecisionは、第1皮の゚ラヌの頻床を瀺したす。蚀い換えれば、あなたが間違っおむルミナティの䞭で人をランク付けした頻床。



完党性およそRecallは、モデルが正しく決定した怜蚌デヌタのラベルの数を枬定したす。



F1は䞡方のラベルの組み合わせです。すべおの人々をむルミナティずしお分類するず、最倧限の完党性ずわずかな粟床が保蚌されるこずがわかりたす。



なぜならすべおがマヌクされおいるので、モデルの粟床にはあたり興味がありたせん。完党性ず正確さが必芁です。



プロパティの最初のバヌゞョンでは、真のブヌル倀のみを考慮したした。぀たり䞊蚘の段萜では、すべおのセットは「ADR 0 = True」および「PS 0 = True」の圢匏でした。粟床玄アむテム粟床は63.4でした。



63.4はこれでいいですかNULL、PS 0、およびFN 0がテストデヌタの4分の3を構成し、それらが自然に芋぀けやすいずいう事実に基づいお、私たちは間違いなくより良い結果を出すこずができたす。次に、残りの䜍眮ブヌル倀falseを远加したす。



オプション2すべおの䜍眮ブヌル倀

ラベルカりントリコヌル
NULL 254 0.9048
PS 0204 0.9899
FN 0 149 0.975
その他24 0.2273
PS-2 19 0.2857
アむテムの粟床515/6780.7596 


ここで、単玔なケヌスを完党に定矩し、適切な粟床を取埗したす。75は、最初の本「Game of Thrones」ず「Battle of the Kings」の3分の1、および残りの4分の3を決定するためのモデル自䜓をマヌクするだけでよいこずを意味したす。䜕時間もかかりたすが、圓然のこずです。



それでも、NULLタグを98+の完党性で定矩しない理由はないので、それを目的ずしたプロパティを远加したしょう。



オプション3匕甚笊

ラベルカりントリコヌル
PS 0 218 0.9907
NULL 180 0.9119
FN 0 167 0.9118
その他63 0.3784
PS 2 25 0.5
アむテムの粟床550/7100.7746 


段萜の開始匕甚笊の数をカりントしたす。



NULLがより正確になっおいないこずに驚いおいるず蚀いたいです。これに取り組む必芁がありたす。さらにFN 0を改善したいず思い



たす。オプション4名のむンデックス

ラベルカりントリコヌル
PS 0 218 0.9907
NULL 183 0.9057
FN 0 157 0.8971
その他68 0.4189
PS-2 23 0.5484
アむテムの粟床551/7100.7761 


このプロパティには、名のむンデックスが含たれたす。



うヌん...倚分耇雑すぎるので、もう䞀床ブヌル倀に戻りたしょう。



オプション5むンデックス0の名前+冗長性

ラベルカりントリコヌル
PS 0 216 0.986
FN 0 166 0.9265
NULL 160 1
その他85 0.5811
PS 2 32 0.7143
アむテムの粟床578/7100.8141 


ここにある最初の匕甚笊の数を正しく数えなかったため、結果が台無しになりたした。



修正するずすぐにNULLが完党に決定されたすが、モデルを改善する簡単な方法がなくなりたした。今、私は本圓に結果をさらに改善するために工倫する必芁がありたすそれが動䜜するかどうかのを芋おみたしょう...



2 - PS+ず話をした埌オプション6

スピヌカヌが2぀の段萜の䞊たたは電流以䞋であればここでは、ブヌル倀を䜿甚したす。理論的には、これによりPS -2の結果が増加するはずです。

ラベルカりントリコヌル
PS 0 216 0.986
FN 0 166 0.9265
NULL 160 1
その他84 0.5676
PS 2 32 0.7143
アむテムの粟床578/7100.8141 


効果なし



オプション7シヌケンス??

ラベルカりントリコヌル
PS 0 217 0.986
FN 0 168 0.9265
NULL 160 1
その他82 0.5541
PS 2 30 0.6429
アむテムの粟床576/7100.8113むンスタンスの粟床56/1420.3944 


埅っおCRFはシヌケンスを凊理できるこずがわかりたした。実際、これがその意味です。むンスタンスの粟床倀玄むンスタンスの粟床を無芖したした、なぜなら これは垞に0/1でした。぀たり、モデルはテキスト党䜓を1぀の長い察話ず芋なしおいたした。



申し蚳ありたせんが、私は自分を平手打ちする必芁がありたす。粟床を向䞊させるず仮定したす-これは未解決の質問ですが-この機胜をどのように䜿甚したすか5぀の段萜で各シヌケンスの長さを瀺すこずを詊みたしたが、これは正しいように思えたせん。



おそらく、2぀の連続したNULLが䞀臎する堎合、䌚話が完了したず仮定しお、これはシヌケンスになりたす。



それで遊んだ埌、私は䌚話で動䜜するモデルを構築するこずができたせんでした。私が理解しおいるように、シヌケンス内の䜍眮に応じお、倚くの特別なトランゞションりェむトおよそのトランゞションりェむトが必芁です。したがっお、モデルは、䌚話の開始時、䞭間、たたは終了時に、私たちの䜍眮に応じお異なる決定を行いたす。



しかし、モデルの動䜜には、これが起こっおいるこずを瀺すものは䜕もありたせん。近い将来、他のプロパティで少し遊んでみたす。はい、トレヌニングデヌタずテストデヌタを生成するスクリプトを芋おみたしょう。最適化されおいたせん 各段萜のプロパティを5回蚈算したす。この資料に぀いおはそのたたにしおおきたすが、1぀のサむクルを䜿甚しお段萜のブヌルプロパティを保持し、1぀を䜿甚しお既存の段萜に远加するず、高速化できるこずに泚意しおください。

 tree = ASOIAFtoXML([{"title": "ASOIAF", "contents": "corpus/train_asoiaf_pos_tagged.txt"}]) paragraphs = tree.xpath(".//paragraph") In [29]: def prep_test_data(paragraphs):   max_index = len(paragraphs)   results = []   for index, paragraph in enumerate(paragraphs):       extractor = feature_extractor(paragraph, set_of_particles)       all_features = extractor.local_features() + extractor.feature_booleans()       for n in [-2, -1, 1, 2]:           if 0 <= n+index < max_index:               neighbor_features = feature_extractor(paragraphs[index + n], set_of_particles, tag_distance = n).feature_booleans()               if neighbor_features:                   all_features += neighbor_features            all_features.insert(0, extractor.speaker)       results.append("\t".join(all_features))   return results results = prep_test_data(paragraphs) In [31]: max_index = len(results) with codecs.open(r"new_test.txt", "w", "utf-8") as output:   for line in results[:int(max_index/2)]:           output.write(line + '\n') with codecs.open(r"new_train.txt", "w", "utf-8") as output:   for line in results[int(max_index/2):]:           output.write(line + '\n')
      
      





その他のプロパティ



他のいく぀かのプロパティを詊したした



埌者はかなり巧劙な動きだず思いたしたが、機胜せず、81を超える粟床は埗られたせんでした。



怜蚌でトレヌニングデヌタを倉曎しようずしたずころ、84になりたした。特定のデヌタの倚くのプロパティを改善するのに倚くの時間を費やすべきではありたせん。これは再蚓緎に぀ながりたす。実際、トレヌニングデヌタずテストデヌタを混合するこずは良い考えです。私はそれらを混ぜたせんでした、なぜなら これはシヌケンスの損傷に぀ながるず思いたしたが、もう䜿甚しないので、なぜですかそれらを混ぜたす。



少し混ざったデヌタ



82を受け取りたした。



わかったここでスキルの限界に達したず思いたす。



継続はありたせんか



次に䜕ができるかをたずめお話したしょう。





おわりに



いいねこれが誰かに圹立぀こずを願っおいたす。読んでくれおありがずう、そしおもしあなたが私に連絡したいなら、私はツむッタヌにいたす。



たた、ゲヌム・オブ・スロヌンズの倧芏暡な批刀的研究のために䞊蚘のすべおが行われたこずに泚意したいず思いたす。あなたがこれらの本のファンであり、察話ラベルのおかげで可胜であった分析を読みたいなら、私はすぐにすべおを公開したす。



All Articles