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

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

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

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

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Mecab

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

Q&A

3回答

2890閲覧

単語のデータセットを作成

aoisj

総合スコア27

Python 3.x

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

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Mecab

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

0グッド

0クリップ

投稿2017/09/26 05:57

###やりたいこと
機械学習を行うためのデータセットを作成しようとしています。
具体的には一つの文章(小説など)のテキストファイルを入力として渡すと、
そのテキストファイル内容のジャンルを出力するようにしたいです。
実装しようとしているのは

1.テキストファイル名を入力する
2.指定したテキストファイルの中身を形態素解析する(Mecabを用いる)
3.形態素解析結果を特定の品詞(名詞や動詞)のみに絞り込む(ジャンル判定に影響があるもののみを使いたいため)
4.絞り込んだ単語(品詞?)についてTF-IDF値を求める(本来TF-IDF値は複数の文章から求めるものだが、1つの文章内での相対的な特徴量を求めるために採用している)
5.単語とTF-IDF値のセットをデータセットとして用意する(例:[自転車, 0.33412])

以上の5ステップを考えています。
そして現在は3ステップまで実装が完了しました。
しかし、4ステップ目をどのように実装すれば良いのかが分かりません。
また3ステップ目と4ステップ目の順番が正しいのか(逆ではないのか)を教えていただきたいです。

以下に実装途中のコードを記させていただきます。

-*- coding: utf-8 -*- import numpy as np from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer import sys import MeCab #CountVectorizer():文書ごとの単語の出現頻度を取得 count = CountVectorizer() m = MeCab.Tagger ("-Ochasen") doc = input('select file(ex, ○○.txt):') f = open(doc, "r",encoding = "utf-8") text = f.read() f.close() #絞り込みの基準を設定 """level = float(input('set level(0.0 <= level <= 1.0):'))""" #文字列を改行位置で区切って分割する chunks = m.parse(text).splitlines() #絞り結果を格納 sels = [] #絞り込み for chunk in chunks: print(chunk) #↓[コーヒー コーヒー コーヒー 名詞-一般]のこと cols = chunk.split('\t') if len(cols) >= 4: parts = cols[3].split('-') #名詞or動詞で始まっている場合 → 真 if parts[0].startswith('名詞') or parts[0].startswith('動詞'): #要素を追加 sels.append(chunk) #絞り結果 print('\n%s 絞り込み結果↓\n' %doc) for sel in sels: print(sel)

コード内には質問内容に含まれてない部分がありますが、ご了承ください。

今回初めて機械学習を行うので質問が丸投げのような状態になってしまい、
申し訳ございません。

説明不足なところが多々あると思うので、質問をしていただけると非常にありがたいです。

###実装環境
言語:python3
OS:ubuntu

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

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

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

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

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

guest

回答3

0

説明によるとtfidf.fit_transformは絞り込みを行った後の単語のみからTF-IDF値を計算しているので、
元のテキストファイルの文章内でのTF-IDF値とは異なる値を取ってしまうということでしょうか?

tfidf.fit_transformはTF-IDF値の計算の考え方に基づき計算している関数に過ぎません。したがって、ご質問の回答は、ほぼTF-IDF値とは何かに近いものなので、私が説明するよりも専門図書などで確認することをお勧めします。

お示しいただいたコードの件ですが、inputとoutput、さらには期待するoutputがよくわからないので何とも言えませんでした。まずは、コード上のtfidfが期待した通りの計算結果になっていることをテストしてみていはいかがでしょうか?

投稿2017/10/10 21:31

R.Shigemori

総合スコア3376

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

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

aoisj

2017/10/11 03:52

回答ありがとうございます。 英文のTF-IDF値を求めるプログラムについての説明が不足していたので inputとoutputについて補足させていただきます。 input:例) It is meaningless only to think my long further aims idly. It is important to set my aims but at the same time I should confirm my present condition. Unless I set the standard where I am in any level, Ill be puzzled about what I should do from now on. output: keyword:aims, TF-IDF:0.244338888713 keyword:is, TF-IDF:0.244338888713 keyword:it, TF-IDF:0.244338888713 keyword:my, TF-IDF:0.366508333069 keyword:set, TF-IDF:0.244338888713 keyword:should, TF-IDF:0.244338888713 keyword:the, TF-IDF:0.244338888713 keyword:to, TF-IDF:0.244338888713 [[('aims', 0.24433888871261045)], [('is', 0.24433888871261045)], [('it', 0.24433888871261045)], [('my', 0.36650833306891567)], [('set', 0.24433888871261045)], [('should', 0.24433888871261045)], [('the', 0.24433888871261045)], [('to', 0.24433888871261045)]] このようになっています。 上記のinputはファイル名によって指定するので、 厳密にはinputはファイル名となっています。 またTF-IDF値の絞り込みを行うための基準値を設定するために、 ファイル名の入力後、基準値を入力するようにしています。 R.Shigetomiさんの私の質問に関する解釈は正しいです。 やはり形態素解析後、TF-IDF値を求めてから 品詞の絞り込みを行わないといけないということでしょうか? TF-IDF値については理解できていたつもりだったのですが、 学習不足だったのかもしれません。
R.Shigemori

2017/10/11 13:40

ジャンル識別という観点からいうと、語を絞り込んだほうがいいかと思います。絞り込みを行わないと疎行列になり過ぎて、特徴量として役に立たなくなると思います。ただ、絞り込み過ぎるとTFIDF値が近似し過ぎてその後の識別がうまく機能しない可能性もあります。かといって差がありすぎる場合もうまく機能しないことがありそうなので、試行錯誤するしかないかもしれません
guest

0

前後のコードをよく見ずに回答した部分がありましたので、改めて説明します。
私のサンプルコードでいうselsには形態素解析によって指定した品詞のみがひとつの文として結合された要素になります。
例えば、「私は駅に行く」を形態素解析にかけると"私","は","駅","に","行く"となります。このうち、名詞と動詞のみを使うとすると、"私","駅","行く"になりますが、TF-IDFを算出するためには、この3つをつなげて"私 駅 行く"とひとつの文に結合する必要があります。ただし、この方法は私が使っている方法であって、もしかすると形態素の配列のまま処理できるかもしれません。そのあたりは公式ドキュメントを確認してください。

tfidf.fit_transformは、この"私 駅 行く"をあらためて、"私","駅","行く"という単語に分解してTF-IDFの計算処理をします。処理結果は、to_array()メソッドで取得できる計算結果とget_feature_names()で取得できる計算結果に対応する単語の配列に分かれます。実は、to_array()に含まれる計算結果の順番はインプットの語順通りである保証はありません。そのため、計算結果の配列と単語との対応関係を明示するためにget_feature_names()で単語を確認する必要があります。

正直なところ、言葉で説明してもイメージがつかみにくいところが多々あるかと思いますので、英文を事例に上記の処理を行ってみるとtfidf.fit_transformが何を行い、その結果がどのようなものになるのかがつかめるかと思います。その上で、希望する処理をするためにはどのようなデータを与えるべきかを検討されることをお勧めします。
あえて、英文が始めることをお勧めするのは、tfidf.fit_transformは(それ以外もおおむねそうなのですが)英文のように単語間がスペースで区切られていることが前提となっている処理であることを理解するためです。また、処理の単位である文章をtfidfがどのように認識しているのかもいろいろと実験するとわかるかと思います。

投稿2017/10/10 13:01

R.Shigemori

総合スコア3376

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

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

aoisj

2017/10/10 16:07

丁寧なご回答感謝します。 説明によるとtfidf.fit_transformは絞り込みを行った後の単語のみからTF-IDF値を計算しているので、元のテキストファイルの文章内でのTF-IDF値とは異なる値を取ってしまうということでしょうか? 異なる値を取ってしまう場合、元の文章内でのTF-IDF値を計算後、 品詞で絞り込むといった方法は可能でしょうか?ご意見をいただきたいです。 また、このプログラムを実装する前に英文での形態素解析を行い、 最初の質問に記したような[単語(形態素),TF-IDF値]という形のデータセット(行列?)を作成する プログラムを実装しました。 理由は形態素解析がうまくできていなかったので、英文からTF-IDF値の計算をやってみようと考えたからです。 以下にそのプログラムを記します。 ``` # -*- coding: utf-8 -*- #データセット作成(TF-IDF値を利用) #指定したテキストファイル(日本語は分かち書きされたもののみ)に対応 import numpy as np from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer #文書を指定 doc = input('select file(ex, ○○.txt):') doc_name = doc with open(doc, encoding = 'utf-8') as f: #改行文字を空白に置き換える doc = [f.read().replace('\n', ' ')] f.close() #絞り込みの基準を設定 level = float(input('set level(0.0 <= level <= 1.0):')) #文書を表示 """print('\n%s:%s\n' %(doc_name, doc))""" #CountVectorizer():文書ごとの単語の出現頻度(TF)を取得 count = CountVectorizer() #N種類の文字列を0からN-1までの整数に置き換える bag = count.fit_transform(doc) TF = bag.toarray() #辞書作成 dic = count.get_feature_names() #TfidfTransformer:(文書内の)TF-IDFを計算 tfidf = TfidfTransformer(use_idf = True, norm = 'l2', smooth_idf = True) #全件表示 np.set_printoptions(precision = 2) #語彙辞書から用語文書行列を返す TF_IDF = tfidf.fit_transform(bag).toarray() my_dic = [] #keyword表示 for idx, word, in zip(*np.where(level <= TF_IDF)): print('keyword:%s, TF-IDF:%s'%(dic[word], TF_IDF[(idx, word)])) #my_dic[]に重要語を追加 my_dic.append(list([(dic[word], TF_IDF[(idx, word)])])) #データセット表示 print('\n%s'%my_dic) ``` 見づらいコードで申し訳ありません。 このプログラム場合、各形態素のTF-IDF値はジャンルを分類する際に利用しようとしてまとめているので、今後必要がないと判断すれば絞り込んだ形態素の行列のみをデータセットにしてみようと考えています。 なので、このプログラムを現在実装中のプログラムに適応することができるのかを教えていただきたいです。 質問ばかりになってしまい、申し訳ありません。
guest

0

TFIDF値算出に使用する関数についてこだわりがないようでしたらTfidfVectorizerを使った以下のようなコードでいかがでしょうか?

python

1from sklearn.feature_extraction.text import TfidfVectorizer 2 3tfidf = TfidfVectorizer() 4result = tfidf.fit_transform(sels) # TFIDF値の算出 5 6tfidf_arr = result.toarray() # 値の取得 7tfidf_FeatureName = result.get_feature_names() # 単語名称の取得 8

このtfidf_arrですが、行は文章になります。列は単語になりますが、列番号と単語の対応関係はtfidf_FeatureNameに格納しています。したがって単語単位のTFIDF値を見たい場合は、tfidf_FeatureNameからtfidf_arrを検索するイメージになります。

投稿2017/09/29 22:42

R.Shigemori

総合スコア3376

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

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

aoisj

2017/10/03 04:43

返事が遅れてしまい、申し訳ありません。 丁寧なご回答ありがとうございます。 教えていただいたコードを該当すると思われる箇所に埋め込んでみたのですが、 「AttributeError: get_feature_names not found」 というエラーメッセージが出てしまいました。 get_feature_names関数を書いた行にはエラーも警告も出ていないと思うので原因が分かりません。 またtfidf_arrの行が文章、列が単語という説明をいただいたのですが、 理解が追いついていないので、もう少し詳しい説明をいただきたいです。 よろしくお願いいたします。
R.Shigemori

2017/10/03 23:40

すみません。コードに間違いがありました。get_feature_names()は、tfidfに対して行うものでした、したがって、その部分は tfidf.get_feature_names() になります。 tfidf_Vectorizerは、以下のような動作をします。 <対象データ1> No 文章 1 "I go to a school" 2 "I want to go to the park tomorrow" <toarraryの出力イメージ> No I go to school want the parrk 1 2 なお、上記の空欄部分はtfidfの計算結果が入ります。 行が文章を表すというのは、上記のNoに相当します。また、列が単語を表すというのは、上記のIやgoに相当します。私の場合は、tfidf_arrをDataFrameにし、get_feature_names()の結果をこのDataFrameのcolumnにあてることで先のイメージに近い処理結果にしています。 なお、入力データが以下のような場合、処理結果に相違が発生します。 <対象データ2> No 文章 1 "I go to a school I want to go to" 2 "the park tomorrow" ifidfは、No=1 No=2 をひとつの固まりとして計算するので、上記のケースの場合、No=2には go という単語がないと認識されて計算されます。一方、<対象データ1>の場合、No=2には go が存在することとして計算されます。したがって、「行が文章をあらわす」としていますが、この文章の単位をどのように定義するのかが結構重要になります。
aoisj

2017/10/10 06:50

返事が遅れてしまい、申し訳ありません。 R.Shigetomiさんのアドバイスなども参考にし、 現段階で自分なりに理解できているのかを確認したいので、 以下に記したことで解釈が間違っている箇所や 不足している箇所があれば、ご指摘をいただきたいです。 sels:形態素解析され、指定した品詞の形態素のみが格納された配列 result:selsの形態素のTF-IDF値の計算計算結果(中身は分かっていません) tfidf_arr:resultが格納された配列 tfidf_FeatureName:分かりませんでした。 get_featurenames()については何度か機能を調べたのですが、 どのような機能の関数なのかが今いち理解できませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問