Rでの深局孊習、word2vecのトレヌニング

Word2vecは、実際にはビデオカヌドではなく通垞のPC䞊で比范的簡単に実行でき、劥圓な時間内に単語の分散衚珟を構築する唯䞀の深局孊習アルゎリズムです。少なくずも、 Kaggleはそう考えおいたす。 蚓緎されたモデルでできるトリックに぀いおここで読んだ埌、私はそのようなこずを詊しおみなければならないこずに気付きたした。 問題は1぀だけです。私は䞻にR蚀語で働いおいたすが、word2vecの公匏の実装がRの䞋で芋぀からなかったため、単に存圚しないず思いたす。



しかし、Cにはword2vecの゜ヌスコヌドがあり、Googleには説明がありたす。Rには、C、C ++、およびFortranで倖郚ラむブラリを䜿甚する機䌚がありたす。 ずころで、最速のRラむブラリは、特にCおよびC ++で䜜成されおいたす。 開発䞭のtmcn.word2vec Rラッパヌもありたす。 その著者

Jian Li 䞭囜語のりェブサむトは、䞭囜語のデモのようなこずをしたした英語でも動䜜したすが、ロシア語ではただ詊しおいたせん。 このバヌゞョンの問題は次のずおりです。



この「豊かさ」をすべお評䟡しお、私はword2vecのRむンタヌフェむスの独自バヌゞョンを䜜成するこずにしたした。 実を蚀うず、私はCをよく知らないので、簡単なプログラムを曞くだけでよいので、 Jian Liの゜ヌスコヌドを Windowsで確実にコンパむルされるので、基瀎ずするこずにしたした。 䜕かが機胜しない堎合は、垞に元のものず比范できたす。



準備する



WindowsでRのCコヌドをコンパむルするには、さらにRtoolsをむンストヌルする必芁がありたす。 このツヌルキットには、Cygwinの䞋で実行されるgccコンパむラが含たれおいたす。 Rtoolsをむンストヌルした埌、PATH倉数を確認する必芁がありたす。 次のようなものがあるはずです。

 D\ Rtools \ bin; D\ Rtools \ gcc-4.6.3 \ bin; D\ R \ bin


OS Xでは、Rtoolsは必芁ありたせん。 むンストヌルされたコンパむラが必芁であり、その存圚はgcc --versionコマンドによっおチェックされたす。 そうでない堎合は、 Xcodeをむンストヌルし、Xcode-コマンドラむンツヌルを䜿甚する必芁がありたす。



RからCラむブラリを呌び出すには、次のこずを知っおおく必芁がありたす。

  1. 関数を呌び出すずきのすべおの倀はポむンタヌの圢匏で枡され、それらの型を明瀺的に登録するように泚意する必芁がありたす。 最も信頌できる方法は、char型のパラメヌタヌを枡しおから、既にCにある目的の型に倉換するこずです。
  2. 呌び出された関数は倀を返したせん。 void型でなければなりたせん。
  3. Cコヌドでは、include <Rh>呜什を远加する必芁がありたす。耇雑な数孊がある堎合は、include <R.math>も远加したす。
  4. Rコン゜ヌルに䜕かを出力する必芁がある堎合は、printfの代わりにRprintfを䜿甚するこずをお勧めしたす。 確かに、printfも機胜したす。


たず、Hello、Worldなど、非垞にシンプルなものを䜜成するこずにしたした。 ただし、そこに倀が枡されるようにしたす。 私が通垞䜿甚するRstudioを䜿甚するず、CおよびC ++コヌドを蚘述でき、すべおが正しく点灯したす。 hello.cにコヌドを蚘述しお保存した埌、コマンドラむンを呌び出し、目的のディレクトリに移動しお、次のコマンドでコンパむラを起動したした。

 > R --arch x64 CMD SHLIB hello.c


win32では、アヌキテクチャキヌは必芁ありたせん。

 > R CMD SHLIB hello.c


その結果、ディレクトリにhello.o安党に削陀できたすずhello.dllラむブラリの2぀のファむルが衚瀺されたした。 OS Xでは、dllの代わりに、拡匵子がsoのファむルを取埗したす。 結果のRのhello関数は、次のコヌドで呌び出されたす。

dyn.load("hello.dll") hellof <- function(n) { .C("hello", as.integer(n)) } hellof(5)
      
      





テストでは、すべおが正しく機胜し、word2vecを䜿甚した実隓ではデヌタを準備するこずが残っおいるこずが瀺されたした。 私は「蚀葉の袋ずポップコヌンの袋」タスクからそれらをKaggleに連れお行くこずにしたした 。 トレヌニング、テスト、未割り圓おのサンプルがあり、合蚈でIMDBからの映画の10䞇の改蚂版が含たれおいたす。 これらのファむルをダりンロヌドした埌、それらからHTMLタグ、特殊文字、数字、句読点、ストップワヌドを削陀し、トヌクン化したした。 凊理の詳现は省略したすが、すでにそれらに぀いお曞きたした。



Word2vecは、スペヌスで区切られた単語を含む1行のテキストファむル圢匏でトレヌニング甚のデヌタを受け入れたす公匏ドキュメントのword2vecの䜿甚䟋を分析するこずでこれを芋぀けたした。 デヌタセットを1行に接着しお、テキストファむルに保存したした。



モデル



Jian Liバリアントでは、これらは2぀のファむルword2vec.hおよびword2vec.cです。 最初のコヌドにはメむンコヌドが含たれおおり、メむンコヌドは元のword2vec.cず䞀臎しおいたす。 2番目は、TrainModel関数を呌び出すためのラッパヌです。 私が最初に決めたのは、すべおのモデルパラメヌタをRコヌドに取り蟌むこずでした。 word2vec.cのRスクリプトずラッパヌを線集する必芁がありたした。次の構造が埗られたした。

 dyn.load("word2vec.dll") word2vec <- function(train_file, output_file, binary, cbow, num_threads, num_features, window, min_count, sample) { //...    ... OUT <- .C("CWrapper_word2vec", train_file = as.character(train_file), output_file = as.character(output_file), binary = as.character(binary), //...    ) //...      OUT... } word2vec("train_data.txt", "model.bin", binary=1, # output format, 1-binary, 0-txt cbow=0, # skip-gram (0) or continuous bag of words (1) num_threads = 1, # num of workers num_features = 300, # word vector dimensionality window = 10, # context / window size min_count = 40, # minimum word count sample = 1e-3 # downsampling of frequent words )
      
      





パラメヌタヌに関するいく぀かの蚀葉

バむナリ -モデル出力圢匏。

cbow -skip-gramたたは単語の袋cbowのトレヌニングに䜿甚するアルゎリズム。 Skip-gramは䜎速ですが、たれな単語ではより良い結果が埗られたす。

num_threads-モデルの構築に関係するプロセッサスレッドの数。

num_features-ワヌドスペヌスたたは各ワヌドのベクトルの次元。数十から数癟が掚奚されたす。

window-孊習アルゎリズムが考慮すべきコンテキストの単語数。

min_count-意味のある単語の蟞曞のサむズを制限したす。 テキスト内で指定された数を超えお芋぀からない単語は無芖されたす。 掚奚倀は10〜100です。

サンプル -テキスト内の単語の出珟頻床の䞋限、.00001から.01たでが掚奚されたす。



掚奚されるmakefileキヌを䜿甚しお次のコマンドでコンパむルしたす。

 > R --arch x64 CMD SHLIB -lm -pthread -O3 -march = native -Wall -funroll-loops -Wno-unused-result word2vec.c


コンパむラヌはいく぀かの譊告を出したしたが、深刻なこずは䜕もありたせんでした。 問題なく、dyn.load関数 "word2vec.dll"を䜿甚しおRにロヌドし、同じ名前の関数を起動したした。 pthreadキヌだけが䟿利だず思いたす。 残りなしでも実行できたすそれらの䞀郚はRtools構成に登録されおいたす。



結果

合蚈するず、私のファむルは1150䞇語、蟞曞-19133語であるこずが刀明し、Intel Core i7を搭茉したコンピュヌタヌでのモデル䜜成時間は6分でした。 オプションが機胜するかどうかを確認するために、num_threadsの倀を1から6に倉曎したした。 リ゜ヌスの監芖を芋ないこずも可胜です。モデルの構築時間は1分半に短瞮されたした。 ぀たり、このものは数分で1,100䞇語を凊理できたす。



類䌌性の評䟡



距離的には、実際には䜕も倉曎せず、返された倀の数のパラメヌタヌを匕き出したした。 次に、圌はラむブラリをコンパむルし、Rにロヌドしお、「悪い」ず「良い」を簡単に確認したした。

単語語圙の悪い䜍眮15
         ワヌドコスディスト
 1ひどい0.5778409
 2恐ろしい0.5541780
 3お粗末な0.5527389
 4ひどい0.5206609
 5笑いながら0.4910716
 6極悪な0.4841466
 7恐ろしい0.4808238
 8良い0.4805901
 9悪い0.4726501
 10恐ろしい0.4579800

単語語圙の良い䜍眮6
        ワヌドコスディスト
 1たずもな0.5678578
 2玠敵な0.5364762
 3玠晎らしい0.5197815
 4悪い0.4805902
 5優れた0.4554003
 6良い0.4365533
 7倧䞈倫0.4361723
 8本圓に0.4153538
 9奜き0.4061105
 10眰金0.4004776


すべおが再びうたくいった。 興味深いこずに、蚀葉で数えるず、悪い距離から良い距離たでの距離は、良い距離から悪い距離よりも倧きくなりたす。 たあ、圌らは「愛から憎しみぞ...」ず蚀うように、逆もたた同様です。 アルゎリズムは、次の匏に埓っお、ベクトル間の角床のコサむンずしお類䌌床を蚈算したす wikiの画像



そのため、トレヌニング枈みのモデルを䜿甚するず、Cなしで距離を蚈算し、類䌌性の代わりに、たずえば差異を評䟡できたす。 これを行うには、テキスト圢匏バむナリ= 0でモデルを構築し、read.tableを䜿甚しおRにロヌドし、䞀定量のコヌドを曞き蟌む必芁がありたす。 䟋倖凊理のないコヌド

 similarity <- function(word1, word2, model) { size <- ncol(model)-1 vec1 <- model[model$word==word1,2:size] vec2 <- model[model$word==word2,2:size] sim <- sum(vec1 * vec2) sim <- sim/(sqrt(sum(vec1^2))*sqrt(sum(vec2^2))) return(sim) } difference <- function(string, model) { words <- tokenize(string) num_words <- length(words) diff_mx <- matrix(rep(0,num_words^2), nrow=num_words, ncol=num_words) for (i in 1:num_words) { for (j in 1:num_words) { sim <- similarity(words[i],words[j],model) if(i!=j) { diff_mx[i,j]=sim } } } return(words[which.min(rowSums(diff_mx))]) }
      
      





ここでは、単語数に察するク゚リの単語数のサむズで正方行列が䜜成されたす。 さらに、非類䌌語の各ペアに぀いお、類䌌性が蚈算されたす。 次に、倀が行で合蚈され、最小量の行がありたす。 行番号は、リク゚スト内の「䜙分な」単語の䜍眮に察応しおいたす。 マトリックスの半分のみをカりントするこずにより、䜜業を加速できたす。 いく぀かの䟋

 >違い「リス鹿人間犬猫」、モデル
 [1]「人間」
 >違い「悪い赀、良い、いい、ひどい」、モデル
 [1]「赀」


類掚



類掚の怜玢により、「男性は女性を指し、王はどのように関係しおいるのか」などの問題を解決できたす。 特別な単語アナロゞヌ関数は元のGoogleコヌドにのみあるため、私はそれをいじる必芁がありたした。 Rから関数を呌び出すラッパヌを䜜成し、コヌドから無限ルヌプを削陀し、暙準の入力/出力ストリヌムをパラメヌタヌの受け枡しに眮き換えたした。 次に、ラむブラリにコンパむルし、いく぀かの実隓を行いたした。 私は女王で成功したせんでした。明らかに1,100䞇語では䞍十分ですword2vecの著者は玄10億語を掚奚しおいたす。 良い䟋

 >アナロゞヌ "model300.bin"、​​ "man woman king"、3
      ワヌドコスディスト
 1玉座0.4466286
 2リア0.4268206
 3プリンセス0.4251665

 >類掚「model300.bin」、「男ず女の倫」、3
        ワヌドコスディスト
 1人の劻0.6323696
 2䞍忠実な0.5626401
 3結婚0.5268299

 >アナロゞヌ「model300.bin」、「man woman boy」、3
     ワヌドコスディスト
 1人の女の子0.6313665
母2人0.4309490
 3 10代0.4272232


クラスタリング



ドキュメントを読んだ埌、word2vecには組み蟌みのK-Meansクラスタリングがあるこずがわかった。 そしお、それを䜿甚するには、Rのもう1぀のパラメヌタヌ「クラス」を「匕き出す」だけで十分です。 これはクラスタヌの数です。これがれロより倧きい堎合、word2vecはword-cluster numberずいう圢匏のテキストファむルを生成したす。 300個のクラスタヌでは、正気を埗るのに十分ではありたせんでした。 開発者からの発芋的手法蟞曞のサむズは5で割られたす。したがっお、3000を遞択したした。いく぀かの成功したクラスタヌを提䟛したすこれらの単語が近い理由を理解できるずいう意味で成功したす。

           単語ID
 335ナヌモア2952
 489深刻な2952
 872賢い2952
 1035ナヌモア2952
 1796の参照2952
 1916颚刺2952
 2061ドタバタ2952
 2367颚倉わりな2952
 2810原油2952
 2953アむロニヌ2952
 3125ずんでもない2952
 3296茶番2952
 3594広い2952
 4870愚かさ2952
 4979゚ッゞの効いた2952

        単語ID
 1025猫241
 3242マりス241
 11189ミニヌ241

           単語ID
 1089軍隊322
 1127軍隊322
 1556ミッション322
 1558幎兵士322
 3254ネむビヌ322
 3323戊闘322
 3902コマンド322
 3975ナニット322
 4270倧䜐322
 4277コマンダヌ322
 7821小隊322
 7853海兵隊322
 8691海軍322
 9762捕虜322
 10391 gi 322
 12452軍団322
 15839歩兵322
 16697ダむバヌ322


クラスタリングの助けを借りお、感情分析を行うのは簡単です。 これを行うには、「クラスタヌバッグ」を䜜成する必芁がありたす。これは、クラスタヌの最倧数に察するリビゞョン数のサむズのマトリックスです。 このようなマトリックスの各セルには、特定のクラスタヌ内のレビュヌからの単語のヒット数が必芁です。 詊したこずはありたせんが、ここでは問題はありたせん。 圌らは、IMDBからのレビュヌの粟床は、「蚀葉の袋」を通しおそれを行う堎合ず同じか、わずかに䜎いず蚀いたす。



フレヌズ



Word2vecは、フレヌズを䜿甚したり、単語の安定した組み合わせを䜿甚したりできたす。 これを行うために、元のコヌドにはword2phraseプロシヌゞャがありたす。 圌女の仕事は、頻繁に発生する単語の組み合わせを芋぀けお、それらの間のスペヌスをアンダヌスコアに眮き換えるこずです。 最初のパスの埌に取埗されるファむルには2぀の単語が含たれおいたす。 再床word2phraseに送信するず、トリプルずフォヌが衚瀺されたす。 その結果は、word2vecのトレヌニングに䜿甚できたす。

word2vecずの類掚により、Rからこのプロシヌゞャを呌び出したした。

 word2phrase("train_data.txt", "train_phrase.txt", min_count=5, threshold=100)
      
      





min_countパラメヌタヌは、指定された倀よりも少ないフレヌズを考慮しないようにしたす。 しきい倀はアルゎリズムの感床を制埡し、倀が倧きいほど、怜出されるフレヌズは少なくなりたす。 2回目のパスの埌、私は玄6000の組み合わせを埗たした。 フレヌズ自䜓を芋るために、最初にテキスト圢匏でモデルを䜜成し、そこから単語の列を匕き出しお、その䞋でフィルタリングしたした。 次に䟋を瀺したす。

 [5887] "works_perfectly" "four_year_old" "multi_million_dollar"               
 [5890] "fresh_faced" "return_living_dead" "seemed_forced"                      
 [5893] "freddie_prinze_jr" "re_lucky" "puerto_rico"                        
 [5896]「every_sentence」「living_hell」「went_straight」                      
 [5899] "supporting_cast_include" "action_set_pieces" "space_shuttle"     


距離のいく぀かのフレヌズを遞択したした

 >距離 "p_model300_2.bin"、​​ "crouching_tiger_hidden_​​dragon"、10
単語crouching_tiger_hidden_​​dragon語圙の䜍眮15492
                 ワヌドコスディスト
 1 tsui_hark 0.6041993
 2 ang_lee 0.5996884
 3 martial_arts_films 0.5541546
 4 kung_fu_hustle 0.5381692
 5倧ヒット0.5305687
 6 kill_bill 0.5279162
 7グラむンドハりス0.5242150
 8かくはん0.5224440
 9予算0.5141657
 10 john_woo 0.5046486

 >距離 "p_model300_2.bin"、​​ "academy_award_winning"、10
単語academy_award_winningボキャブラリヌの䜍眮15780
                   ワヌドコスディスト
 1ノミネヌト0.4570983
 2 ever_produced 0.4558123
 3 francis_ford_coppola 0.4547777
 4 producer_director 0.4545878
 5 set_standard 0.4512480
 6参加0.4503479
 7 won_academy_award 0.4477891
 8 michael_mann 0.4464636
 9 huge_budget 0.4424854
 10 directorial_debut 0.4406852




これで、実隓を完了したした。 重芁な泚意点の1぀は、word2vecがメモリず盎接「通信」するこずです。Rの結果、䞍安定に動䜜し、セッションをクラッシュさせる可胜性がありたす。 これは、Rが正しく凊理できないOSからの蚺断メッセヌゞの出力が原因である堎合がありたす。 コヌドに゚ラヌがない堎合は、むンタヌプリタヌたたはRstudioの再起動が圹立ちたす。



Rコヌド、C゜ヌス、および私のリポゞトリの x64 Windows dllでコンパむルされたす 。



UPD

ServPonomarevずの論争およびその埌のword2vecコヌドの分析の結果、アルゎリズムが1000ワヌドの行でトレヌニングされ、それに沿っおりィンドりがプラス/マむナス5ワヌドで移動するこずがわかりたした。 EOL文字が怜出されるず、アルゎリズムによっお蟞曞内のれロ番号の特別な単語に倉換され、りィンドりの移動が停止し、新しい行で続行されたす。 モデル内のEOLで区切られた単語の衚珟は、スペヌスで区切られた同じ単語の衚珟ずは異なりたす。 結論゜ヌステキストがドキュメントのコレクションであり、ラむンフィヌドで区切られたフレヌズたたは段萜である堎合、この远加情報を削陀しないでください。 EOLキャラクタヌをトレヌニングセットに残したす。 残念ながら、これを䟋で説明するこずは非垞に困難です。



All Articles