丁香五月天婷婷久久婷婷色综合91|国产传媒自偷自拍|久久影院亚洲精品|国产欧美VA天堂国产美女自慰视屏|免费黄色av网站|婷婷丁香五月激情四射|日韩AV一区二区中文字幕在线观看|亚洲欧美日本性爱|日日噜噜噜夜夜噜噜噜|中文Av日韩一区二区

您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號(hào)安全和更好的產(chǎn)品體驗(yàn),強(qiáng)烈建議使用更快更安全的瀏覽器
此為臨時(shí)鏈接,僅用于文章預(yù)覽,將在時(shí)失效
人工智能開發(fā)者 正文
發(fā)私信給AI研習(xí)社
發(fā)送

0

手把手教你用 TensorFlow 實(shí)現(xiàn)文本分類(上)

本文作者: AI研習(xí)社 2017-05-28 10:20
導(dǎo)語:文本分類全流程解析。

手把手教你用 TensorFlow 實(shí)現(xiàn)文本分類(上)

雷鋒網(wǎng)按:本文作者張慶恒,原文載于作者個(gè)人博客,雷鋒網(wǎng)已獲授權(quán)。

由于需要學(xué)習(xí)語音識(shí)別,期間接觸了深度學(xué)習(xí)的算法。利用空閑時(shí)間,想用神經(jīng)網(wǎng)絡(luò)做一個(gè)文本分類的應(yīng)用, 目的是從頭到尾完成一次機(jī)器學(xué)習(xí)的應(yīng)用,學(xué)習(xí)模型的優(yōu)化方法,同時(shí)學(xué)會(huì)使用主流的深度學(xué)習(xí)框架(這里選擇tensorflow)。

文章分為兩部分,本文僅實(shí)現(xiàn)流程,用簡單的softmax回歸對(duì)文本進(jìn)行分類,后面一篇文章再從流程的各個(gè)方面對(duì)模型進(jìn)行優(yōu)化,達(dá)到比較好的效果。

  收集數(shù)據(jù)

該部分不是這里的重點(diǎn),數(shù)據(jù)從各大新聞網(wǎng)站爬取新聞文本,分十類保存到本地,包括科技、生活、體育、娛樂等。文本分別保存到training_set和testing_set目錄下,如:

$ tree -L 1 training_set/

training_set/

├── 10_hel

├── 1_ent

├── 2_fin

├── 3_spo

├── 4_tec

├── 5_mil

├── 6_soc

├── 7_lif

├── 8_cul

└── 9_car

文本以text_id.txt的格式保存在不同類的目錄下(如text_1234.txt)。本例保存了共113673個(gè)訓(xùn)練文本和等數(shù)量的測(cè)試文本(暫時(shí)按1:1的比例)。

  預(yù)處理文本

step0

為方便后面處理,預(yù)處理文本首先要分別針對(duì)訓(xùn)練文本和測(cè)試文本生成唯一的文本ID, 這里用 {class_id}{text_type}{text_id}.txt 來標(biāo)示唯一文本,class_id為類的id,這里為1-10;text_type為數(shù)據(jù)類型包括train和test;text_id為類文件夾下的文本id,實(shí)現(xiàn)函數(shù):

def get_unique_id(self, data_dir):

        """

            get flie unique id famate as {class_id}_type_{text_id}.txt.

            data_dir is the full path of file

              e.g ./training_set/4_tec/4_tec_text/text_2001.txt

            where "training" is type, "4" is file class, and "2001" is text id.

            modify this function to adapt your data dir fomate

        """


        dir_list = data_dir.split("/")

        class_id = dir_list[2].split("_")[0]

        text_id = dir_list[4].split(".")[0]

        type_id = dir_list[1].split("_")[0]

        return class_id + "_" + type_id + "_" + text_id

step1: 分詞

通俗來講,文本分類的主要思想,是構(gòu)建各類文本的漢語詞典,通過對(duì)文本進(jìn)行分析,觀察文本中哪類詞匯比較多,由此判斷文本所屬類別。因此,文本分類需要對(duì)文本進(jìn)行分詞操作,可以選擇的分詞工具很多,這里選擇Python編寫的jieba開源庫對(duì)文本進(jìn)行分詞,并以行為單位,將文本保存到輸出文件,該部分實(shí)現(xiàn)比較簡單:

def splitwords(self, data_dir, data_type):


        if os.path.exists(data_type+".txt"):

            os.remove(data_type+".txt")


        list_dirs = os.walk(data_dir)

        for root, _, files in list_dirs:

            print root

            # get all files under data_dir

            for fp in files:

                file_path = os.path.join(root, fp)

                file_id = self.get_unique_id(file_path)

                #split words for f, save in file ./data_type.txt

                with nested(open(file_path), open(data_type+".txt", "a+")) as (f1, f2):

                    data = f1.read()

                    #print data

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

                    f2.write(file_id + " " + " ".join(seg_list).replace("\n", " ")+"\n")


        print "split word for %s file end." % data_type

        return

函數(shù)傳入?yún)?shù)為數(shù)據(jù)集目錄路徑,以及數(shù)據(jù)集類型(train or test)。結(jié)果文件保存形如train.txt,后續(xù)的操作在該輸出文件基礎(chǔ)之上。輸出文件格式為:<class_{data_type}_id> < words >

step2: 去除停用詞

這部分主要?jiǎng)h去文本中的停用詞,停用詞包括一些對(duì)于文本分類無用,而且出經(jīng)常出現(xiàn)的詞匯或符號(hào),如“因此”、“關(guān)于”、“嘿嘿”、標(biāo)點(diǎn)符號(hào)等。去除停用詞需根據(jù)停用詞典,去除上面經(jīng)過分詞操作的文本中的停用詞。停用詞典可以根據(jù)自己需要生成或在網(wǎng)絡(luò)上獲得,這里后面源碼鏈接中會(huì)給出使用的停用詞詞典。

def rm_stopwords(self, file_path, word_dict):


        #read stop word dict and save in stop_dict

        stop_dict = {}

        with open(word_dict) as d:

            for word in d:

                stop_dict[word.strip("\n")] = 1


        # remove tmp file if exists

        if os.path.exists(file_path+".tmp"):

            os.remove(file_path+".tmp")


        print "now remove stop words in %s." % file_path

        # read source file and rm stop word for each line.

        with nested(open(file_path), open(file_path+".tmp", "a+"))  as (f1, f2):

            for line in f1:

                tmp_list = [] # save words not in stop dict

                words = line.split()

                for word in words[1:]:

                    if word not in stop_dict:

                        tmp_list.append(word)

                words_without_stop =  " ".join(tmp_list)

                f2.write(words[0] + " " + words_without_stop + "\n")


        # overwrite origin file with file been removed stop words

        shutil.move(file_path+".tmp", file_path)

        print "stop words in %s has been removed." % file_path

        return

代碼中經(jīng)過簡單的按行讀文本,然后搜索停用詞典,如果文本中的詞匯在詞典中,則跳過,否則保存。這里每行對(duì)應(yīng)數(shù)據(jù)集中的一個(gè)文本。

  step3: 生成詞典

上面提到文本分類需要得到能表征各類文本的漢語詞典,這部分的主要思路是實(shí)現(xiàn)tf_idf算法自動(dòng)提取關(guān)鍵詞,根據(jù)詞頻(TF)和逆文檔頻率(IDF)來衡量詞匯在文章中的重要程度。這里詞頻的計(jì)算采用公式:

手把手教你用 TensorFlow 實(shí)現(xiàn)文本分類(上)

由于是衡量某類文本的關(guān)鍵詞,公式中的“文章”為某類所有文本的總和。逆文檔頻率計(jì)算采用公式:

手把手教你用 TensorFlow 實(shí)現(xiàn)文本分類(上)

上面的文檔總數(shù)為train數(shù)據(jù)集所有文本的數(shù)目。tf-idf為兩個(gè)指標(biāo)的乘積,計(jì)算各類文本中所有詞匯的tf-idf,由小到大排序,默認(rèn)取前500個(gè)詞匯作為該類的關(guān)鍵詞保存到詞典。最終生成大小為5000的詞典。簡潔考慮,該部分的關(guān)鍵代碼(gen_dict方法中):

        for k, text_info in class_dict.items():

            #print "class %s has %d words" % (k, text_info.file_num)

            # get tf in words of class k

            for w in text_info.wordmap:

                text_info.tf_idf(w, word_in_files[w], text_num)


            main_words = []

            with open(save_path, "a+") as f:

                main_words = text_info.get_mainwords()

                print "class %s : main words num: %d" % (k, len(main_words))

                f.write("\n".join(main_words) + "\n")

class_dict是類id到該類文本信息(text_info)的字典,text_info.wordmap保存了該類文本的所有不重復(fù)的詞匯,text_info.tf_idf方法計(jì)算該類文本某詞的tf-idf,輸入?yún)?shù)為詞匯,詞匯在整個(gè)語料庫出現(xiàn)的文本數(shù)和語料庫的文本數(shù)。text_info.get_mainwords方法得到該類本前500個(gè)關(guān)鍵詞。完整的定義與實(shí)現(xiàn)參考源碼

step4: 生成詞袋

該部分實(shí)現(xiàn)向量化文本,利用生成的詞典,以行為單位將去停用詞后的文本轉(zhuǎn)換為向量,這里向量為5000維。如果文本出現(xiàn)詞典中的某詞匯,則文本向量對(duì)應(yīng)詞典中該詞匯的位置的計(jì)數(shù)累加。最終生成文件,行數(shù)為文本數(shù),列為5000。此外生成對(duì)應(yīng)的label文件,行數(shù)為文本數(shù),對(duì)應(yīng)于文本向量文件行,列為1,對(duì)應(yīng)某文本的類別(1-10)。該部分代碼比較簡單,實(shí)現(xiàn)在gen_wordbag方法中。

到此完成了文本的預(yù)處理,接下來針對(duì)不同分類算法,將有不同的處理,這里參考tensotflow處理MNIST數(shù)據(jù)集,讀取預(yù)處理后的文本到系統(tǒng),進(jìn)行線性回歸。

  讀取訓(xùn)練數(shù)據(jù)

該部分主要包括兩部分,一是從磁盤讀取向量化后的文本保存到numpy數(shù)組,將數(shù)據(jù)和類別分別存儲(chǔ),數(shù)據(jù)保存為二維(text_line_num, 5000)的數(shù)組,text_line_num為數(shù)據(jù)集的文本數(shù),5000為詞典的維度,也是后面模型輸入?yún)?shù)的個(gè)數(shù)。類別保存為標(biāo)簽向量(label_line_num, 1),label_line_num,同樣為數(shù)據(jù)集的大小。

為方便處理,將類別10的標(biāo)簽保存為0,并對(duì)label進(jìn)行“one_hot”處理,這部分解釋可參考上個(gè)tensotflow鏈接。該部分在datasets類中實(shí)現(xiàn)。需要注意的是這里train部分?jǐn)?shù)據(jù)最為cv(cross validation)數(shù)據(jù),這里暫時(shí)不會(huì)用到。此外,由于數(shù)據(jù)較多,為節(jié)省內(nèi)存,提高整體運(yùn)算速度,分別讀取train數(shù)據(jù)集和test數(shù)據(jù)集。dataset類中保存不同類型的數(shù)據(jù)集,并實(shí)現(xiàn)next_batch方法,獲取指定數(shù)目的數(shù)據(jù)。

  訓(xùn)練數(shù)據(jù)

該部分利用softmax回歸對(duì)數(shù)據(jù)進(jìn)行訓(xùn)練,對(duì)于tensorflow的使用這里不作介紹。完整代碼如下:

#!/usr/bin/python

#-*-coding:utf-8-*-


import tensorflow as tf

from datasets import datasets


data_sets = datasets()

data_sets.read_train_data(".", True)


sess = tf.InteractiveSession()


x = tf.placeholder(tf.float32, [None, 5000])

W = tf.Variable(tf.zeros([5000, 10]))

b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x, W) + b)


y_ = tf.placeholder(tf.float32, [None, 10])

cross_entropy = -tf.reduce_sum(y_ * tf.log(y + 1e-10))

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)


#training

tf.global_variables_initializer().run()


saver = tf.train.Saver()

for i in range(1000):

    batch_xs, batch_ys = data_sets.train.next_batch(100)

    train_step.run({x: batch_xs, y_: batch_ys})


print W.eval()

print b.eval()


path = saver.save(sess, "./model2/model.md")

代碼中:

● x : 對(duì)于輸入數(shù)據(jù),None占位符標(biāo)示輸入樣本的數(shù)量,5000為單個(gè)樣本的輸入維度,對(duì)應(yīng)字典維度。

● W :權(quán)重矩陣,行為輸入維度,列為輸出維度,這里為類別的數(shù)目10。

● b : 偏重為10對(duì)應(yīng)輸出的維度

● y : 定義訓(xùn)練輸出結(jié)果,使用softmax作為激勵(lì)函數(shù),tf.matmul(x, W) + b為輸入?yún)?shù),tf.matmul為矩陣乘。

● y_ : 真實(shí)樣本的類別,從數(shù)據(jù)集讀入,None占位符標(biāo)示輸入樣本的數(shù)量,10為輸出的維度。

● cross_entropy: 交叉熵,衡量真實(shí)值與預(yù)測(cè)值的偏差程度,訓(xùn)練過程中目的是最小化該值。

訓(xùn)練對(duì)cross_entropy進(jìn)行梯度下降算法更新參數(shù),學(xué)習(xí)率為0.01。迭代1000次,每次使用100個(gè)訓(xùn)練集。最后保存訓(xùn)練的模型到指定目錄。

  測(cè)試模型

這部分主要讀取上面保存的模型參數(shù),對(duì)測(cè)試數(shù)據(jù)集進(jìn)行預(yù)測(cè),并打印準(zhǔn)確率。

!/usr/bin/python

#-*-coding:utf-8-*-


import tensorflow as tf

from datasets import datasets


data_sets = datasets()

data_sets.read_test_data(".", True)


sess = tf.InteractiveSession()


x = tf.placeholder(tf.float32, [None, 5000])

W = tf.Variable(tf.zeros([5000, 10]))

b = tf.Variable(tf.zeros([10]))

y = tf.nn.softmax(tf.matmul(x, W) + b)

y_ = tf.placeholder(tf.float32, [None, 10])


saver = tf.train.Saver()

saver.restore(sess, "./model2/model.md")


# test

correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))

acc = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

print(acc.eval({x: data_sets.test.text, y_: data_sets.test.label}))

  小結(jié)

直接通過上面過程訓(xùn)練模型,得到的準(zhǔn)確率大概為65%,雖然比10%高出許多,仍然屬于比較低的準(zhǔn)確率。在后面一篇文章重點(diǎn)對(duì)上面的過程進(jìn)行改進(jìn),提高預(yù)測(cè)的準(zhǔn)確性。

此外,值得一提的是,一開始,直接參考tensorflow官網(wǎng)給的例子進(jìn)行訓(xùn)練會(huì)出現(xiàn)準(zhǔn)確率為0的現(xiàn)象,觀察TensorBord,發(fā)現(xiàn)權(quán)重和偏重一直不更新,打印W和b發(fā)現(xiàn)值為Nan,最后找到問題所在:

使用交叉熵作為cost function,由于文本矩陣為嚴(yán)重稀疏矩陣,導(dǎo)致出現(xiàn)y_ tf.log(y)結(jié)果為0log0的現(xiàn)象。導(dǎo)致訓(xùn)練參數(shù)為Nan,給預(yù)測(cè)值加一個(gè)極小的值,防止與測(cè)試為0。

雷鋒網(wǎng)相關(guān)閱讀:

手把手教你用 TensorFlow 實(shí)現(xiàn)文本分類(下)

手把手教你如何用 TensorFlow 實(shí)現(xiàn)基于 DNN 的文本分類


雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知

手把手教你用 TensorFlow 實(shí)現(xiàn)文本分類(上)

分享:
相關(guān)文章

編輯

聚焦數(shù)據(jù)科學(xué),連接 AI 開發(fā)者。更多精彩內(nèi)容,請(qǐng)?jiān)L問:yanxishe.com
當(dāng)月熱門文章
最新文章
請(qǐng)?zhí)顚懮暾?qǐng)人資料
姓名
電話
郵箱
微信號(hào)
作品鏈接
個(gè)人簡介
為了您的賬戶安全,請(qǐng)驗(yàn)證郵箱
您的郵箱還未驗(yàn)證,完成可獲20積分喲!
請(qǐng)驗(yàn)證您的郵箱
立即驗(yàn)證
完善賬號(hào)信息
您的賬號(hào)已經(jīng)綁定,現(xiàn)在您可以設(shè)置密碼以方便用郵箱登錄
立即設(shè)置 以后再說