scikit-learnをテキスト分類に適用


テキストマイニングのpaperは統一的なbenchmarkを見つけることができなくて、自分でプログラムを走るしかなくて、通りかかった先輩が20 newsgroupsあるいはその他の使いやすい公共データセットの分類(すべての種類の分類結果を要して、すべてあるいは一部の特徴を取ってどうでもいい)を知っていたら、面倒な伝言を残して今のbenchmarkに教えて、万謝!
ええ、本文を話します.20 newsgroupsの公式サイトには3つのデータセットがあり、ここでは最も原始的な20 news-1997を使用しています.tar.gz.
次の手順に分けられます.
データセットのロード
提feature 分類
  • Naive Bayes
  • KNN
  • SVM
  • クラスタリング
  • 説明:scipy公式サイト
    参考になりましたが、ちょっと散らかっていてバグがありました.本文ではブロックを分けて見ます.
    Environment:
    Python 2.7 + Scipy (scikit-learn)
    1.データセットのロード
    20 news-1997.tar.gzはデータセットをダウンロードしてscikit_に解凍しますlearn_Dataフォルダの下で、データをロードします.詳細はcodeコメントを参照してください.
    #first extract the 20 news_group dataset to /scikit_learn_data
    from sklearn.datasets import fetch_20newsgroups
    #all categories
    #newsgroup_train = fetch_20newsgroups(subset='train')
    #part categories
    categories = ['comp.graphics',
     'comp.os.ms-windows.misc',
     'comp.sys.ibm.pc.hardware',
     'comp.sys.mac.hardware',
     'comp.windows.x'];
    newsgroup_train = fetch_20newsgroups(subset = 'train',categories = categories);

    loadが完了しているかどうかを確認できます.
    #print category names
    from pprint import pprint
    pprint(list(newsgroup_train.target_names))
    

    結果:
    ['comp.graphics', 'comp.os.ms-windows.misc', 'comp.sys.ibm.pc.hardware', 'comp.sys.mac.hardware', 'comp.windows.x']
    2.提feature:
    さっきloadが入ってきたnewsgroup_trainはdocumentの1編で、私たちはそこからfeatureを抽出して、つまり語頻ああ神馬の、fit_を使いますtransform
    Method 1. HashingVectorizer,規定feature個数
    #newsgroup_train.data is the original documents, but we need to extract the 
    #feature vectors inorder to model the text data
    from sklearn.feature_extraction.text import HashingVectorizer
    vectorizer = HashingVectorizer(stop_words = 'english',non_negative = True,
                                   n_features = 10000)
    fea_train = vectorizer.fit_transform(newsgroup_train.data)
    fea_test = vectorizer.fit_transform(newsgroups_test.data);
    
    
    #return feature vector 'fea_train' [n_samples,n_features]
    print 'Size of fea_train:' + repr(fea_train.shape)
    print 'Size of fea_train:' + repr(fea_test.shape)
    #11314 documents, 130107 vectors for all categories
    print 'The average feature sparsity is {0:.3f}%'.format(
    fea_train.nnz/float(fea_train.shape[0]*fea_train.shape[1])*100);
    

    結果:
    Size of fea_train:(2936, 10000)Size of fea_train:(1955, 10000)The average feature sparsity is 1.002%
    10000語、すなわち10000次元featureしか取らなかったので、疎度はまだ低くありません.実際にはTfidfVectorizer統計で万次元のfeatureが得られ、私が統計したすべてのサンプルは13 w多次元で、かなりまばらな行列です.
    **************************************************************************************************************************
    TF-IDFがtrainとtestで抽出したfeature次元が異なるというコード注記がありますが、どうやって同じにしますか?2つの方法があります.
    Method 2. CountVectorizer+TfidfTransformer
    2つのCountVectorizerにvocabularyを共有させる:
    #----------------------------------------------------
    #method 1:CountVectorizer+TfidfTransformer
    print '*************************
    CountVectorizer+TfidfTransformer
    *************************' from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer count_v1= CountVectorizer(stop_words = 'english', max_df = 0.5); counts_train = count_v1.fit_transform(newsgroup_train.data); print "the shape of train is "+repr(counts_train.shape) count_v2 = CountVectorizer(vocabulary=count_v1.vocabulary_); counts_test = count_v2.fit_transform(newsgroups_test.data); print "the shape of test is "+repr(counts_test.shape) tfidftransformer = TfidfTransformer(); tfidf_train = tfidftransformer.fit(counts_train).transform(counts_train); tfidf_test = tfidftransformer.fit(counts_test).transform(counts_test);

    結果:
    *************************
    CountVectorizer+TfidfTransformer*************************the shape of train is (2936, 66433)the shape of test is (1955, 66433)
    Method 3. TfidfVectorizer
    2つのTfidfVectorizerにvocabularyを共有させる:
    #method 2:TfidfVectorizer
    print '*************************
    TfidfVectorizer
    *************************' from sklearn.feature_extraction.text import TfidfVectorizer tv = TfidfVectorizer(sublinear_tf = True, max_df = 0.5, stop_words = 'english'); tfidf_train_2 = tv.fit_transform(newsgroup_train.data); tv2 = TfidfVectorizer(vocabulary = tv.vocabulary_); tfidf_test_2 = tv2.fit_transform(newsgroups_test.data); print "the shape of train is "+repr(tfidf_train_2.shape) print "the shape of test is "+repr(tfidf_test_2.shape) analyze = tv.build_analyzer() tv.get_feature_names()#statistical features/terms

    結果:
    *************************TfidfVectorizer*************************the shape of train is (2936, 66433)the shape of test is (1955, 66433)
    また、sklearnにカプセル化されたfeature関数、fetch_20newsgroups_vectorized
    Method 4. fetch_20newsgroups_vectorized
    しかし、この方法ではいくつかのクラスのfeatureを選択することはできません.20クラスのfeatureをすべて出すしかありません.
    print '*************************
    fetch_20newsgroups_vectorized
    *************************' from sklearn.datasets import fetch_20newsgroups_vectorized tfidf_train_3 = fetch_20newsgroups_vectorized(subset = 'train'); tfidf_test_3 = fetch_20newsgroups_vectorized(subset = 'test'); print "the shape of train is "+repr(tfidf_train_3.data.shape) print "the shape of test is "+repr(tfidf_test_3.data.shape)

    結果:
    *************************fetch_20newsgroups_vectorized*************************the shape of train is (11314, 130107)the shape of test is (7532, 130107)
    3.分類
    3.1 Multinomial Naive Bayes Classifier
    コード&commentを参照して、説明しない
    ######################################################
    #Multinomial Naive Bayes Classifier
    print '*************************
    Naive Bayes
    *************************' from sklearn.naive_bayes import MultinomialNB from sklearn import metrics newsgroups_test = fetch_20newsgroups(subset = 'test', categories = categories); fea_test = vectorizer.fit_transform(newsgroups_test.data); #create the Multinomial Naive Bayesian Classifier clf = MultinomialNB(alpha = 0.01) clf.fit(fea_train,newsgroup_train.target); pred = clf.predict(fea_test); calculate_result(newsgroups_test.target,pred); #notice here we can see that f1_score is not equal to 2*precision*recall/(precision+recall) #because the m_precision and m_recall we get is averaged, however, metrics.f1_score() calculates #weithed average, i.e., takes into the number of each class into consideration.

    私の最後の3行の注釈に注意して、どうしてf 1≠2*(正確率*リコール率)/(正確率+リコール率)
    ここで、関数calculate_result計算f 1:
    def calculate_result(actual,pred):
        m_precision = metrics.precision_score(actual,pred);
        m_recall = metrics.recall_score(actual,pred);
        print 'predict info:'
        print 'precision:{0:.3f}'.format(m_precision)
        print 'recall:{0:0.3f}'.format(m_recall);
        print 'f1-score:{0:.3f}'.format(metrics.f1_score(actual,pred));
        

    3.2 KNN:
    ######################################################
    #KNN Classifier
    from sklearn.neighbors import KNeighborsClassifier
    print '*************************
    KNN
    *************************' knnclf = KNeighborsClassifier()#default with k=5 knnclf.fit(fea_train,newsgroup_train.target) pred = knnclf.predict(fea_test); calculate_result(newsgroups_test.target,pred);

    3.3 SVM:
    ######################################################
    #SVM Classifier
    from sklearn.svm import SVC
    print '*************************
    SVM
    *************************' svclf = SVC(kernel = 'linear')#default with 'rbf' svclf.fit(fea_train,newsgroup_train.target) pred = svclf.predict(fea_test); calculate_result(newsgroups_test.target,pred);

    結果:
    *************************
    Naive Bayes*************************predict info:precision:0.764recall:0.759f1-score:0.760*************************KNN*************************predict info:precision:0.642recall:0.635f1-score:0.636*************************SVM*************************predict info:precision:0.777recall:0.774f1-score:0.774
    4.クラスタリング
    ######################################################
    #KMeans Cluster
    from sklearn.cluster import KMeans
    print '*************************
    KMeans
    *************************' pred = KMeans(n_clusters=5) pred.fit(fea_test) calculate_result(newsgroups_test.target,pred.labels_);

    結果:
    *************************KMeans*************************predict info:precision:0.264recall:0.226f1-score:0.213
    本明細書のすべてのコードのダウンロード:ここ
    精度が低いようですね…では、すべての特徴を使いましょう……結果は以下の通りです.
    *************************Naive Bayes*************************predict info:precision:0.771recall:0.770f1-score:0.769*************************KNN*************************predict info:precision:0.652recall:0.645f1-score:0.645*************************SVM*************************predict info:precision:0.819recall:0.816f1-score:0.816*************************KMeans*************************predict info:precision:0.289recall:0.313f1-score:0.266
    Pythonの詳細については、引き続き更新されますので、このブログと新浪微博Rachel Zhangに注目してください.