TFIDFをパッケージでする場合、三種類の選択肢があります。
ただし、それぞれ入力や出力が違うので注意が必要です。
モジュール | 入力 | 出力 |
---|---|---|
nltk | 各行、単語に分けたリスト | 行、単語ごとに計算が必要 |
gensim | 各行、単語に分けたリスト | スパースマトリクス |
sklearn | 各行、単語をスペースで繋いだ文字列 | スパースマトリクス |
いったん下記データをつくります
import random chrs = 'python' words = [] for i in range(5): #1行ごとにp,y,t,h,o,nから3~10文字ランダムに選ぶ tmp = random.choices(chrs,k= random.randint(3,10)) words.append(tmp)
NLTKの場合
import nltk collection = nltk.TextCollection(words) #語の一覧 terms = list(set(collection)) d = [] #行ごとに for i,w in enumerate(words): #各語のtfidfを計算 for term in terms: d.append([i,term,collection.tf_idf(term,w)])
最初につくったcollectionからtf_idfを呼び、
対象の語と文章をいれるとtfidfが計算できます。
gensimの場合
from gensim import matutils,models from gensim import corpora dictionary = corpora.Dictionary(words) #各行を順に上記のdoc2bowに渡し、それをmodel化する corp = list(map(dictionary.doc2bow, words)) mdl = models.TfidfModel(corp) #スパースマトリックスにする mtx = matutils.corpus2csc(mdl[corp])
sklearnの場合
from sklearn.feature_extraction import text # 一文字だと判定してくれない、スペースで区切りなので専用データをつくる words = [] for i in range(5): tmp = map(lambda x : x + '_' ,random.choices(chrs,k= random.randint(3,10))) words.append(' '.join(list(tmp))) # 一旦Bag of wordsにする bow = text.CountVectorizer() bow_data = bow.fit_transform(words) #tfidfを計算する tfidf = text.TfidfTransformer(norm=None) #帰ってくるのはスパースマトリクス res = tfidf.fit_transform(bow_data)
sklearnの場合はデフォルトで一文字はカウントしないつくりなので注意が必要です
また、行の中が単語のリストではなく、スペースでつながった一文(実際の英文のようなイメージ)を渡します
全体として
Python的な処理であれば、nltkの方が初心者でもやりやすいとは思います
MLのパイプラインとしては、sklearn/gensimの方が後続はつかいやすいです