1. 程式人生 > >CNN-中文文字分類-開源專案-自定義資料集

CNN-中文文字分類-開源專案-自定義資料集

最近參加學校的一個數據分析比賽,因為自己前面自學了一些基本的機器學習演算法,但其實還處於入門階段,便參加了。選擇了一道中文文字分類的題目。

今日頭條使用者畫像
選題背景:
隨著機器創作能力越來越強,今後社會媒體上將會產生越來越多的機器創作者自動生產的內容。有效識別出哪些是人類作者生產的內容,哪些是機器作者生產的內容(包括機器寫作、機器翻譯、機器自動摘要),對於媒體內容的稽核、分發、推薦等,具有十分重要的意義。
題目概況
給定一個由今日頭條提供的媒體內容文件構成的資料集,參賽隊伍採用適當的演算法,對每篇文件的作者進行身份識別,區分出該文件屬於人類寫作、機器寫作、機器翻譯和機器自動摘要中的哪一類。
需求描述
分析完成後,應提交分析報告。
提交分類模型原始碼。
資料集


訓練集共包含97,512篇文件,檔名為t.txt,,每一行代表一篇文件,包含三個欄位,依次為文件標籤、文件內容和文件ID,Unicode編碼,JSON格式,如下所示:
{"\u6807\u7b7e":"\u81ea\u52a8\u6458\u8981","\u5185\u5bb9":"\u5206\u6790\u4e2d\u56fd\u7ecf\u6d4e\uff0c\u8981\u770b\u8fd9\u8258\u5927\u8239\u65b9\u5411\u662f\u5426\u6b63\u786e\uff0c\u52a8\u529b\u662f\u5426\u5f3a\u52b2\uff0c\u6f5c\u529b\u662f\u5426\u5145\u6c9b\u3002\u53ea\u8981\u6295\u8d44\u8005\u5168\u9762\u4e86\u89e3\u4e2d\u56fd\u6539\u9769\u5f00\u653e\u4ee5\u6765\u7684\u7ecf\u6d4e\u53d1\u5c55\u5386\u7a0b\u3001\u8fd1\u671f\u4e2d\u56fd\u4e3a\u4fc3\u8fdb\u7ecf\u6d4e\u6301\u7eed\u7a33\u5b9a\u589e\u957f\u5236\u5b9a\u7684\u6218\u7565\u4ee5\u53ca\u4e2d\u56fd\u7ecf\u6d4e\u5404\u9879\u6570\u636e\u548c\u8d8b\u52bf\uff0c\u5c31\u4f1a\u4f5c\u51fa\u6b63\u786e\u5224\u65ad\u3002",“id”:0}
該資料打印出來為:
{‘標籤’: ‘自動摘要’, ‘內容’: ‘分析中國經濟,要看這艘大船方向是否正確,動力是否強勁,潛力是否充沛。只要投資者全面瞭解中國改革開放以來的經濟發展歷程、近期中國為促進經濟持續穩定增長制定的戰略以及中國經濟各項資料和趨勢,就會作出正確判斷。’, ‘id’: 0}

因為資料集有點大,達到97512個樣本,於是決定用深度學習框架跑結果,在Github上找到了一個開源的text-classification-cnn-rnn,按照它的官方demo例項跑是沒有任何問題的,大家也可以試下它的程式碼。直接下載它給的訓練子集,密碼是:qfud
但是怎麼才能把自己的自定義資料執行上去呢,於是博主到處Google、百度,結果發現只有這一篇

可以參考,問題是。。。。他連官方Demo跑出來都報錯了啊。。。所以。。博主在參考了他的部落格以及官方的文件後,重寫一篇指引檔案,方便後面的人查閱。也以免誤導他人學習。ORZ(當然,,也可能是當時他的時間是2018年7月16日,所以大家在看部落格的時候,也一定要注意博主發帖的時間

,畢竟程式碼是不斷更改的)
博主配置:

  • Windows 10教育版 64位作業系統
  • Python 3.6.6
  • tensorflow-gpu 1.11.0
  • numpy 1.14.5
  • scikit-learn 0.19.1
  • scipy 1.1.0

博主這裡就不重複官方的教程跑demo了,具體的大家可以去看官方講解。這裡主要講解下博主此次比賽如何使用自己的資料集在這個模型上的使用方法。首先資料集是一個
整個資料集的文字
這個檔案十分大。所以不能用常規方法點選開啟,因此博主使用Python程式碼,一行行的列印句子。發現就像比賽題目概況一樣,全是Unicode編碼,最開始博主嘗試改成UTF-8格式,發現不能成功。後來才知道有json庫,可以直接幫助轉碼。。。下面是關於如何去處理這個資料集的程式碼:

import os, json

labels = ["自動摘要","機器作者","人類作者","機器翻譯"]#建立的資料夾名,可以自定義自己的文字類別
for i in range(len(labels)):
	path = "./"
	path = path + labels[i]
	os.mkdir(path)

#讀取每一個訓練集,將其放進對應資料夾內
f_obj = open('t.txt')
count = 0
while 1:
	cur_example = f_obj.readline()
	if cur_example == "":
		break
	cur_example = json.loads(cur_example)

	label = cur_example['標籤']
	content = cur_example['內容']
	exaID = cur_example['id']

	fileName = label + "-" + str(exaID) + ".txt"
	path = "./" + label + "/"
	os.chdir(path)

	with open(fileName, 'w',encoding='utf-8') as tmp_obj:
		tmp_obj.write(content)
		tmp_obj.close()

	os.chdir("../")
	count += 1
	print(count)
	
f_obj.close()

程式碼的作用是將整個檔案讀取,並將每個不同的分類放在不同的資料夾內,這樣方便後面模型的使用。(如果你們要用在自己的中文文字分類任務裡,需要自己去調整建立的資料夾類別以及資料夾的命名,建議檔名是以類別+id來區分某一類資料夾裡的檔案)。
總之,你必須先將不同類別的檔案放在不同的資料夾下面,這樣方便後面的資料預處理。
分好類後,可以參考該圖示四個資料夾
每個資料夾下有不同的文字,即你的各個訓練集
建立一個dddData資料夾,並將這四個資料夾放入dddData內,並把整個dddData資料夾放進你在Github上下載的資料夾內
(即你所分好類的資料集放入你所下載的資料夾內)
進入helper資料夾內修改cnews_group.py檔案。
修改部分原始碼即可:(關於***.train.txt、***.test.txt、***.val.txt檔案的命名,你可以自定義你想命名的,如果你改為了自己想要的檔名,請保證後面更改的程式碼也要跟著改進)

   # f_train = open('data/cnews/cnews.train.txt', 'w', encoding='utf-8')
   # f_test = open('data/cnews/cnews.test.txt', 'w', encoding='utf-8')
   # f_val = open('data/cnews/cnews.val.txt', 'w', encoding='utf-8')
   f_train = open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.train.txt', 'w', encoding='utf-8')
   f_test = open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.test.txt', 'w', encoding='utf-8')
   f_val = open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.val.txt', 'w', encoding='utf-8')

關於count大於、小於的數值,建議你統計一下你的資料集的樣本總數,然後第一個引數小於你總數的60%來取值,第二個引數按80%來取值。

            if count < 14626:
                f_train.write(category + '\t' + content + '\n')
            elif count < 19502:
                f_test.write(category + '\t' + content + '\n')
            else:
                f_val.write(category + '\t' + content + '\n')

如果你前面檔案的命名格式沒有更改,那麼可以直接複製這個程式碼。可能路徑不同,需要你去更改下。

if __name__ == '__main__':
    # save_file('data/thucnews')
    # print(len(open('data/cnews/cnews.train.txt', 'r', encoding='utf-8').readlines()))
    # print(len(open('data/cnews/cnews.test.txt', 'r', encoding='utf-8').readlines()))
    # print(len(open('data/cnews/cnews.val.txt', 'r', encoding='utf-8').readlines()))
    save_file('C:/Users/Syler/Desktop/text-classification-cnn-rnn/dddData')
    print(len(open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.train.txt', 'r', encoding='utf-8').readlines()))
    print(len(open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.test.txt', 'r', encoding='utf-8').readlines()))
    print(len(open('C:/Users/Syler/Desktop/text-classification-cnn-rnn/data/cnews/diyData.val.txt', 'r', encoding='utf-8').readlines()))

當你改完這三處程式碼後,你就可以執行下這段程式碼,如果不出問題的話,那麼此時你的data資料夾裡的cnews資料夾內會多出三個檔案。即diyData.test.txt、diyData.trian.txt、diyData.val.txt。這時候別慌。。。不要聽上個博主說的什麼缺乏停用詞。。根本不存在停用詞的問題!!
進入data資料夾內,有一個cnews_loader.py的檔案,進行修改。將你要分的類,進行補充或更改。

def read_category():
    """讀取分類目錄,固定"""
    categories = ['機器翻譯', '機器作者', '人類作者', '自動摘要']

這裡需要進行CNN模型的調整引數。博主的水平暫時沒有那麼高,所以使用的是預設引數,如果有大佬知道怎麼調超參可以更優的話,無視博主。這裡因為博主只需要分4類,於是把num_classes的值修改為4即可。

class TCNNConfig(object):
    """CNN配置引數"""

    embedding_dim = 64  # 詞向量維度
    seq_length = 600  # 序列長度
    num_classes = 4  # 類別數
    num_filters = 128  # 卷積核數目
    kernel_size = 5  # 卷積核尺寸
    vocab_size = 5000  # 詞彙表達小

    hidden_dim = 128  # 全連線層神經元

    dropout_keep_prob = 0.5  # dropout保留比例
    learning_rate = 1e-3  # 學習率

    batch_size = 64  # 每批訓練大小
    num_epochs = 10  # 總迭代輪次

    print_per_batch = 100  # 每多少輪輸出一次結果
    save_per_batch = 10  # 每多少輪存入tensorboard

最後修改run_cnn.py函式,將檔案的命名改為前面生成的檔名。這裡說下關於diyData.val.txt這個檔案,這個檔案是在你執行run_cnn.py的時候才會生成這個檔案,所以沒有的話,是不用擔心的。

# train_dir = os.path.join(base_dir, 'cnews.train.txt')
# test_dir = os.path.join(base_dir, 'cnews.test.txt')
# val_dir = os.path.join(base_dir, 'cnews.val.txt')
# vocab_dir = os.path.join(base_dir, 'cnews.vocab.txt')
train_dir = os.path.join(base_dir, 'diyData.train.txt')
test_dir = os.path.join(base_dir, 'diyData.test.txt')
val_dir = os.path.join(base_dir, 'diyData.val.txt')
vocab_dir = os.path.join(base_dir, 'diyData.vocab.txt')

對了,有一個地方需要注意,關於模型的使用,有個地方可能會報錯,大家需要額外注意,就是windows下的反斜槓和linux下的斜槓是不相容的,因此可以使用這個程式碼進行修改。這裡我修改的是predict.py檔案中的一個地方。還有個檔案也是需要修改的,如果是地址不對的錯誤,大家按照同樣的方法便可以修復了。

# vocab_dir = os.path.join(base_dir, 'cnews.vocab.txt')
vocab_dir = os.path.join(base_dir, 'diyData.vocab.txt').replace('\\', '/')

最後,整個模型就可以使用了。只要前面沒報錯的話,就可以去命令列輸入

python run_cnn.py train

進行訓練。
再使用

python run_cnn.py test

進行測試訓練集。
如果想使用在自定義的中文文字上執行,那麼可以可以看下這個檔案,稍微修改下便可以使用了。