新闻分类实战-贝叶斯
由于看了多篇文章還是對處理流程迷迷糊糊,所以自己重新整理了分類流程:
參考博客
一.新聞文本進行分類預測。流程如下:
二.代碼部分:
1. 文本分詞
就是將獲取到的新聞數據,轉化成有一個個詞語組成的樣式。新聞的數據是由搜狗實驗室提供,可以根據鏈接進行獲取,這里使用的數據是已經經過清洗后的數據,直接進行加載(關于文章中使用的數據,包括處理后的新聞數據和停用詞數據,已經上傳至資源,可以自行下載)
1.1 數據加載
import pandas as pd import jieba #既然涉及到分詞,最常用,也是最成熟的一個包就是jieba了 #pip install jiebadf_news = pd.read_table('./data/val.txt',names=['category','theme','URL','content'],encoding='utf-8') df_news = df_news.dropna()#默認刪除any帶nan的數據行 df_news.head()#默認讀取前5行
輸出的結果為:(Category:當前新聞所屬的類別,一會我們要進行分別任務,這就是標簽了。Theme:新聞的主題,這個咱們先暫時不用,大家在練習的時候也可以把它當作特征。URL:爬取的界面的鏈接,方便檢驗爬取數據是不是完整的,這個咱們暫時也不需要。Content:新聞的內容,這些就是一篇文章了,里面的內容還是很豐富的。)
1.2分詞:使用結吧分詞器
next:根據文章的內容來進行類別的劃分,先把文章進行分詞,把它轉換成向量。
#df_news的content列中,用.values拿到該列值,.tolist代表轉換成list格式。 content = df_news.content.values.tolist()#將每一篇文章轉換成一個lis print (content[4999])#選擇最后一篇文章看看[out]全球最美女人合成圖::國整形外科教授李承哲,在國際學術雜志美容整形外科學會學報發表了考慮種族和民族臉型多樣性的黑人、白人、中國人、日本人女性“最具魅力的臉型”的論文。李承哲合成這些臉型時采用的演藝人臉型有,黑人13名、白人16名、中國人20名、日本人14名等共63名的臉型。M賈兇宰笙蠐乙來撾:黑人美女、白人美女、中國美女、日本美女和韓國美女。
1.3 jieba分詞基本步驟
使用jieba分詞篩選結果的五步驟:
- 在遍歷數據之前創建一個空列表,用于存放數據,
- 然后在依次遍歷存放新聞數據的列表,獲取每一篇新聞數據,
- 使用jieba.lcut()方法對文本進行分詞,
- 接著就是剔除掉字符個數小于等于1個的詞語,還有順帶去掉換行符(也可以按照自己的格式要求進行剔除)
- 最后就是將滿足的結果添加到最初創建的空列表中
因為分詞后的內容是列表,可以直接使用字典套列表的形式創建DataFrame,而字典的鍵就是分詞的結果的列名
創建的DataFrame數據可以用于繪制詞云圖,從分詞后的結果可以看出,雖然剔除了部分數據,但是還是有很多不是我們想看到的內容,比如冒號空格,句號空格等。因此繪制詞云圖之前需要先剔除一些常見的不是很重要的詞語,前面的是初加工篩選,這里就要精加工篩選了,為了避免一個個手動剔除常見的一些不重要的詞匯,所以就有了停用詞字典這個概念,凡是分詞結果后的詞語在這個停用詞范圍中的,都將被舍棄
1.4加載停用詞字典數據進行數據清洗
#不設置quoting,默認會去除英文雙引號,只留下英文雙引號內的內容,設置quoting = 3,會如實讀取內容。 stopwords=pd.read_csv("stopwords.txt",index_col=False,sep="\t",quoting=3,names=['stopword'], encoding='utf-8')#index_col=False——重新設置一列成為index值 stopwords.head(20) #為了方便日后的使用,這里直接封裝函數,只需要傳入相對應格式的數據即可 def drop_stopwords(contents,stopwords):contents_clean = []#存放所有文章all_words = []#存放所有文章的詞組for line in contents:line_clean = []#存放單篇文章的詞組for word in line:if word in stopwords:continueline_clean.append(word)all_words.append(str(word))contents_clean.append(line_clean)return contents_clean,all_words#print (contents_clean)contents = df_content.content_S.values.tolist()#.values.tolist()--pandas DataFrame數據轉為list stopwords = stopwords.stopword.values.tolist() contents_clean,all_words = drop_stopwords(contents,stopwords)#df_content.content_S.isin(stopwords.stopword) #df_content=df_content[~df_content.content_S.isin(stopwords.stopword)] #df_content.head() #將處理后的結果轉化為DataFrame數據 df_content=pd.DataFrame({'contents_clean':contents_clean}) df_content.tail() df_all_words=pd.DataFrame({'all_words':all_words})#all_words將所有分詞的結果以單個數據的形式都保存起來了 df_all_words.tail() import numpy words_count=df_all_words.groupby(by=['all_words'])['all_words'].agg([('counts','count')]) #words_count=df_all_words.groupby(by=['all_words'])['all_words'].agg({"count":numpy.size}) #pandas引入了agg函數,它提供基于列的聚合操作。而groupby可以看做是基于行,或者說index的聚合操作 #通過這里介紹我們可以交接 groupby函數是基于行操作的 而agg是基于列操作的 words_count=words_count.reset_index().sort_values(by=["counts"],ascending=False)#對索引進行排序 words_count.head()1.5詞云圖繪制
那么接下來就可以使用數據繪制詞云圖,既可以選擇按照每篇新聞分詞的數據,也可以使用全部詞語的數據,下面就使用所有詞語的數據進行繪制,基本步驟就是四步:
- 首先截取要呈現的目標數據(一般20,50或者100,根據需要選定)
- 詞云圖對象初始化(這里可以對詞云圖的參數進行設置)
- 將選取的數據傳入到fit.words()方法中
- 最后就是將詞云圖展示出來
1.6 提取關鍵詞
import jieba.analyse#工具包 index = 2400#根據索引值隨便找一篇文章就行 print (df_news['content'][index]) content_S_str = "".join(content_S[index]) #把分詞的結果組合在一起,形成一個句子 print (" ".join(jieba.analyse.extract_tags(content_S_str, topK=5, withWeight=False)))#選出來5個核心詞[out]法國VS西班牙、里貝里VS哈維,北京時間6月24日凌晨一場的大戰舉世矚目,而這場勝利不僅僅關乎兩支頂級強隊的命運,同時也是他們背后的球衣贊助商耐克和阿迪達斯之間的一次角逐。T諶胙”窘炫分薇的16支球隊之中,阿迪達斯和耐克的勢力范圍也是幾乎旗鼓相當:其中有5家球衣由耐克提供,而阿迪達斯則贊助了6家,此外茵寶有3家,而剩下的兩家則由彪馬贊助。而當比賽進行到現在,率先挺進四強的兩支球隊分別被耐克支持的葡萄牙和阿迪達斯支持的德國占據,而由于最后一場1…
耐克 阿迪達斯 歐洲杯 球衣 西班牙
1.7 詞袋模型LDA
由上面的分類看出,通過jieba可以直接提取文本的特征,但是要進行文本的分類,對于計算機來講的話,它并不認識這些漢字,它只認識數值,有沒有可能性將漢字都轉化為數字,用數字進行表示呢?那么詞袋模型就可以解決這個問題
from gensim import corpora, models, similarities import gensim #http://radimrehurek.com/gensim/#做映射,相當于詞袋 dictionary = corpora.Dictionary(contents_clean) ##輸出:[(詞ID,詞頻)..],對該文本進行詞袋格式的轉換,查找詞典在文檔出現的詞和次數進行輸出 corpus = [dictionary.doc2bow(sentence) for sentence in contents_clean]# 在 DT 矩陣上運行和訓練 LDA 模型 #指定主題數為20 lda = gensim.models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20) #類似Kmeans自己指定K值#一號分類結果 # .print_topic(1, topn=5) 獲取單個主題及主題下的單詞 topn為顯示的單詞數 print (lda.print_topic(1, topn=5))##第一類主題,顯示頻率最高的5個Doc2Bow是Gensim中封裝的一個方法,主要用于實現Bow模型,下面主要介紹下Bow模型。
1、BoW模型原理
Bag-of-words model (BoW model) 最早出現在自然語言處理(Natural Language Processing)和信息檢索(Information Retrieval)領域.。該模型忽略掉文本的語法和語序等要素,將其僅僅看作是若干個詞匯的集合,文檔中每個單詞的出現都是獨立的。BoW使用一組無序的單詞(words)來表達一段文字或一個文檔.。近年來,BoW模型被廣泛應用于計算機視覺中。
基于文本的BoW模型的一個簡單例子如下:
首先給出兩個簡單的文本文檔如下:
1
2
基于上述兩個文檔中出現的單詞,構建如下一個詞典 (dictionary):
{“John”: 1, “likes”: 2,“to”: 3, “watch”: 4, “movies”: 5,“also”: 6, “football”: 7, “games”: 8,“Mary”: 9, “too”: 10}
1
上面的詞典中包含10個單詞, 每個單詞有唯一的索引, 那么每個文本我們可以使用一個10維的向量來表示。如下:
1
2
該向量與原來文本中單詞出現的順序沒有關系,而是詞典中每個單詞在文本中出現的頻率。
也是通過余弦定理計算兩個句子的相似度。
既然是進行文本分類,首先要做的就是進行標簽制作,這里就按照常見的是個新聞標簽進行對應新聞的匹配
標簽處理好了之后就是進行數據特征的處理,那么就有個問題,每篇的新聞的字數是不一樣的,有的是200詞,有的是300詞,有的甚至更多,但是在機器學習中要求輸入的數據的維度是統一的,因此就得把數據的維度化為統一,那么就需要找一個可以進行衡量的支點,而這個支點就是語料庫,即使每篇文章的數據的長短不一樣,但是由所有文章組成的語料庫的容量是一定了,所以判斷每篇文章中數據是否在語料庫中既可以對應上,也就轉化為同一維度了,為了方便理解還是進行舉例說明
1.8使用CountVectorizer轉換成向量形式
from sklearn.feature_extraction.text import CountVectorizer #lowercase=True 將所有字符變成小寫 vec = CountVectorizer(analyzer='word', max_features=4000, lowercase = False) vec.fit(words)2.貝葉斯分類器進行分類
#用于多項式模型的樸素貝葉斯分類器 from sklearn.naive_bayes import MultinomialNB classifier = MultinomialNB() classifier.fit(vec.transform(words), y_train)#transform(raw_documents ) #將文檔轉換為文檔術語矩陣,使用符合fit的詞匯表或提供給構造函數的詞匯表,從原始文本文檔中提取令牌計數。 #返回為:文檔術語矩陣#測試集數據處理 test_words = [] for line_index in range(len(x_test)):try:#x_train[line_index][word_index] = str(x_train[line_index][word_index])test_words.append(' '.join(x_test[line_index]))except:print (line_index,word_index) test_words[0] #分類結果準確率#返回給定測試數據和標簽的平均準確度 classifier.score(vec.transform(test_words), y_test)3.使用tdidf矢量器轉換成向量形式
解釋一下TF-IDF是一個什么東西,還是進行舉例子,假設一篇文章為《中國的蜜蜂養殖》當我進行詞頻統計的時候,發現這篇文章中,‘中國’,‘蜜蜂’,‘養殖’這三個詞出現的次數(TF就代表這出現的詞頻)是一樣的,比如都是10次,那這個時候如果判斷其重要性呢?這一篇文章應該講述的是都跟蜜蜂和養殖相關的技術,所以這倆詞應當是重點了。而中國這個詞,我們既可以說中國的蜜蜂,還可以說中國的籃球,中國的大熊貓,能派上用場的地方簡直太多了,沒有那么專一,所以在這篇文章中它應當不是那么重要的。 這里我們就可以給出一個合理的定義了,如果一個詞在整個語料庫中(可以當作是在所有文章中)出現的次數都很高(這篇也有它,另一片還有這個詞),那么這個詞的重要程度就不高,因為它更像一個通用詞。如果另一個詞在整體的語料庫中的詞頻很低,但是在這一篇文章中的詞頻卻很高(這個就是IDF逆文本頻率),我們就有理由認為它在這篇文章中就很重要了。比如蜜蜂這個詞,在籃球,大熊貓相關的文章中基本不可能出現,這里卻大量出現了。因此就可以使用TF-IDF進行文本關鍵詞的提取
#使用tdidf矢量器 #TfidfVectorizer:多個詞組可以不同組合,詞庫數量變多 from sklearn.feature_extraction.text import TfidfVectorizer #analyzer='word'定義特征為詞(word)或n-gram字符,如果傳遞給它的調用被用于抽取未處理輸入源文件的特征序列 vectorizer = TfidfVectorizer(analyzer='word', max_features=4000, lowercase = False) vectorizer.fit(words)from sklearn.naive_bayes import MultinomialNB classifier = MultinomialNB() classifier.fit(vectorizer.transform(words), y_train)classifier.score(vectorizer.transform(test_words), y_test)總結
以上是生活随笔為你收集整理的新闻分类实战-贝叶斯的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 南京 学计算机的学校,南京小学生暑假学计
- 下一篇: 华为机试 (10/6)