美文网首页
Task7 卷积神经网络

Task7 卷积神经网络

作者: _一杯凉白开 | 来源:发表于2019-05-23 21:58 被阅读0次

    任务:

    1. 卷积运算的定义、动机(稀疏权重、参数共享、等变表示)。一维卷积运算和二维卷积运算。
    2. 反卷积(tf.nn.conv2d_transpose)
    3. 池化运算的定义、种类(最大池化、平均池化等)、动机。
    4. Text-CNN的原理。
    5. 利用Text-CNN模型来进行文本分类。

    文本分类实现数据集处理流程图

    • 数据处理步骤+每一步处理的目的如下图所示:


      文本分类实现数据集处理流程图
    • 数据处理部分实现
    1. 读数据
      其中数据是已经jiebe分词+去停用词后的结果
    def read_file(path):
        with open(path, 'r', encoding="UTF-8") as f:
            data = []
            labels = []
            for line in f:
                if line.split('\t')[1] == '':
                    continue
                data.append(line.split('\t')[0])
                labels.append(line.split('\t')[1])
        return data, labels
    # 读文件
    data, labels = read_file('E:/task6/merge.txt')
    
    1. 利用tokenizer将文字转换为数字特征
    • 将文字转换为数字特征要将整个数据集放入,这样保证训练集、验证集、测试集文字编码一致
    • 其中同时返回对应单词和数字的映射关系,以便在转化词向量过程中获取词向量列表
    def get_tokenizer(data):
        tokenizer = Tokenizer(num_words=None)
        tokenizer.fit_on_texts(data)
        text_seq = tokenizer.texts_to_sequences(data)
        # 对应的单词和数字的映射关系
        word_index = tokenizer.word_index 
        index_word = tokenizer.index_word
        return word_index, index_word, text_seq
    
    # 利用tokenizer将文字转换为数字特征
    word_index, index_word, X_train_text_seq = get_tokenizer(data)
    
    1. FastText Embedding
    def get_fasttext_voc(data, word_index):
        '''
            利用fasttext获取词向量
        '''
        fasttext_model = FastText([data], 
                                  size=FASTEXT_SIZE,         # 需要学习的嵌入大小(默认为100)
                                  window=3,         # 上下文窗口大小(默认5)
                                  min_count=1,      # 忽略出现次数低于此值的单词(默认值5)
                                  iter=10,          # epoch(默认5)
                                  min_n = 3,        # char ngram的最小长度(默认值3)
                                  max_n = 6,        # char ngram的最大长度(默认值6)
                                  word_ngrams = 0)  # 如果为1,使用子单词(n-grams)信息丰富单词向量。如果是0,这就相当于Word2Vec
        # 获取词向量列表
        wordEmbedding = np.zeros((len(word_index) + 1, FASTEXT_SIZE))
        for word, i in word_index.items():
            if word in fasttext_model:
                wordEmbedding[i] = fasttext_model[word]   
        return wordEmbedding
    
    # fasttext embedding
    wordEmbedding = get_fasttext_voc(data, word_index)
    
    1. 让每个文本长度相同
    # 让每个文本长度相同
    X_train_text_seq = pad_sequences(X_train_text_seq, maxlen=LEN_WORDS, padding='post', truncating='post')
    
    1. 划分数据集
    # 划分数据集
    X_train, X_test, y_train, y_test = train_test_split(X_train_text_seq, 
                                                        labels,
                                                        test_size = 0.2,
                                                        random_state=33)
    
    1. 对类别变量编码
    def get_label_num(data):
        data = [i.replace('\n', '') for i in data]
        y_labels = list(set(data))
        le = preprocessing.LabelEncoder()
        le.fit(y_labels)
        num_labels = len(y_labels)
        data_labels = to_categorical([le.transform([x])[0] for x in data], num_labels)
        return data_labels
    
    # 对类别变量编码
    y_train_label = get_label_num(y_train)
    y_test_label = get_label_num(y_test)
    

    CNN

    实现基础版CNN:

    LeNet-5 是卷积神经网络的作者Yann LeCun用于MNIST识别任务提出的模型。模型很简单,就是卷积池化层的堆叠,最后加上几层全连接层。将其运用在文本分类任务中。
    其中模型结构如下所示:


    实现过程如下:

    def model_CNN(X_train, X_test, y_train, y_test, index_word, embedding_matrix):
        '''
            模型结构:
                嵌入层:将词编码数据转换为固定尺寸的稠密向量,同时把词向量矩阵加载到Embedding层
                卷积池化层:256 * 3 * 3
                卷积池化层:128 * 3 * 3
                Dropout:0.1
                BatchNormalization: 批量标准化层,在每一个批次的数据中标准化前一层的激活项
                全连接:256,'relu'
                分类器:2, 'softmax'
        '''
        model = Sequential()
        model.add(Embedding(len(index_word) + 1,             # imput_dim: 词汇表大小,即最大整数index+1
                            FASTEXT_SIZE,                    # output_dim: 词向量的维度
                            weights=[embedding_matrix],      # 加载词向量矩阵
                            input_length=LEN_WORDS,           # input_lenth: 输入序列的长度
                            trainable=False))                # 设置trainable=False使得这个编码层不可再训练
        # filters:输出空间的维度,kernel_size: 1D 卷积窗口的长度,padding:"same" 表示填充输入以使输出具有与原始输入相同的长度
        model.add(Conv1D(256, 3, padding='same'))   
        # pool_size:最大池化的窗口大小, strides:作为缩小比例的因数
        model.add(MaxPooling1D(3, 3, padding='same'))
        model.add(Conv1D(128, 3, padding='same'))
        model.add(MaxPooling1D(3, 3, padding='same'))
        model.add(Conv1D(64, 3, padding='same'))
        
        model.add(Flatten())
        # rate: 在 0 和 1 之间浮动。需要丢弃的输入比例
        model.add(Dropout(0.1))
        model.add(BatchNormalization())
        # units: 正整数,输出空间维度
        model.add(Dense(256, activation='relu'))
        model.add(Dropout(0.1))
        model.add(Dense(2, activation='softmax'))
        # 配置训练模型
        model.compile(loss='categorical_crossentropy',          # 表示目标应该是分类格式的
                      optimizer='adam',                         # 随机优化的一种方法
                      metrics=['accuracy']                      # 模型评估标准
                      )
        # 给定数量的迭代训练模型
        model.summary()
        model.fit(X_train, y_train, 
                  batch_size=32, 
                  epochs=15, 
                  validation_data=(X_test, y_test))  
    

    Text-CNN

    1. 原理

    Yoon Kim在2014年 “Convolutional Neural Networks for Sentence Classification” 论文中提出TextCNN(利用卷积神经网络对文本进行分类的算法)论文翻译版,其中网络结构如下所示:


    假设我们有一些句子需要对其进行分类。句子中每个词是由n维词向量组成的,也就是说输入矩阵大小为m*n,其中m为句子长度。CNN需要对输入样本进行卷积操作,对于文本数据,filter不再横向滑动,仅仅是向下移动,有点类似于N-gram在提取词与词间的局部相关性。图中共有三种步长策略,分别是2,3,4,每个步长都有两个filter(实际训练时filter数量会很多)。在不同词窗上应用不同filter,最终得到6个卷积后的向量。然后对每一个向量进行最大化池化操作并拼接各个池化值,最终得到这个句子的特征表示,将这个句子向量丢给分类器进行分类,至此完成整个流程。
    其中每个层的作用,参照:https://blog.csdn.net/asialee_bird/article/details/88813385

    模型结构如下所示:


    TextCNN网络结构

    实现过程如下:

    def model_TextCNN(X_train, X_test, y_train, y_test, index_word, embedding_matrix):
        '''
            模型结构:
                词嵌入,
                卷积池化 * 3:256 * 3 * 4
                拼接三个模型的输出向量,
                全连接,
                Dropout,
                全连接
        '''
        # shape: 一个尺寸元组(整数)表明期望的输入是按批次的LEN_WORDS维向量
        main_input = Input(shape=(LEN_WORDS, ), dtype='float32')
        embed = Embedding(len(index_word) + 1,             
                            FASTEXT_SIZE,                    
                            weights=[embedding_matrix],      
                            input_length=LEN_WORDS,           
                            trainable=False)(main_input)
        # 词窗大小分别为3,4,5
        # strides指明卷积的步长
        cnn1 =  Conv1D(256, 3, padding='same', strides=1, activation='relu')(embed)
        cnn1 = MaxPooling1D(pool_size=4)(cnn1)
        cnn2 =  Conv1D(256, 4, padding='same', strides=1, activation='relu')(embed)
        cnn2 = MaxPooling1D(pool_size=4)(cnn2)
        cnn3 =  Conv1D(256, 5, padding='same', strides=1, activation='relu')(embed)
        cnn3 = MaxPooling1D(pool_size=4)(cnn3)  
        # 合并三个模型的输出向量
        cnn = concatenate([cnn1,cnn2,cnn3], axis=-1)                 
        flat = Flatten()(cnn)
        drop = Dropout(0.1)(flat)
        main_output = Dense(2, activation='softmax')(drop)
        model = Model(inputs=main_input, output=main_output)
        # 配置训练模型
        model.compile(loss='categorical_crossentropy',          # 表示目标应该是分类格式的
                      optimizer='adam',                         # 随机优化的一种方法
                      metrics=['accuracy']                      # 模型评估标准
                      )
        # 给定数量的迭代训练模型
        model.summary()
        model.fit(X_train, y_train, 
                  batch_size=32, 
                  epochs=15, 
                  validation_data=(X_test, y_test))
    

    完整代码见:github
    参考资料:

    相关文章

      网友评论

          本文标题:Task7 卷积神经网络

          本文链接:https://www.haomeiwen.com/subject/ycvyzqtx.html