TextCNN-基于卷積神經(jīng)網(wǎng)絡(luò)的文本分類

1 簡(jiǎn)述

????在沒(méi)有監(jiān)督數(shù)據(jù)的時(shí)候,采用無(wú)監(jiān)督算法的方式可以計(jì)算兩句話的相似度球及,即通過(guò)一些因子粒竖,比如語(yǔ)序颅崩、詞性、共現(xiàn)詞比例等等進(jìn)行打分蕊苗,最后通過(guò)加權(quán)計(jì)算的方式得到最終的相似分值沿后,最終結(jié)果主要依賴因子即特征的提取和加權(quán)公式的設(shè)計(jì),相關(guān)項(xiàng)目可以參考Kaggle Quora比賽華人第一名的解決方案朽砰,里面有一些優(yōu)秀的可借鑒特征尖滚。
????但是最終想要更好的效果必然要使用到有監(jiān)督的算法,而現(xiàn)有較好的技術(shù)便是TextCNN瞧柔。本文主要是整理捋順一下TextCNN的整個(gè)過(guò)程以及背后的一些原理漆弄,包括自己踩坑的點(diǎn),還有Tensorflow的一些框架問(wèn)題造锅。

2 項(xiàng)目

????CNN做文本分類的項(xiàng)目及代碼可以參考: TextCNN

3 論文

????CNN做文本分類的論文可以參看: Convolutional Neural Networks for Sentence Classification

paper_models.png

????上圖是論文中給出的模型結(jié)構(gòu)撼唾,但是這張圖不是很清楚,下圖可以更清楚的看清TextCNN的結(jié)構(gòu)哥蔚。
models.png

????算法的主要流程是通過(guò)使用不同kernel_sizes的卷積核對(duì)文本embedding二維向量進(jìn)行卷積操作倒谷,每一種kernel_sizes的卷積核有多個(gè),這樣就可以獲得類似n-gram的句法特征糙箍,最后經(jīng)過(guò)max_pooling恨锚,在進(jìn)行一次拼接,即可以得到文檔向量倍靡,經(jīng)過(guò)全連接和softmax即可進(jìn)行分類猴伶。
????由上圖所示,文檔二維embedding向量為(7x5),卷積核的kernel_sizes有三種他挎,分別為2,3,4筝尾,每種卷積核有2個(gè),一共有2x3=6個(gè)卷積核办桨。kernel_sizes=4的卷積核經(jīng)過(guò)卷積之后得到(7-4+1)x1即4x1的向量筹淫,通過(guò)max_pooling之后得到一個(gè)數(shù)值,同理其余的5個(gè)卷積核分別進(jìn)行卷積和池化操作呢撞,這樣可以得到6個(gè)數(shù)值损姜,然后將這6個(gè)數(shù)值拼接一起,注意拼接時(shí)候的維度殊霞,既可以得到文本新的向量摧阅。然后可以接全連接再接softmax即可以分類。
????論文中另一case是針對(duì)算法的輸入即embedding向量進(jìn)行優(yōu)化绷蹲,可以使用Pre-trained的詞向量代替隨機(jī)初始化的embedding向量棒卷,分別對(duì)比隨機(jī)初始化、靜態(tài)預(yù)訓(xùn)練向量(不參與訓(xùn)練)祝钢、微調(diào)預(yù)訓(xùn)練向量(參與訓(xùn)練)和通過(guò)設(shè)置通道channels輸入不同向量四種方式比规。最終效果個(gè)人感覺(jué)只能做一個(gè)參考,具體還要視業(yè)務(wù)場(chǎng)景而定拦英。比如針對(duì)業(yè)務(wù)垂直領(lǐng)域很強(qiáng)的文本領(lǐng)域蜒什,使用基于大數(shù)據(jù)集的預(yù)訓(xùn)練向量可能不會(huì)有很好的效果,比如針對(duì)數(shù)碼領(lǐng)域疤估,如果隨機(jī)初始化embedding向量吃谣,在通過(guò)train的方式更新,那么類似“蘋果”之類的詞語(yǔ)更會(huì)傾向“蘋果手機(jī)”做裙,而使用大數(shù)據(jù)集預(yù)訓(xùn)練的詞向量岗憋,“蘋果”這個(gè)詞則可能更會(huì)傾向水果,這種引入預(yù)訓(xùn)練的方式可能會(huì)打破原有數(shù)據(jù)的結(jié)構(gòu)平衡锚贱,當(dāng)然如果對(duì)領(lǐng)域多元化的業(yè)務(wù)可能引入預(yù)訓(xùn)練效果會(huì)更好仔戈。另一個(gè)引入預(yù)訓(xùn)練詞向量的好處是可以加快訓(xùn)練速度,這樣即使效果得不到提升拧廊,但是速度得到提升也是蠻不錯(cuò)的监徘。

4 代碼

????下面是一個(gè)標(biāo)準(zhǔn)的TextCNN的代碼:

# coding: utf-8

import tensorflow as tf
import warnings
warnings.filterwarnings("ignore")

class TCNNConfig(object):
    embedding_dim = 64  # 詞向量維度
    seq_length = 600  # 序列長(zhǎng)度
    num_classes = 10  # 類別數(shù)
    num_filters = 256  # 卷積核數(shù)目
    # kernel_sizes = [3, 4, 5]  # 卷積核尺寸
    kernel_sizes = 5 # 卷積核尺寸
    vocab_size = 5000  # 詞匯表達(dá)小
    hidden_dim = 128 # 全連接層神經(jīng)元
    dropout_keep_prob = 0.5  # dropout保留比例
    learning_rate = 1e-3  # 學(xué)習(xí)率
    batch_size = 64  # 每批訓(xùn)練大小
    num_epochs = 10  # 總迭代輪次
    print_per_batch = 100  # 每多少輪輸出一次結(jié)果
    save_per_batch = 10  # 每多少輪存入tensorboard

class TextCNN(object):
    def __init__(self, config):
        self.config = config
        # 三個(gè)待輸入的數(shù)據(jù)
        self.input_x = tf.placeholder(tf.int32, [None, self.config.seq_length], name='input_x')
        self.input_y = tf.placeholder(tf.float32, [None, self.config.num_classes], name='input_y')
        self.keep_prob = tf.placeholder(tf.float32, name='keep_prob')
        self.cnn()
    def cnn(self):
        # 詞向量映射
        with tf.device('/cpu:0'):
            embedding = tf.get_variable('embedding', [self.config.vocab_size, self.config.embedding_dim])
            embedding_inputs = tf.nn.embedding_lookup(embedding, self.input_x)

        with tf.name_scope("cnn"):
            # CNN layer
            conv = tf.layers.conv1d(embedding_inputs, self.config.num_filters, self.config.kernel_size, name='conv')
            # global max pooling layer
            gmp = tf.reduce_max(conv, reduction_indices=[1], name='gmp')

        '''
        for kernel_size in self.config.kernel_sizes:
            gmps = []
            with tf.name_scope("cnn-%s" % kernel_size):
                # CNN layer
                conv = tf.layers.conv1d(embedding_inputs, self.config.num_filters, kernel_size)
                # global max pooling layer
                gmp = tf.reduce_max(conv, reduction_indices=[1])
                gmps.append(gmp)
        gmp = tf.concat(values=gmps, name='last_pool_layer', axis=3)
        '''

        with tf.name_scope("score"):
            # 全連接層,后面接dropout以及relu激活
            fc1 = tf.layers.dense(gmp, self.config.hidden_dim, name='fc1')
            fc2 = tf.contrib.layers.dropout(fc1, self.keep_prob)
            fc = tf.nn.relu(fc2)

            # 分類器
            self.logits = tf.layers.dense(fc, self.config.num_classes, name='fc2')
            self.y_pred_cls = tf.argmax(tf.nn.softmax(self.logits), 1)  # 預(yù)測(cè)類別

        with tf.name_scope("optimize"):
            # 損失函數(shù)吧碾,交叉熵
            cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=self.logits, labels=self.input_y)
            self.loss = tf.reduce_mean(cross_entropy)
            # 優(yōu)化器
            self.optim = tf.train.AdamOptimizer(learning_rate=self.config.learning_rate).minimize(self.loss)

        with tf.name_scope("accuracy"):
            # 準(zhǔn)確率
            correct_pred = tf.equal(tf.argmax(self.input_y, 1), self.y_pred_cls)
            self.acc = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

????代碼中的TextCNN并沒(méi)有設(shè)置可變kernel_sizes凰盔,統(tǒng)一設(shè)置kernel_sizes=5。通過(guò)修改注釋代碼即可以實(shí)現(xiàn)可變kernel_sizes倦春。實(shí)驗(yàn)之后發(fā)現(xiàn)加入可變的kernel_sizes可以在實(shí)驗(yàn)的那個(gè)數(shù)據(jù)集上略微提升一點(diǎn)效果户敬,但是提升不大落剪,因?yàn)楣潭╧ernel_sizes=5效果就已經(jīng)很好了,具體對(duì)比可以看GitHub的對(duì)比尿庐,所以在新的數(shù)據(jù)集上可以實(shí)驗(yàn)對(duì)比兩種效果忠怖,kernel_sizes一般選2,3,4,5。
????另一個(gè)困擾我比較久的是數(shù)據(jù)傳輸問(wèn)題抄瑟,數(shù)據(jù)在傳送過(guò)程中的維度變化》财現(xiàn)在就基于以上代碼(tensorflow)捋順一下數(shù)據(jù)傳送過(guò)程中的維度變化。batch_size=64皮假,seq_length=600鞋拟,可得input_x (64, 600);vocab_size=5000惹资,embedding_dim =64贺纲,可得embedding (5000, 64);embedding_inputs (64, 600, 64)布轿;num_filters=256哮笆,kernel_size=5来颤,可得conv (64, 596, 256)汰扭;gmp (64, 256);fc1 (64, 128)福铅;fc2(64, 128)萝毛,fc1到fc2只經(jīng)過(guò)一個(gè)dropout所以維度并沒(méi)有變化;fc(64, 128)滑黔,fu2到fc只經(jīng)過(guò)一個(gè)relu所以維度沒(méi)有變化笆包。之后就是進(jìn)行softmax操作了。

5 踩坑

???? - python2 對(duì)漢字真是太不友好了略荡,各種編碼問(wèn)題
???? - 盡量不要并聯(lián)太多and庵佣,不然速度會(huì)很慢,比如分詞的時(shí)候可以先通過(guò)詞長(zhǎng)過(guò)濾掉一部分汛兜,然后全部收集巴粪,最后再遍歷,篩掉停用詞粥谬。如果分詞的時(shí)候直接篩停用詞肛根,速度超級(jí)慢。
???? - 字符級(jí)和詞語(yǔ)級(jí)從當(dāng)前公開(kāi)數(shù)據(jù)集上對(duì)比漏策,效果相當(dāng)派哲,詞語(yǔ)級(jí)速度更快,但是需要預(yù)先分詞
???? - 目前還沒(méi)有實(shí)驗(yàn)預(yù)訓(xùn)練詞向量掺喻,未完待續(xù)芭届。储矩。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末喉脖,一起剝皮案震驚了整個(gè)濱河市椰苟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌树叽,老刑警劉巖舆蝴,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異题诵,居然都是意外死亡洁仗,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門性锭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)赠潦,“玉大人,你說(shuō)我怎么就攤上這事草冈∷拢” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵怎棱,是天一觀的道長(zhǎng)哩俭。 經(jīng)常有香客問(wèn)我,道長(zhǎng)拳恋,這世上最難降的妖魔是什么凡资? 我笑而不...
    開(kāi)封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮谬运,結(jié)果婚禮上隙赁,老公的妹妹穿的比我還像新娘。我一直安慰自己梆暖,他們只是感情好伞访,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著轰驳,像睡著了一般厚掷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上滑废,一...
    開(kāi)封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天蝗肪,我揣著相機(jī)與錄音,去河邊找鬼蠕趁。 笑死薛闪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的俺陋。 我是一名探鬼主播豁延,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼昙篙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了诱咏?” 一聲冷哼從身側(cè)響起苔可,我...
    開(kāi)封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎袋狞,沒(méi)想到半個(gè)月后焚辅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苟鸯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年同蜻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片早处。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡湾蔓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砌梆,到底是詐尸還是另有隱情默责,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布咸包,位于F島的核電站桃序,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏诉儒。R本人自食惡果不足惜葡缰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一亏掀、第九天 我趴在偏房一處隱蔽的房頂上張望忱反。 院中可真熱鬧,春花似錦滤愕、人聲如沸温算。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)注竿。三九已至,卻和暖如春魂贬,著一層夾襖步出監(jiān)牢的瞬間巩割,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工付燥, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宣谈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓键科,卻偏偏與公主長(zhǎng)得像闻丑,于是被迫代替她去往敵國(guó)和親漩怎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容