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

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

ただいまの
回答率

90.99%

  • Python 3.x

    4117questions

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

  • 機械学習

    486questions

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

  • Mecab

    120questions

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

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

受付中

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 399

aoisj

score 19

やりたいこと

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

0

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

from sklearn.feature_extraction.text import TfidfVectorizer

tfidf = TfidfVectorizer()
result = tfidf.fit_transform(sels) # TFIDF値の算出

tfidf_arr = result.toarray()       # 値の取得
tfidf_FeatureName = result.get_feature_names() # 単語名称の取得

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/03 13:43

    返事が遅れてしまい、申し訳ありません。
    丁寧なご回答ありがとうございます。
    教えていただいたコードを該当すると思われる箇所に埋め込んでみたのですが、
    「AttributeError: get_feature_names not found」
    というエラーメッセージが出てしまいました。
    get_feature_names関数を書いた行にはエラーも警告も出ていないと思うので原因が分かりません。

    またtfidf_arrの行が文章、列が単語という説明をいただいたのですが、
    理解が追いついていないので、もう少し詳しい説明をいただきたいです。
    よろしくお願いいたします。

    キャンセル

  • 2017/10/04 08: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 が存在することとして計算されます。したがって、「行が文章をあらわす」としていますが、この文章の単位をどのように定義するのかが結構重要になります。

    キャンセル

  • 2017/10/10 15:50

    返事が遅れてしまい、申し訳ありません。
    R.Shigetomiさんのアドバイスなども参考にし、
    現段階で自分なりに理解できているのかを確認したいので、
    以下に記したことで解釈が間違っている箇所や
    不足している箇所があれば、ご指摘をいただきたいです。

    sels:形態素解析され、指定した品詞の形態素のみが格納された配列
    result:selsの形態素のTF-IDF値の計算計算結果(中身は分かっていません)
    tfidf_arr:resultが格納された配列
    tfidf_FeatureName:分かりませんでした。

    get_featurenames()については何度か機能を調べたのですが、
    どのような機能の関数なのかが今いち理解できませんでした。

    キャンセル

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/11 01: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値はジャンルを分類する際に利用しようとしてまとめているので、今後必要がないと判断すれば絞り込んだ形態素の行列のみをデータセットにしてみようと考えています。
    なので、このプログラムを現在実装中のプログラムに適応することができるのかを教えていただきたいです。
    質問ばかりになってしまい、申し訳ありません。

    キャンセル

0

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/11 12: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値については理解できていたつもりだったのですが、
    学習不足だったのかもしれません。

    キャンセル

  • 2017/10/11 22:40

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

    キャンセル

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

  • ただいまの回答率 90.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    形態素解析の結果の一部のみを抽出したい

    前提・実現したいこと csvファイルにある文章をPythonを経由してMeCabで形態素解析をしています。  結果を出力する際、特定の品詞(名詞、形容詞、接続詞)と原形だけ

  • 受付中

    TF-IDF値が一定値以上のものをデータとして保持する

    前提・実現したいこと 現在、指定したテキストファイルから一定値以上のTF-IDF値を持つ単語をkeywordとして抽出し、keywordとそのTF-IDF値をセットで入力データとし

  • 解決済

    pythonでMecabを利用した語彙解析がうまくできない。

    ●環境 ・Windows Edition:Windows 7 Professional  Service Pack 1 ・pythonバージョン:Python 3.6.2 (v3.

  • 解決済

    mecab 品詞 選択

    やりたいこと 選択したテキストファイル内の文章をmecabを用いて形態素解析し、 品詞(名詞、動詞など)を絞り込みたいと考えています。 現在、テキストファイルの文章を形態素解析する

  • 解決済

    複数のテキストファイルをLDAモデルに

    やりたいこと 複数のテキストファイルを入力とし、指定したトピック数に分類するプログラムを作成したいと考えています。 現在、一つのテキストファイルをLDAモデルに投入するプログラムは

  • 解決済

    指定した言葉を排除したい

    やりたいこと テキストファイルからトピックモデルを作成するプログラムを実装中なのですが、コーパスを生成するのに用いる辞書に指示語(あれ、ここ、そちら)や、それ自体に重要な意味を持た

  • 解決済

    mecabでセリフのみを抽出したい

    やりたいこと mecabを用いて入力したテキストファイルのセリフ部分(「」や『』で囲まれている部分)の 名詞(代名詞,非自立名詞,数,固有名詞を除く)を取り出して行列selsに格納

  • 解決済

    テキストに番号を付けて管理したい

    困っていること 入力したファイルのトピックを抽出するための前段階として 指定したディレクトリ内の.txtファイルを用いてLDAモデルを作成するプログラムを実装したのですが、 現在の

同じタグがついた質問を見る

  • Python 3.x

    4117questions

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

  • 機械学習

    486questions

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

  • Mecab

    120questions

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