樸素貝葉斯實現文件分類

ckxllf發表於2019-10-07

  本文為重點記錄在實現作業過程中遇到的問題和解決方法。

  作業要求:

  實驗資料在bayes_datasets資料夾中。其中,

   train為訓練資料集,包含hotel和travel兩個中文文字集,文字為txt格式。hotel文字集中全部都是介紹酒店資訊的文件,travel文字集中全部都是介紹景點資訊的文件;

   Bayes_datasets/test為測試資料集,包含若干hotel類文件和travel類文件。

  用樸素貝葉斯演算法對上述兩類文件進行分類。要求輸出測試資料集的文件分類結果,即每類文件的數量。

  (例:hotel:XX,travel:XX)

  貝葉斯公式:

  樸素貝葉斯演算法的核心,貝葉斯公式如下:

  

貝葉斯公式

  程式碼實現:

  第一部分:讀取資料

  f_path = os.path.abspath('.')+'/bayes_datasets/train/hotel'

  f1_path = os.path.abspath('.')+'/bayes_datasets/train/travel'

  f2_path = os.path.abspath('.')+'/bayes_datasets/test'

  ls = os.listdir(f_path)

  ls1 = os.listdir(f1_path)

  ls2 = os.listdir(f2_path)

  #去掉網址的正規表示式

  pattern = r"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*,]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)|([a-zA-Z]+.\w+\.+[a-zA-Z0-9\/_]+)"

  res = []

  for i in ls:

  with open(str(f_path+'\\'+i),encoding='UTF-8') as f:

  lines = f.readlines()

  tmp = ''.join(str(i.replace('\n','')) for i in lines)

  tmp = re.sub(pattern,'',tmp)

  remove_digits = str.maketrans('', '', digits)

  tmp = tmp.translate(remove_digits)

  # print(tmp)

  res.append(tmp)

  print("hotel總計:",len(res))

  for i in ls1:

  with open(str(f1_path + '\\' + i), encoding='UTF-8') as f:

  lines = f.readlines()

  tmp = ''.join(str(i.replace('\n', '')) for i in lines)

  tmp = re.sub(pattern, '', tmp)

  remove_digits = str.maketrans('', '', digits)

  tmp = tmp.translate(remove_digits)

  # print(tmp)

  res.append(tmp)

  print("travel總計:",len(res)-308)

  #print(ls2)

  for i in ls2:

  with open(str(f2_path + '\\' + i), encoding='UTF-8') as f:

  lines = f.readlines()

  tmp = ''.join(str(i.replace('\n', '')) for i in lines)

  tmp = re.sub(pattern, '', tmp)

  remove_digits = str.maketrans('', '', digits)

  tmp = tmp.translate(remove_digits)

  # print(tmp)

  res.append(tmp)

  print("test總計:",len(res)-616)

  print("資料總計:",len(res))

  這一部分的任務是將放在各個資料夾下的txt文件讀入程式,並將資料按照需要的形式存放。資料分為訓練集和測試集,而訓練集又包括景點和酒店兩類,故資料總共分為三類,分三次分別讀取。在訓練集的每一個txt檔案中最前端都有一串網址資訊,我用正規表示式將其過濾掉,後來發現此部分並不會影響最終的結果。之後將三類文件依次讀取,將讀取的結果存放入一個結果list中。list的每一項為一個字串,存放的是一個txt檔案的去除掉要過濾的資料之後的全部資訊。最終得到travel資料夾下共有308個文件,hotel資料夾下也有308個文件,測試集共有22個文件。

  第二部分:分詞,去除停用詞

  stop_word = {}.fromkeys([',','。','!','這','我','非常','是','、',':',';'])

  print("中文分詞後結果:")

  corpus = []

  for a in res:

  seg_list = jieba.cut(a.strip(),cut_all=False)#精確模式

  final = ''

  for seg in seg_list:

  if seg not in stop_word:#非停用詞,保留

  final += seg

  seg_list = jieba.cut(final,cut_all=False)

  output = ' '.join(list(seg_list))

  # print(output)

  corpus.append(output)

  # print('len:',len(corpus))

  # print(corpus)#分詞結果

  這一部分要做的是設定停用詞集,即分詞過程中過濾掉的無效詞彙,將每一個txt檔案中的資料進行中文分詞。首先stop_word存放了停用詞集,使用第三方庫jieba進行中文分詞,將去除停用詞後的結果最後放入corpus中。

  第三部分:計算詞頻

  #將文字中的詞語轉換為詞頻矩陣

  vectorizer = CountVectorizer()

  #計算各詞語出現的次數

  X = vectorizer.fit_transform(corpus)

  #獲取詞袋中所有文字關鍵詞

  word = vectorizer.get_feature_names()

  #檢視詞頻結果

  #print(len(word))

  for w in word:

  print(w,end=" ")

  print(" ")

  #print("詞頻矩陣:")

  X = X.toarray()

  #print("矩陣len:",len(X))

  #np.set_printoptions(threshold=np.inf)

  #print(X) 無錫人流多少錢 http://www.bhnnk120.com/

  這一部分的任務是將文字中的詞語轉換為詞頻矩陣,並且計算各詞語出現的次數。詞頻矩陣是將文件集合轉換為矩陣,每個文件都是一行,每個單詞(標記)是列,相應的(行,列)值是該文件中每個單詞或標記的出現頻率。

  但我們需要注意的是,本次作業的詞頻矩陣的大小太大,我曾嘗試輸出整個詞頻矩陣,直接導致了程式卡頓,我也嘗試了輸出矩陣的第一項,也有近20000個元素,所以如果不是必需,可以不輸出詞頻矩陣。

  第四部分:資料分析

  # 使用616個txt資料夾內容進行預測

  print ("資料分析:")

  x_train = X[:616]

  x_test = X[616:]

  #print("x_train:",len(x_train))

  #print("x_test:",len(x_test))

  y_train = []

  # 1表示好評0表示差評

  for i in range(0,616):

  if i < 308:

  y_train.append(1)#1表示旅店

  else:

  y_train.append(0)#0表示景點

  #print(y_train)

  #print(len(y_train))

  y_test= [0,0,0,1,1,1,0,0,1,0,1,0,0,1,0,0,1,1,1,0,1,1]

  # 呼叫MultionmialNB分類器

  clf = MultinomialNB().fit(x_train,y_train)

  pre = clf.predict(x_test)

  print("預測結果:",pre)

  print("真實結果:",y_test)

  print(classification_report(y_test,pre))

  hotel = 0

  travel = 0

  for i in pre:

  if i == 0:

  travel += 1

  else:

  hotel += 1

  print("Travel:",travel)

  print("Hotel:",hotel)

  這部分的任務是將所有的訓練資料根據其標籤內容進行訓練,然後根據訓練得到的結果對測試資料進行預測分類。x_train代表所有的訓練資料,共有616組;其對應的標籤為y_train,也有616組,值為1代表酒店,值為0代表景點。x_test代表所有的測試資料,共有22組;其對應標籤為y_test,亦22組,其值則由我自己事先根據其值手工寫在程式中。此時需要注意的是測試集檔案在程式中的讀取順序可能與資料夾目錄中的順序不一致。最後將測試集資料使用訓練集資料呼叫MultionmialNB分類器得到的模型進行預測,並將預測結果與真實結果進行對比。

  得出執行結果。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2658956/,如需轉載,請註明出處,否則將追究法律責任。

相關文章