首頁  >  文章  >  後端開發  >  序列分類、IMDB影評分類等功能詳解

序列分類、IMDB影評分類等功能詳解

巴扎黑
巴扎黑原創
2017-06-23 14:59:531833瀏覽

序列分類,預測整個輸入序列的類別標籤。情緒分析,預測使用者撰寫文字話題態度。預測選舉結果或產品、電影評分。

國際電影資料庫(International Movie Database)影評資料集。目標值二元,正面或負面。語言大量否定、反語、模糊,不能只看單字是否出現。建立詞向量循環網絡,逐個單字查看每個評論,最後單字話性值訓練預測整個評論情緒分類器。

斯擔福大學人工智慧實驗室的IMDB影評資料集: http://ai.stanford.edu/~amaas/data/sentiment/ 。壓縮tar文檔,正面負面評論從兩個文件夾文字文件獲取。利用正規表示式擷取純文本,字母全部轉小寫。

詞向量嵌入表示,比獨熱編碼詞語語義更豐富。詞彙表確定單字索引,找出正確詞向量。序列填滿相同長度,多個影評資料批次送入網路。

序列標註模型,傳入兩個佔位符,一輸入資料data或序列,二目標值target或情緒。傳入配置參數params對象,優化器。

動態計算目前批次資料序列長度。資料單一張量形式,各序列以最長影評長度補0。絕對值最大值縮減詞向量。零向量,標量0。實型詞向量,標量大於0實數。 tf.sign()離散為0或1。結果沿時間步相加,得到序列長度。張量長度與批次資料容量相同,標量表示序長。

使用params物件定義單元類型和單元數量。 length屬性指定向RNN提供批次資料最多行數。取得每個序列最後活性值,送入softmax層。因每條影評長度不同,批次資料每個序列RNN最後相關輸出活性值有不同索引。在時間步維度(批次資料形狀sequences*time_steps*word_vectors)建立索引。 tf.gather()沿第1維建立索引。輸出活性值形狀sequences*time_steps*word_vectors前兩維扁平化(flatten),加入序列長度。新增length-1,選擇最後有效時間步。

梯度裁剪,梯度值限制在合理範圍內。可用任何中分類有意義代價函數,模型輸出可用所有類別機率分佈。增加梯度裁切(gradient clipping)改善學習結果,限制最大權值更新。 RNN訓練難度高,不同超參數搭配不當,權值極易發散。

TensorFlow支援優化器實例compute_gradients函數推演,修改梯度,apply_gradients函數應用權值變化。梯度分量小於-limit,設定-limit;梯度分量在於limit,設定limit。 TensorFlow導數可取None,表示某個變數與代價函數沒有關係,數學上應為零向量但None利於內部效能最佳化,只需傳回None值。

影評逐字送入循環神經網絡,每個時間步由詞向量構成批次資料。 batched函數找出詞向量,所有序列長度補齊。訓練模型,定義超參數、載入資料集和詞向量、經過預處理訓練批次資料運行模型。模型成功訓練,取決網路結構、超參數、詞向量品質。可從skip-gram模型word2vec專案( )、史丹佛NLP研究組Glove模型(https://nlp.stanford.edu/projects/glove ),載入預訓練詞向量。

Kaggle 開放學習競賽( ),IMDB影評數據,與他人比較預測結果。

    import tarfileimport refrom helpers import downloadclass ImdbMovieReviews:

        DEFAULT_URL = \'http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz'TOKEN_REGEX = re.compile(r'[A-Za-z]+|[!?.:,()]')def __init__(self, cache_dir, url=None):
        self._cache_dir = cache_dir
        self._url = url or type(self).DEFAULT_URLdef __iter__(self):
            filepath = download(self._url, self._cache_dir)
            with tarfile.open(filepath) as archive:for filename in archive.getnames():if filename.startswith('aclImdb/train/pos/'):yield self._read(archive, filename), Trueelif filename.startswith('aclImdb/train/neg/'):yield self._read(archive, filename), Falsedef _read(self, archive, filename):
            with archive.extractfile(filename) as file_:
                data = file_.read().decode('utf-8')
                data = type(self).TOKEN_REGEX.findall(data)
                data = [x.lower() for x in data]return dataimport bz2import numpy as npclass Embedding:def __init__(self, vocabulary_path, embedding_path, length):
            self._embedding = np.load(embedding_path)
            with bz2.open(vocabulary_path, 'rt') as file_:
                self._vocabulary = {k.strip(): i for i, k in enumerate(file_)}
            self._length = lengthdef __call__(self, sequence):
            data = np.zeros((self._length, self._embedding.shape[1]))
            indices = [self._vocabulary.get(x, 0) for x in sequence]
            embedded = self._embedding[indices]
            data[:len(sequence)] = embeddedreturn data

        @propertydef dimensions(self):return self._embedding.shape[1]import tensorflow as tffrom helpers import lazy_propertyclass SequenceClassificationModel:def __init__(self, data, target, params):
            self.data = data
            self.target = target
            self.params = params
            self.prediction
            self.cost
            self.error
            self.optimize

        @lazy_propertydef length(self):
            used = tf.sign(tf.reduce_max(tf.abs(self.data), reduction_indices=2))
            length = tf.reduce_sum(used, reduction_indices=1)
            length = tf.cast(length, tf.int32)return length

        @lazy_propertydef prediction(self):# Recurrent network.output, _ = tf.nn.dynamic_rnn(
                self.params.rnn_cell(self.params.rnn_hidden),
                self.data,
                dtype=tf.float32,
                sequence_length=self.length,
            )
            last = self._last_relevant(output, self.length)# Softmax layer.num_classes = int(self.target.get_shape()[1])
            weight = tf.Variable(tf.truncated_normal(
                [self.params.rnn_hidden, num_classes], stddev=0.01))
            bias = tf.Variable(tf.constant(0.1, shape=[num_classes]))
            prediction = tf.nn.softmax(tf.matmul(last, weight) + bias)return prediction

        @lazy_propertydef cost(self):
            cross_entropy = -tf.reduce_sum(self.target * tf.log(self.prediction))return cross_entropy

        @lazy_propertydef error(self):
            mistakes = tf.not_equal(
                tf.argmax(self.target, 1), tf.argmax(self.prediction, 1))return tf.reduce_mean(tf.cast(mistakes, tf.float32))

        @lazy_propertydef optimize(self):
            gradient = self.params.optimizer.compute_gradients(self.cost)try:
                limit = self.params.gradient_clipping
                gradient = [
                    (tf.clip_by_value(g, -limit, limit), v)if g is not None else (None, v)for g, v in gradient]except AttributeError:print('No gradient clipping parameter specified.')
            optimize = self.params.optimizer.apply_gradients(gradient)return optimize

        @staticmethoddef _last_relevant(output, length):
            batch_size = tf.shape(output)[0]
            max_length = int(output.get_shape()[1])
            output_size = int(output.get_shape()[2])
            index = tf.range(0, batch_size) * max_length + (length - 1)
            flat = tf.reshape(output, [-1, output_size])
            relevant = tf.gather(flat, index)return relevantimport tensorflow as tffrom helpers import AttrDictfrom Embedding import Embeddingfrom ImdbMovieReviews import ImdbMovieReviewsfrom preprocess_batched import preprocess_batchedfrom SequenceClassificationModel import SequenceClassificationModel

    IMDB_DOWNLOAD_DIR = './imdb'WIKI_VOCAB_DIR = '../01_wikipedia/wikipedia'WIKI_EMBED_DIR = '../01_wikipedia/wikipedia'params = AttrDict(
        rnn_cell=tf.contrib.rnn.GRUCell,
        rnn_hidden=300,
        optimizer=tf.train.RMSPropOptimizer(0.002),
        batch_size=20,
    )

    reviews = ImdbMovieReviews(IMDB_DOWNLOAD_DIR)
    length = max(len(x[0]) for x in reviews)

    embedding = Embedding(
        WIKI_VOCAB_DIR + '/vocabulary.bz2',
        WIKI_EMBED_DIR + '/embeddings.npy', length)
    batches = preprocess_batched(reviews, length, embedding, params.batch_size)

    data = tf.placeholder(tf.float32, [None, length, embedding.dimensions])
    target = tf.placeholder(tf.float32, [None, 2])
    model = SequenceClassificationModel(data, target, params)

    sess = tf.Session()
    sess.run(tf.initialize_all_variables())for index, batch in enumerate(batches):
        feed = {data: batch[0], target: batch[1]}
        error, _ = sess.run([model.error, model.optimize], feed)print('{}: {:3.1f}%'.format(index + 1, 100 * error))

 

參考資料:
《機器智能的TensorFlow實踐》

歡迎加我微信交流:qingxingfengzi
我的微信公眾號:qingxingfengzigz
我老婆張幸清的微信公眾號:qingqingfeifangz

#

以上是序列分類、IMDB影評分類等功能詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn