sklearn中的分詞函數countVectorizer()的改動--保留長度為1的字符串


1簡述問題

使用countVectorizer()將文本向量化時發現,文本中長度唯一的字符串會被自動過濾掉,這對於我在做的情感分析來講,一些表較重要的表達情感傾向的詞匯被過濾掉,比如文本'沒用的東西,可把我可把我坑的不輕,越用越覺得這個手機真的廢'。

用結巴分詞的精確模式分詞,然后我用空格連接這些分詞得到的句子是:

'沒用 的 東西 , 可 把 我 可 把 我 坑 的 不輕 , 越用 越 覺得 這個 手機 真的 廢'

  代碼如下:

def cut_word(sent):
    line=re.sub(r'[a-zA-Z0-9]*','',sent)
    wordList=jieba.lcut(line)
    #print(wordList)
    return ' '.join(wordList)

vec= CountVectorizer(min_df=1)
c='沒用的東西,可把我可把我坑的不輕,越用越覺得這個手機真的廢'
cut=cut_word(c)

然后用countVectorizer()對這個分好詞的句子進行向量化發現,一個字的詞都被過濾掉了:

['不輕', '東西', '手機', '沒用', '真的','越用']

  代碼如下:

vec.fit_transform([cut])
vec.get_feature_names()

他把最能表達情感傾向的詞“坑”,‘廢’給過濾掉了,這對於向量化后的句子特征就損失了很多的信息。我認為因為這個庫的函數原本就是為了英文分詞的,而英文長度為1 的詞是26個字母,並不會表示什么重要含義,所以在編寫這個函數時自動就給這些長度低於2的單詞給去掉了。但是中文可不一樣,一個字的意義可以有非常重要的含義。對於我們分類不重要的詞,比如一些代詞“你”,‘我’,‘他’等其他經常出現的詞,可以用停用詞表給過濾掉,這個countVectorizer()就自帶了一個組停用詞的參數,stop_words,這個停用詞是個列表包含了要去掉的停用詞,我們可以針對自己需要自定義一個停用詞表。當stop_words=‘english’時,函數會自動為英文文本分詞去除停用詞。中文都是自己自定義。

2解決方法

我是找了源代碼,這個函數在sklearn包的feature_exceration文件夾中text.py。

找到了打開文件,找到了CountVectorizer()的代碼,定位到fit_transform(raw_documents)中關於詞匯表對於原始文本進行處理的地方

看見vocabulary這是包含所有分詞的字典,再定位到_cout_vocab()函數位置,

看見raw_vocabulary了,796行是對特征(分詞)進行計數的放到字典feature_counter中。doc是原始文本的每行文本,這利用analyze()處理,再往回找

analyze = self.build_analyzer(),可再往上找self.build_analyzer()函數,

我們主要找的是對文本進行處理的函數,所以找的就是出現文本,且對文本進行操作的函數。定位到264行,根據countVectorizer()的初始定義self.analyzer的默認值是‘word’,所以

self.build_analyzer()函數默認情況下是跳到這里對文本dco進行操作。再看看preprocess()tokenize()

找到self.build_preprocessor()看一下知道是對文本的編碼格式以及大小寫的操作,對文本預處理的函數。

重點到self.bulid_tokenizer(),看名字就是知道是分詞函數了。

這是我該過的,#原句是 return lambda doc: token_pattern.findall(doc),是根據正則表達式token_patten來從文本doc中找到符合正則表達式的所有分詞,可見問題出在這里,再回到原文本countVectorizer()定義的正則表達式。

#原句token_patten=u'(?u)\b\w\w+\b',水平太菜不太看懂這個表達式,反正試了一下,這個表達式真的會過濾掉字符長度為1的字符串,我就改了一下正則表達式。因為待分的文本都是分詞好且用空格連起來的字符串,所以用鄭子表達式空格作為切分文本的標記。

所以總的來說就是改了兩個點

  (1)CountVectorizer中將默認的正則表達式u'(?u)\b\w\w+\b'改為r"\s+:即token_pattern=r"\s+"

  (2)self.build_tokenizer()中fiandall()替換成split(),即return lambda doc: token_pattern.split(doc)

 

3.測試

結合自己定義的停詞表,去掉沒用的詞,再試一下分詞效果:

 原來分詞效果:

['不輕', '東西', '手機', '沒用', '真的','越用']

  更改過后效果:

['不輕', '東西', '坑', '廢', '手機', '沒用', '真的', '越', '越用']

可見,長度為1的重要情感詞,'坑', '廢',得到了保留。

 

 

 
        
 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM