59928


タイトルの通りです  
Sentencepieceをmodel_type=bpeで訓練を行いました。  
corpus.txtはプロによる校正済みの日本語文書です。一行あたりに一文が書かれています。  
文章の総数は約200,000文です。

[code]

    import sentencepiece as spm
    spm.SentencePieceTrainer.Train('--input=corpus.txt --model_prefix=index --vocab_size=32000 --model_type=bpe --max_sentence_length=200000 --character_coverage=1.0')
    sp = spm.SentencePieceProcessor()
    sp.Load("index.model")
    sp.EncodeAsIds("総務省は地方自治体に向けて改善案を提出した。") #著作権の都合により適当な文章を入力としています
    sp.EncodeAsPieces("総務省は地方自治体に向けて改善案を提出した。")
    
[/code]

訓練に使用した一部をIDに変換したところ以下のようにUNKを指すIDが発生しました。

[code]

    [12667, 28077, 15866, 25464, 0, 21805, 0, 19801, 21301, 27760, 0, 23969, 0, 31770, 19800, 0]
    ['▁', '総', '務', '省', 'は地方', '自', '治体に向け', 'て', '改', '善', '案を', '提', '出', 'し', 'た', '。']
    
[/code]

UNKを発生しないようにするにはどのような処理が必要でしょうか。

追記:  
sentencepieceのversionを確認したところ0.1.83でした


CC BY-SA 4.0
2019-10-23T00:44:29.813
59890
2019-10-24T12:36:27.110
2019-10-24T12:36:27.110
36311
36311
question
python
SentencepieceでBPEを訓練する際にどうしても0（UNK）が発生してしまう


可能性として、データの問題か、あるいはsentencepieceの問題があります。

JESCというデータを使って検証する場合、以下を実行します:

[code]

    wget https://nlp.stanford.edu/projects/jesc/data/split.tar.gz
    tar xzvf split.tar.gz
    cd split
    cut -f2 train > train.ja
    
[/code]

[code]

    import sentencepiece as spm
    spm.SentencePieceTrainer.Train(
        '--input=./split/train.ja --model_prefix=index --vocab_size=32000 --model_type=bpe --max_sentence_length=200000 --character_coverage=1.0'
    )
    spm.SentencePieceTrainer.Train(
        '--input=./split/train.ja --model_prefix=index2 --vocab_size=32000 --model_type=bpe --max_sentence_length=200000 --character_coverage=0.9995'
    )
    
    sp1 = spm.SentencePieceProcessor()
    sp1.Load("index.model")
    
    sp2 = spm.SentencePieceProcessor()
    sp2.Load("index2.model")
    
    print(sp1.EncodeAsIds("総務省は地方自治体に向けて改善案を提出した。"))
    print(sp1.EncodeAsPieces("総務省は地方自治体に向けて改善案を提出した。"))
    print(sp2.EncodeAsIds("総務省は地方自治体に向けて改善案を提出した。"))
    print(sp2.EncodeAsPieces("総務省は地方自治体に向けて改善案を提出した。"))
    
[/code]

[出力]

[code]

    [3518, 12114, 26197, 11252, 26306, 26687, 26370, 8349, 6439, 24385, 26933, 1335, 26220]
    ['▁総', '務省', 'は', '地方', '自', '治', '体', 'に向けて', '改善', '案を', '提', '出した', '。']
    [3518, 12114, 28791, 11252, 28900, 29281, 28964, 8349, 6439, 24385, 29527, 1335, 28814]
    ['▁総', '務省', 'は', '地方', '自', '治', '体', 'に向けて', '改善', '案を', '提', '出した', '。']
    
[/code]

EncodeAsIds内の文は任意です。

もし、このスクリプトの実行によってunkがなくなったのであれば、問題はデータにあった可能性が高いということになります。データの問題としての可能性は、

  * データが少ない。
  * corpus.txtがutf-8ではない。
  * データがトーカナイズされている。
  * データ内に印字不能文字等、なんらかの不正な文字が含まれている。

などがあると思います。

しかし、これでもunkが出るのであれば、問題はsentencepieceにある可能性があります。その場合、sentencepieceのgithubページを確認し、最新バージョンに対して正しい方法でコンパイル・インストールを行ってください。  
<https://github.com/google/sentencepiece>

詳しい回答を希望する場合、sentencepieceの公式のgithubページからissueを投稿すると良いでしょう。


CC BY-SA 4.0
2019-10-24T04:14:13.800
59928
2019-10-24T04:36:43.310
2019-10-24T04:36:43.310
59890
answer