摘要:最后,模型甚至可以返回最能影響分類器分類效果的個(gè)單詞,但是要求分類器有屬性,目前用到的幾個(gè)分類器,似乎都有這個(gè)這個(gè)屬性。
工作上需要用到文本分類,這里用 sklearn 做為工具,記錄下學(xué)習(xí)過(guò)程
目錄1. SVM 文本分類范例
2. sklearn 做文本分類其他可選分類器
3. 文本分類的數(shù)據(jù)預(yù)處理
3. 中文文本分類方法
import numpy as np from sklearn import metrics from sklearn.datasets import fetch_20newsgroups from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import SGDClassifier from sklearn.svm import LinearSVC from sklearn.utils.extmath import density categories = [ "alt.atheism", "talk.religion.misc", "comp.graphics", "sci.space", ] print("Loading 20 newsgroups dataset for categories:") print(categories if categories else "all") dataHome = "/Users/xinsheng/PycharmProjects/PythonPlaygroud/dataset" data_train = fetch_20newsgroups(data_home= dataHome, subset="train", categories=categories, shuffle=True, random_state=42) data_test = fetch_20newsgroups(data_home=dataHome, subset="test", categories=categories, shuffle=True, random_state=42) print("data loaded") y_train, y_test = data_train.target, data_test.target target_names = data_train.target_names vectorizer = TfidfVectorizer(sublinear_tf=True, max_df=0.5, stop_words="english") X_train = vectorizer.fit_transform(data_train.data) X_test = vectorizer.transform(data_test.data) feature_names = vectorizer.get_feature_names() # 在 as array 之前是什么呢 feature_names = np.asarray(feature_names) results = [] def benchmark(clf): clf.fit(X_train, y_train) pred = clf.predict(X_test) if hasattr(clf, "coef_"): print("dimensionality: %d" % clf.coef_.shape[1]) print("density: %f" % density(clf.coef_)) # if opts.print_top10 and feature_names is not None: print("top 10 keywords per class:") for i, label in enumerate(target_names): top10 = np.argsort(clf.coef_[i])[-10:] print("%s: [%s]" % (label, " ".join(feature_names[top10]))) print() print(metrics.classification_report(y_test, pred, target_names=target_names)) for penalty in ["l2", "l1"]: print("=" * 80) print("%s penalty" % penalty.upper()) # Train Liblinear model # svc stands for c-support vector classification print("Linear SVC") benchmark(LinearSVC(penalty=penalty, dual=False, tol=1e-3)) print("SGDClassifier") # Train SGD model benchmark(SGDClassifier(alpha=.0001, n_iter=200, penalty=penalty))
上面這個(gè)例子是官方文檔給出的 SVM 分類實(shí)例,數(shù)據(jù)集是 20 new groups, 如果本地沒(méi)有數(shù)據(jù)集,sklearn 會(huì)自動(dòng)下載
sklearn 的匹配模式非常簡(jiǎn)單,選中模型 clf 后直接調(diào)用 clf.fit(X_train, Y_train) 即可完成模型訓(xùn)練,然后調(diào)用 clf.predict(X_test) 即可返回結(jié)果
需要關(guān)注的是參數(shù)的配置,比如上文中對(duì)于 LinearSVC 和 SGD 來(lái)講,都有一個(gè)很多參數(shù)可以配置,比如 penalty, alpha 等等,下面是參數(shù)的翻譯
SVM 的參數(shù)翻譯
Similar to SVC with parameter kernel="linear", but implemented in terms of liblinear rather than libsvm, so it has more flexibility in the choice of penalties and loss functions and should scale better to large numbers of samples. This class supports both dense and sparse input and the multiclass support is handled according to a one-vs-the-rest scheme. SVM 多 label 分類是多個(gè) binary classifier 的組合 penalty : string, "l1" or "l2" (default="l2") Specifies the norm used in the penalization. The "l2" penalty is the standard used in SVC. The "l1" leads to ``coef_`` vectors that are sparse. 從數(shù)據(jù)集上來(lái)看,l2 的效果好一些 dual : bool, (default=True) Select the algorithm to either solve the dual or primal optimization problem. Prefer dual=False when n_samples > n_features. 一般來(lái)說(shuō) sample > feature, 但是對(duì)于文本分來(lái)來(lái)說(shuō),這個(gè)也不一定為真 tol : float, optional (default=1e-4) Tolerance for stopping criteria. max_iter : int, (default=1000) The maximum number of iterations to be run. tol 和 max_iter 是訓(xùn)練集的終止條件,一個(gè)是按照 loss function 的誤差,一個(gè)是按照最大迭代次數(shù) C : float, optional (default=1.0) Penalty parameter C of the error term. 相當(dāng)于懲罰松弛變量,希望松弛變量接近0,即對(duì)誤分類的懲罰增大,趨向于對(duì)訓(xùn)練集全分對(duì)的情況,這樣對(duì)訓(xùn)練集測(cè)試時(shí)準(zhǔn)確率很高, 但泛化能力弱。C值小,對(duì)誤分類的懲罰減小,允許容錯(cuò),將他們當(dāng)成噪聲點(diǎn),泛化能力較強(qiáng), 對(duì)于那些比較粗糙的數(shù)據(jù),比如說(shuō)文本分類應(yīng)該用較大一些的 C coef_ : array, shape = [n_features] if n_classes == 2 else [n_classes, n_features] Weights assigned to the features (coefficients in the primal problem). This is only available in the case of a linear kernel.
本來(lái)以為 SVC 非線性核的分類效果會(huì)好一些,結(jié)果發(fā)現(xiàn)奇差無(wú)比,然后搜索了下大家對(duì) SVM 的看法
預(yù)測(cè)函數(shù)簡(jiǎn)單f(x) = w’*x+b,分類速度快。對(duì)于類別多的問(wèn)題,分類速度的確需要考慮到,線性分類器的w可以事先計(jì)算出來(lái),而非線性分類器在高維空間時(shí)支持向量數(shù)會(huì)非常多,分類速度遠(yuǎn)低于線性分類器。
線性SVM的推廣性有保證,而非線性如高斯核有可能過(guò)學(xué)習(xí)。再舉個(gè)例子,基于人臉的性別識(shí)別,即給定人臉圖像,判斷這個(gè)人是男還是女。我們提取了3700多維的特征,用線性SVM就能在測(cè)試集上達(dá)到96%的識(shí)別正確率。因此,線性SVM是實(shí)際應(yīng)用最多的,實(shí)用價(jià)值最大的。
如果在你的應(yīng)用中,特征維數(shù)特別低,樣本數(shù)遠(yuǎn)超過(guò)特征維數(shù),則選用非線性核如高斯核是比較合理的。如果兩類有較多重疊,則非線性SVM的支持向量特別多,選擇稀疏的非線性SVM會(huì)是一個(gè)更好的方案,支持向量少分類速度更快。
隨意,非線性 SVM 還不如線性 SVM。
penalty 屬性是 loss function 的定義
另外 sklearn 給出了訓(xùn)練模型的評(píng)價(jià)指標(biāo),以 precision, recall, f1-score, support 來(lái)反應(yīng)模型的好壞。
最后,clf 模型甚至可以返回最能影響分類器分類效果的 top K 個(gè)單詞,但是要求分類器有 coef 屬性,目前用到的幾個(gè)分類器,似乎都有這個(gè)這個(gè)屬性。
除了 SVM 分類外,還要很多分類器可選,下面列出若干常用分類器
results = [] for clf, name in ( (RidgeClassifier(tol=1e-2, solver="lsqr"), "Ridge Classifier"), (Perceptron(n_iter=50), "Perceptron"), (PassiveAggressiveClassifier(n_iter=50), "Passive-Aggressive"), (KNeighborsClassifier(n_neighbors=10), "kNN"), (RandomForestClassifier(n_estimators=100), "Random forest") ): print("=" * 80) benchmark(clf)
除了上面提到的分類器以外,還有一個(gè)是貝葉斯分類,貝葉斯分類我在研究生階段就學(xué)習(xí)過(guò),它根據(jù)單詞和文本的對(duì)應(yīng)關(guān)系來(lái)分類文檔,因?yàn)槟撤N類型的文檔就會(huì)出現(xiàn)某種類型的單詞,下面是我找到的別人寫好的例子。
nbc = Pipeline([ ("vect", TfidfVectorizer()), ("clf", MultinomialNB(alpha=1.0)), # 或者使用 BernoulliNB ]) nbc_6.fit(train_data, train_target) #訓(xùn)練我們的多項(xiàng)式模型貝葉斯分類器 predict = nbc_6.predict(test_data) #在測(cè)試集上預(yù)測(cè)結(jié)果 count = 0 #統(tǒng)計(jì)預(yù)測(cè)正確的結(jié)果個(gè)數(shù) for left , right in zip(predict, test_target): if left == right: count += 1 print(count/len(test_target)) out: 0.793
benchmark 函數(shù)還是定義的那個(gè),從分類的結(jié)果來(lái)看,這幾種分類器的分類效果也都不錯(cuò),且運(yùn)算時(shí)間都不長(zhǎng),考慮到未來(lái),深度學(xué)習(xí)的時(shí)間可以控制在數(shù)十秒以內(nèi),人工智能肯定再會(huì)上一個(gè)臺(tái)階。
隨機(jī)森林分類器:
經(jīng)典的決策樹(shù)是一個(gè)顆樹(shù),按照特征的信息增益來(lái)選擇分裂樣本,計(jì)算公式不是很復(fù)雜。一句來(lái)來(lái)解釋,就是樣本的正反和特征的正反吻合的比較好,這種特征認(rèn)為和數(shù)據(jù)關(guān)系較大,因此可以用來(lái)選取作為分裂特征
?
隨機(jī)森林是從數(shù)據(jù)集中有放回的拿數(shù)據(jù),每個(gè)子數(shù)據(jù)的數(shù)量和原數(shù)據(jù)一樣,所以子數(shù)據(jù)很可能有重復(fù)數(shù)據(jù),然后每個(gè)子數(shù)據(jù)訓(xùn)練數(shù)據(jù)集,最后大家投票,選擇分類。
?
KNN
KNN 是有監(jiān)督的學(xué)習(xí)方法,不同于 Kmeans 的無(wú)監(jiān)督學(xué)習(xí)方法。它的核心是每個(gè)樣本都可以用它最近的幾個(gè)鄰居來(lái)表示,如果一個(gè)樣本在特征空間中的k個(gè)最相似(即特征空間中最鄰近)的樣本中的大多數(shù)屬于某一個(gè)類別,則該樣本也屬于這個(gè)類別。KNN算法中,所選擇的鄰居都是已經(jīng)正確分類的對(duì)象。該方法在定類決策上只依據(jù)最鄰近的一個(gè)或者幾個(gè)樣本的類別來(lái)決定待分樣本所屬的類別。 KNN方法雖然從原理上也依賴于極限定理,但在類別決策時(shí),只與極少量的相鄰樣本有關(guān)。由于KNN方法主要靠周圍有限的鄰近的樣本,而不是靠判別類域的方法來(lái)確定所屬類別的,因此對(duì)于類域的交叉或重疊較多的待分樣本集來(lái)說(shuō),KNN方法較其他方法更為適合。
優(yōu)缺點(diǎn):
特別適合于多分類問(wèn)題(multi-modal,對(duì)象具有多個(gè)類別標(biāo)簽), kNN比SVM的表現(xiàn)要好
該算法在分類時(shí)有個(gè)主要的不足是,當(dāng)樣本不平衡時(shí),如一個(gè)類的樣本容量很大,而其他類樣本容量很小時(shí),有可能導(dǎo)致當(dāng)輸入一個(gè)新樣本時(shí),該樣本的K個(gè)鄰居中大容量類的樣本占多數(shù)。 該算法只計(jì)算“最近的”鄰居樣本,某一類的樣本數(shù)量很大,那么或者這類樣本并不接近目標(biāo)樣本,或者這類樣本很靠近目標(biāo)樣本。無(wú)論怎樣,數(shù)量并不能影響運(yùn)行結(jié)果。
該方法的另一個(gè)不足之處是計(jì)算量較大,因?yàn)閷?duì)每一個(gè)待分類的文本都要計(jì)算它到全體已知樣本的距離,才能求得它的K個(gè)最近鄰點(diǎn)。
Perceptron
感知器分類器,從文檔上來(lái)看,它似乎是線性回歸的
SGD
隨機(jī)梯度下降,好處是能夠跳出局部最優(yōu)解
上面使用到的數(shù)據(jù)集都是 sklearn 自帶的,真正應(yīng)用時(shí),需要自己處理數(shù)據(jù),在一開(kāi)始,這是最耗費(fèi)時(shí)間的過(guò)程。
下面是一個(gè)生成一個(gè)分類器可用數(shù)據(jù)的格式
def fetchTrainData(datadir, type, data = [], target = []): for file in os.listdir(datadir): with open(datadir + file) as f: file_data = [] for row in f: file_data.append(row) data.append(" ".join(file_data)) target.append(type) def jiebaTfIdf(data, virgin, vectorizer): # 語(yǔ)料庫(kù)是一個(gè)一維數(shù)組,數(shù)組的每一個(gè)元素是一個(gè)文檔(經(jīng)過(guò)預(yù)處理) corpus = [] for lines in data["data"]: # cut_all 是什么意思呢? words = jieba.cut(lines, cut_all=True) stopFreeLine = [] for word in words: if word != "" and word != " " and word != " " and word not in STOP_WORDS: stopFreeLine.append(word) # 再把此行加入到命令中 corpus.append(" ".join(stopFreeLine)) # 使用對(duì)單詞進(jìn)行 tfidf 預(yù)處理 # 返回的 shape 是 112 * 6111 這是什么意思呢? # fit_transform 和 transform 的區(qū)別是什么呢 if virgin: tfidf = vectorizer.fit_transform(corpus) else: tfidf = vectorizer.transform(corpus) # feature_names = vectorizer.get_feature_names() return tfidf fetchTrainData(api_train_dir, "0", train_data, target) fetchTrainData(other_train_dir, "1", train_data, target) cache = dict(data = train_data, target=target,target_name=target_name) vectorizer = TfidfVectorizer(sublinear_tf=True, stop_words="english") X_train = jiebaTfIdf(cache, True, vectorizer) clf.fit(X_train, y_train)
X_train 和 y_train 函數(shù)都是數(shù)組,在放入 vectorizer 之前,x_train.data 就是郵件
本身,它是一個(gè)長(zhǎng)度為 2034 的 array: len(x_train.data) -> 2034, 下面是數(shù)組中的
第一個(gè)元素
"From: rych@festival.ed.ac.uk (R Hawkes) Subject: 3DS: Where did all the texture rules go? Lines: 21 Hi, I"ve noticed that if you only save a model (with all your mapping planes positioned carefully) to a .3DS file that when you reload it after restarting 3DS, they are given a default position and orientation. But if you save to a .PRJ file their positions/orientation are preserved. Does anyone know why this information is not stored in the .3DS file? Nothing is explicitly said in the manual about saving texture rules in the .PRJ file. I"d like to be able to read the texture rule information, does anyone have the format for the .PRJ file? Is the .CEL file format available from somewhere? Rych ===================================================== ================= Rycharde Hawkes email: rych@festival.ed .ac.uk Virtual Environment Laboratory Dept. of Psychology Tel : +44 31 650 3426 Univ. of Edinburgh Fax : +44 31 667 0150 ====== ================================================================ "
在進(jìn)入 vectorizer 之后,就變成了一個(gè)矩陣, x_train.shape = (2034, 33809), 每一個(gè)文檔
變成了一個(gè)有 33809 個(gè)詞向量表示的數(shù)組,這個(gè)地方需要注意,fit_transform 和 transform
的區(qū)別,fit_transform 會(huì)計(jì)算需要多少個(gè)詞來(lái)描述一個(gè)文檔,33809 是這個(gè)函數(shù)的輸出之一,而
transform 就用把自己的數(shù)據(jù)變成 33809 個(gè)詞的矩陣,因此對(duì)于訓(xùn)練數(shù)據(jù)集用 fit_transform,
對(duì)測(cè)試集使用 transform, 千萬(wàn)不能多次調(diào)用 fit_transform.
TF-IDF Vectorizer 對(duì)一個(gè)文檔的描述
(0, 26977) 0.29200533962 (0, 13788) 0.223534884596 (0, 12254) 0.143033187036 (0, 4287) 0.112190889038 (0, 31453) 0.104409646825 (0, 15786) 0.23558806939 (0, 2362) 0.260611070013 (0, 11264) 0.0532815955186 (0, 30376) 0.223037634455 (0, 26918) 0.134980938364 (0, 1621) 0.0655837805259 (0, 16025) 0.0699392301968 (0, 32232) 0.0508220378498 (0, 22173) 0.100565143276 (0, 27212) 0.134980938364
起初,我對(duì)這個(gè)數(shù)據(jù)很疑惑,為什么不表示成一個(gè)矩陣的形式,后來(lái)看到一個(gè)例子才搞明白,因?yàn)?br>數(shù)組較長(zhǎng),所以我們把那些不為 0 的詞拿出來(lái)就好,比如第一行,就是 26977 個(gè)位置的詞不為0 ,
其值為 0.29200533962。
sklearn 不支持中文的分詞器,所以我們要手動(dòng)處理,在上面的例子中,我們使用結(jié)巴分詞,并
使用某大學(xué)的停詞詞庫(kù)進(jìn)行過(guò)濾單詞。 words = jieba.cut(lines, cut_all=True)
這句話的意思是把一個(gè)單詞分解成它所有可能組合的形式,比如中華人民共和國(guó)會(huì)分解成
中華,中華人民,和中國(guó)人民共和國(guó)。
cache = dict(data = train_data, target=target,target_name=target_name)
這行代碼我其實(shí)也不是很明白,python 的數(shù)據(jù)結(jié)構(gòu)然后這么的隨意,dict 的 key 可以是一個(gè)
不存在的變量而不需要加上引號(hào)?
關(guān)于 CountVectorizer,我一直以為它是 BOW 類似的實(shí)現(xiàn),但是看到下面這個(gè)例子后才發(fā)現(xiàn)
并不是
texts=["dog cat fish","dog cat cat","fish bird", "bird"] cv = CountVectorizer() cv_fit=cv.fit_transform(texts) print(cv.get_feature_names()) print(cv_fit.toarray()) #["bird", "cat", "dog", "fish"] #[[0 1 1 1] # [0 2 1 0] # [1 0 0 1] # [1 0 0 0]] print(cv_fit.toarray().sum(axis=0)) #[2 3 2 2]
只是簡(jiǎn)單的詞頻相加,看來(lái) sklearn 還是適合用一些簡(jiǎn)單的算法,深度學(xué)習(xí)相關(guān)的東西還是交給
tensorflow 等框架。但是一般并不是不好,sklearn 對(duì)大部分場(chǎng)景已經(jīng)很好了,并且它超級(jí)
快,在筆記本上就能訓(xùn)練出一個(gè)模型。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/40932.html
摘要:幾乎所有大型電子郵箱服務(wù)提供商都內(nèi)置了垃圾郵件檢測(cè)系統(tǒng),能夠自動(dòng)將此類郵件分類為垃圾郵件。大多數(shù)機(jī)器學(xué)習(xí)算法都要求傳入的輸入是數(shù)字?jǐn)?shù)據(jù),而電子郵件信息通常都是文本。 我們的任務(wù) 垃圾郵件檢測(cè)是機(jī)器學(xué)習(xí)在現(xiàn)今互聯(lián)網(wǎng)領(lǐng)域的主要應(yīng)用之一。幾乎所有大型電子郵箱服務(wù)提供商都內(nèi)置了垃圾郵件檢測(cè)系統(tǒng),能夠自動(dòng)將此類郵件分類為垃圾郵件。 在此項(xiàng)目中,我們將使用樸素貝葉斯算法創(chuàng)建一個(gè)模型,該模型會(huì)通過(guò)...
摘要:將不同的評(píng)分按分類放好分詞分詞是通過(guò)第三方的實(shí)現(xiàn)的。這對(duì)于計(jì)算相似度還是用作后續(xù)的分類器訓(xùn)練后續(xù)有時(shí)間的話會(huì)實(shí)現(xiàn)基于的分類器都是十分有幫助的。 Chinese-sentiment-analysis-with-Doc2Vec 簡(jiǎn)介 中文語(yǔ)料的情感分析基本步驟如下: 爬取相關(guān)的語(yǔ)料或者下載相關(guān)語(yǔ)料(本文使用了對(duì)于賓館評(píng)價(jià)的相關(guān)語(yǔ)料作為例子) 將語(yǔ)料進(jìn)行預(yù)處理并分詞 用某種量化的表達(dá)形式來(lái)...
摘要:貢獻(xiàn)者飛龍版本最近總是有人問(wèn)我,把這些資料看完一遍要用多長(zhǎng)時(shí)間,如果你一本書一本書看的話,的確要用很長(zhǎng)時(shí)間。為了方便大家,我就把每本書的章節(jié)拆開(kāi),再按照知識(shí)點(diǎn)合并,手動(dòng)整理了這個(gè)知識(shí)樹(shù)。 Special Sponsors showImg(https://segmentfault.com/img/remote/1460000018907426?w=1760&h=200); 貢獻(xiàn)者:飛龍版...
摘要:寫在前面在此總結(jié)一些在數(shù)據(jù)分析挖掘中可能用到的功能,方便大家索引或者從一種語(yǔ)言遷移到另一種。概率圖模型文本基本操作類別英中中文分詞未知主題模型類別未知未知未知值得留意的是的新第三方模塊,與其他分析可視化挖掘報(bào)表工具的交互類別實(shí)際是的服務(wù)包 寫在前面 在此總結(jié)一些在數(shù)據(jù)分析/挖掘中可能用到的功能,方便大家索引或者從一種語(yǔ)言遷移到另一種。當(dāng)然,這篇博客還會(huì)隨時(shí)更新(不會(huì)另起一篇,為了方便大...
閱讀 2337·2021-11-16 11:52
閱讀 2323·2021-11-11 16:55
閱讀 750·2021-09-02 15:41
閱讀 2981·2019-08-30 15:54
閱讀 3142·2019-08-30 15:54
閱讀 2251·2019-08-29 15:39
閱讀 1507·2019-08-29 15:18
閱讀 968·2019-08-29 13:00