ニシキヘビってかわいいよね、実際みたことないけど。

無職がいよかん国でプログラミングとかの備忘録を書いてます。 一日一食たまごかけごはん。

gensimのLdaModel実行時に「too few updates ~」 と怒られた時

投稿の練習,昨日Qiitaで書いたやつ.

なんすかこれ...
passesかiterationsをいじればいいっぽいけど
数値計算のパラメタ調整とか中身知らないので本当に怖い.

model_lda = LdaModel(corpus=corpus, num_topics=30, id2word=corpus.id2word)
WARNING:gensim.models.ldamodel:too few updates, training might not converge; consider increasing the number of passes or iterations to improve accuracy

ソースコードを見てみる
問題はinit最後に実行されるupdateメソッド616行付近

if updates_per_pass * passes < 10:
    logger.warning("too few updates, training might not converge; consider "
                   "increasing the number of passes or iterations to improve accuracy")

passesは LdaModelのinitパラメタpassesをそのまま使ってる.
デフォルトで1が代入されている.
updates_per_pass... むむむ...

updateメソッド内_607行らへん

updates_per_pass = max(1, lencorpus / updateafter)

lencorpusはupdateメソッドの585行目付近で len(corpus)の値が代入されている.
要は文書数.この警告が出ている時の文章数は4019.
updateafter...

updateメソッド内_599行目あたり

if update_every:
    updatetype = "online"
    updateafter = min(lencorpus, update_every * self.numworkers * chunksize)
else:
    updatetype = "batch"
    updateafter = lencorpus

updateメソッドの引数指定が無いなら,
update_everyには,initパラメタupdate_everyと同じものが代入される.初期値は1.
updatetypeはonlineになる.
self.numworkersには,initパラメタdistributedがFalseのままなら1が入っている.

chunksizeは...

updateメソッド内_たぶん595行

chunksize = min(lencorpus, self.chunksize)

self.chunksizeはinitパラメタchunksizeとおなじ.デフォルトは2000.

つまり...
updateafter = min(4019, 112000) = 2000
updates_per_pass = max(1, 4019 / 2000) ≒ 2
で,ifの左の評価式は 2*1 になる.アウト.

対策は
・passesを増やす.今回の場合ではpasses=5で怒られなくなる.
・updateafterを小さくする=update_everyかchunksizeを小さくする.
_今回の場合でchunksizeだけを変えるなら400ぐらいにしたら怒られなくなる.

このパラメタについては疲れたので別の日に調べます.