2017-06-02 1 views
0

nグラムの機能を使用してsklearnクラシファイアを使用したいと考えています。さらに、n-gramの最良の順序を見つけるためにクロスバリデーションを行いたい。しかし、私はどのように私は一緒にすべての部分を合わせることができますに固執しています。今のnグラムによる分類

、私は次のコードを持っている:私はすべてのループ内での列車試験スプリットを作成するので、これは、それを行うには間違った方法であるように

import pandas as pd 
import numpy as np 
from sklearn.model_selection import train_test_split 
from sklearn.model_selection import cross_val_score 
from sklearn.model_selection import KFold 
from sklearn.feature_extraction.text import CountVectorizer 
from sklearn.naive_bayes import MultinomialNB 

text = ... # This is the input text. A list of strings 
labels = ... # These are the labels of each sentence 
# Find the optimal order of the ngrams by cross-validation 
scores = pd.Series(index=range(1,6), dtype=float) 
folds = KFold(n_splits=3) 

for n in range(1,6): 
    count_vect = CountVectorizer(ngram_range=(n,n), stop_words='english') 
    X = count_vect.fit_transform(text) 
    X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.33, random_state=42) 
    clf = MultinomialNB() 
    score = cross_val_score(clf, X_train, y_train, cv=folds, n_jobs=-1) 
    scores.loc[n] = np.mean(score) 

# Evaluate the classifier using the best order found 
order = scores.idxmax() 
count_vect = CountVectorizer(ngram_range=(order,order), stop_words='english') 
X = count_vect.fit_transform(text) 
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.33, random_state=42) 
clf = MultinomialNB() 
clf = clf.fit(X_train, y_train) 
acc = clf.score(X_test, y_test) 
print('Accuracy is {}'.format(acc)) 

をしかし、私は感じています。

事前に列車テスト分割を行うとclf.fitclf.scoreを使用する際に問題が発生しており、これらの部品が異なるshape秒を持っているよりも、個別の両方の部分にCountVectorizerを適用した場合。

どうすればこの問題を解決できますか?

EDIT:私は最初の語彙を構築しようとした場合ユニグラムのための語彙がバイグラムとは異なっていることから、私はまだ、いくつかの語彙を構築する必要など

例を与える:

# unigram vocab 
vocab = set() 
for sentence in text: 
    for word in sentence: 
     if word not in vocab: 
      vocab.add(word) 
len(vocab) # 47291 

# bigram vocab 
vocab = set() 
for sentence in text: 
    bigrams = nltk.ngrams(sentence, 2) 
    for bigram in bigrams: 
     if bigram not in vocab: 
      vocab.add(bigram) 
len(vocab) # 326044 

これもまた、nグラムサイズごとにCountVectorizerを適用する必要がある同じ問題につながります。

+0

トレーニングセットからボキャブラリを作成します。同じ辞書に単語とバイグラム(とそれ以上)の両方を置くことはできません。 – alexis

答えて

1

最初にvocabularyパラメータを設定する必要があります。ある意味では、ボキャブラリ全体を提供する必要があります。それ以外の場合、次元は決して一致しません(明らかに)。列車/テストの分割を最初に行うと、一方のセットには、もう一方のセットには存在しない単語が存在する可能性があり、次元が一致しないことがあります。

The documentationは言う:

あなたは事前辞書を提供していないとあなたが特徴選択のいくつかの種類を行うアナライザを使用しない場合は、機能の数が、見つかった語彙サイズと等しくなりますデータを分析して

さらに詳しくは、vocabularyの説明があります。

語彙:キーは用語および値である
マッピングまたは反復可能な、任意 マッピングのいずれか(例えば、辞書)は、特徴マトリクスにおける指数、または期間にわたって反復可能です。与えられていない場合、入力文書から語彙が決定される。マッピング内のインデックスは繰り返されてはならず、0と最大インデックスの間に隙間があってはなりません。

+0

さて、私は次のことをします。私は 'text'のすべての単語のリストを取得します。これは' vocab'です。それで、私は 'text'と' labels'を使って列車テスト分割をすることができます。その後、これらの別々の部分で 'CountVectorizer'を実行し、' vocabulary'パラメータを 'vocab'に設定することができます。正しい? – JNevens

+0

@JNevensはい、これはうまくいくはずです。最終的に* n *次元の各単語の特徴ベクトルは* n *はコーパス全体の単語数です。あなたのモデルは* n *次元のベクトルで訓練されます。つまり、次元の数を何とか変更することはできません - あなたのモデルは* m *次元モデルをどのように分類するべきですか? – displayname

+0

私の質問で述べたように、私は、nグラムの異なる順序について分類器を試してみたいと思います。だから、もし私が 'CountVectorizer'を1グラムか2グラムで行うと、これらはボキャブラムとしてすべての単語を持っているのに対し、後者はすべてボキャブラムを持っているので、再び異なるボキャブラリサイズを持ちます。 – JNevens

関連する問題