質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

Mecab

Mecabは、オープンソースの形態素解析エンジンです。 言語、辞書、コーパスに依存しない汎用的な設計を基本方針としています。 Mecabの由来は、開発者の好物である和布蕪(めかぶ)から名づけられました。

Q&A

1回答

1632閲覧

テストデータのコーパス生成でエラー

aoisj

総合スコア27

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

Mecab

Mecabは、オープンソースの形態素解析エンジンです。 言語、辞書、コーパスに依存しない汎用的な設計を基本方針としています。 Mecabの由来は、開発者の好物である和布蕪(めかぶ)から名づけられました。

0グッド

0クリップ

投稿2017/12/07 08:36

###困っていること
こちらを参考にして学習データから作成した辞書とLDAモデルを使って入力データのトピック分布を
求めるプログラムを作成したのですが、
以下に記すプログラムの

python

1#既存の辞書を使用して、入力データのコーパスを作成 2test_corpus = get_corpus(dictionary, test_texts)

↑この部分で

raise TypeError("doc2bow expects an array of unicode tokens on input, not a single string") TypeError: doc2bow expects an array of unicode tokens on input, not a single string

↑このようなエラーが出てしまいました。
学習データのコーパス作成はうまくいっているので、原因が分かりません。
原因と解決策を教えていただきたいです。

###実装中のコード

python

1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4""" 5トピックモデル(入力:novel_setの全ての.txtファイル) 6各ファイルの管理可能 7形態素解析対象:名詞(代名詞,非自立名詞,数,固有名詞を除く) 8NGワード:あり 9""" 10 11import time 12import glob 13import MeCab 14from gensim import corpora, models 15 16def get_files(path): 17 return glob.glob(path) 18 19#形態素解析 20def get_texts(file_list, NG_WORDS): 21 mecab = MeCab.Tagger ("-Ochasen") 22 23 texts = [] 24 25 for file in file_list: 26 f = open(file, "r",encoding = "utf-8") 27 text = f.read() 28 f.close() 29 #形態素解析(文字列を改行位置で区切って分割) 30 chunks = mecab.parse(text).splitlines() 31 32 #絞り込み 33 sels = [] 34 for chunk in chunks: 35 cols = chunk.split('\t') 36 if len(cols) >= 4: 37 parts = cols[3].split('-') 38 #指定した品詞で始まっている場合 → true 39 if parts[0].startswith('名詞'): 40 #代名詞,非自立名詞,固有名詞,数を含めない 41 if parts[1] in ['代名詞','非自立','固有名詞','数']: 42 continue 43 #NGワードを含めない 44 if cols[2] in NG_WORDS: 45 continue 46 #形態素を追加 47 sels.append(cols[2]) 48 texts.append(sels) 49 return texts 50 51def get_test_texts(test_documents,NG_WORDS): 52 mecab = MeCab.Tagger ("-Ochasen") 53 f = open(test_documents, "r",encoding = "utf-8") 54 text = f.read() 55 f.close() 56 57 chunks = mecab.parse(text).splitlines() 58 59 sels = [] 60 61 #絞り込み 62 for chunk in chunks: 63 #chunk:形態素解析結果(1行の文字列) 64 #タブ(\t)で区切り、文字列リストを作成 65 cols = chunk.split('\t') 66 if len(cols) >= 4: 67 #parts[0]:品詞の種類 68 parts = cols[3].split('-') 69 #指定した品詞で始まっている場合 → true 70 if parts[0].startswith('名詞'): 71 #代名詞,非自立名詞,固有名詞,数を含めない 72 if parts[1] in ['代名詞','非自立','固有名詞','数']: 73 continue 74 #NGワードを含めない 75 if cols[2] in NG_WORDS: 76 continue 77 #形態素を追加 78 sels.append(cols[2]) 79 return sels 80 81def get_dictionary(texts): 82 dictionary = corpora.Dictionary(texts) 83 return dictionary 84 85def get_corpus(dictionary, texts): 86 corpus = [dictionary.doc2bow(text) for text in texts] 87 return corpus 88 89def get_lda_model(corpus, dictionary, num_topics=10): 90 lda = models.LdaModel(corpus=corpus, id2word=dictionary, num_topics=num_topics) 91 return lda 92 93#入力ファイル指定 94test_documents = input('select file(ex, ○○.txt):') 95 96t0 = time.time() 97 98#file_list[file_no]:ファイル番号file_noのファイル名 99file_list = get_files('hosizora/*.txt') 100 101NG_WORDS = ['「','」','『','』'] 102 103texts = get_texts(file_list, NG_WORDS) 104 105#辞書作成 106dictionary = get_dictionary(texts) 107 108#辞書加工 109""" 110no_below:出現回数no_below回以下の単語を無視 111no_above:全体のno_above以上に出現した単語を無視(no_above = 0.3 ➝ 30%) 112""" 113dictionary.filter_extremes(no_below = 5, no_above = 0.3) 114 115#学習データのコーパス作成 116corpus = get_corpus(dictionary, texts) 117 118t1 = time.time() 119 120#LDAモデルに投入 121lda = get_lda_model(corpus, dictionary) 122 123#入力データを形態素解析 124test_texts = get_test_texts(test_documents,NG_WORDS) 125 126#既存の辞書を使用して、入力データのコーパスを作成 127test_corpus = get_corpus(dictionary, test_texts) 128 129t2 = time.time() 130 131print(lda) 132 133#各トピックにおける各トークンの出現確率を係数で表示 134for topic in lda.show_topics(-1): 135 print(topic) 136 137print('ファイル数:%d'%len(file_list)) 138 139corpus_time = t1 - t0 140print('コーパス生成時間:%f秒'%corpus_time) 141 142lda_time = t2 -t1 143print('LDAモデル生成時間:%f秒'%lda_time) 144 145total_time = t2 - t0 146print('合計時間:%f秒'%total_time)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

2点ほど

(1)
get_test_texts() の動作をちゃんとテストしてますか?
実際にファイルを指定して、戻り値を確認してますか?

return sels

のインデントは、それで問題ないのですか?

(2)
get_test_texts() の戻り値の形式はどうなってますか?

https://teratail.com/questions/96679

と全く同じ間違いをしていませんか?

投稿2017/12/07 10:13

magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aoisj

2017/12/08 06:47

回答ありがとうございます。 実際にget_test_texts()が正常に動いているのか確認してみたところ、 return selsのインデント間違いに気づきました。 get_test_texts()内におけるfor文と同じインデントに書くことで解決できたと思います。 しかし、test_corpus = get_corpus(dictionary, test_texts) の部分で質問文と同じエラーが出てしまいます。 corpusとtest_corpusはどちらもリスト型なので戻り値の形式に問題はないと思っているのですが・・・。 以前の質問と同じようなミスであれば大変申し訳ありません。 プログラムが長くなってきていて、全体をよく見れていないところがあると思うので 教えていただけると非常にありがたいです。
magichan

2017/12/08 11:26 編集

get_corpus()関数内の dictionary.doc2bow() は引数として "Word List" を受け取ります。がここでは内包表記でループしてますので、get_corpus()関数の第2引数である texts は "Word List の List" を渡す必用があります。 一方、 get_test_texts() の戻り値は "Word List" であるようですのでエラーが出ております。
aoisj

2017/12/08 13:57

回答ありがとうございます。 学習データとテストデータの両方でget_corpus()を使えるようにするためには 内包表記ではなく、普通のfor文で記述すれば解決できるということでしょうか?
magichan

2017/12/08 16:47

内包表記であろうとfor文であろうとループを回している事には変わりがないので同じ結果でしょう。 とりあえず動作するようにするのであれば、get_test_texts()の戻り値を return [sel] などとして、Listで囲ってあげるとよいのではないでしょうか?
aoisj

2017/12/10 18:07

回答ありがとうございます。 いただいたアドバイス通りに実装してみたところ、テストデータのトピック分布を見ることができました。 学習データのトピック分布の上位3つを取り出す(扱う)場合は topics_per_document[]を降順に並び替え、 topics_per_document[0],topics_per_document[1],topics_per_document[2] を見ればよいということでしょうか?
aoisj

2017/12/10 18:28

for topics_per_document in lda[test_corpus]: print(topics_per_document) topics_per_document.sort(key = lambda x:x[1]) topics_per_document.reverse() このような感じで並び替えることはできたのですが、 topics_per_document[]をprint文使わず生成できますか?
magichan

2017/12/11 11:57

「printを使わず」の意味がよくわからないのですが、test_corpus に1つのドキュメントの corpusしか格納していない(get_test_texts()が1つのドキュメントのWord Listを返す)のであれば、for文でまわす必用がないので lda_of_test_doc = lda[test_corpus[0]] top3 = [no for no, rate in sorted(lda_of_test_doc, key=lambda d:d[1], reverse=True)][:3] などとしてTOP3を導きけるのではないでしょうか
aoisj

2017/12/14 05:18

返事が遅くなってしまい、申し訳ありません。 頂いたアドバイスを元に lda_of_test_doc = lda[test_corpus[0]] print(lda_of_test_doc) lda_of_test_doc.sort(key = lambda x:x[1]) lda_of_test_doc.reverse() top3 = [] for i in range(3): top3.append(lda_of_test_doc[i]) print(top3) 自分で理解できるようにこのように書いてみました。 ありがとうございました。
magichan

2017/12/14 05:58

はい。それで問題ないかと思います。 自分で理解できるコードを書くことは大事なことなのですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問