美文网首页
Task6 神经网络基础

Task6 神经网络基础

作者: _一杯凉白开 | 来源:发表于2019-05-22 16:33 被阅读0次

    任务

    • 前馈神经网络、网络层数、输入层、隐藏层、输出层、隐藏单元、激活函数的概念。
    • 感知机相关;定义简单的几层网络(激活函数sigmoid),递归使用链式法则来实现反向传播。
    • 激活函数的种类以及各自的提出背景、优缺点。(和线性模型对比,线性模型的局限性,去线性化)
    • 深度学习中的正则化(参数范数惩罚:L1正则化、L2正则化;数据集增强;噪声添加;early stop;Dropout层)、正则化的介绍。
    • 深度模型中的优化:参数初始化策略;自适应学习率算法(梯度下降、AdaGrad、RMSProp、Adam;优化算法的选择);batch norm层(提出背景、解决什么问题、层在训练和测试阶段的计算公式);layer norm层。
    • FastText的原理。
    • 利用FastText模型进行文本分类。

    概念:

    1. 前馈神经网络

    这是实际应用中最常见的神经网络类型。
    第一层是输入,最后一层是输出,如果有多个隐藏层则称之为“深度”神经网络。他们计算出一系列改变样本相似性的变换。各层神经元的活动是前一层活动的非线性函数。

    2.网络层数

    神经网络主要由:输入层,隐藏层,输出层构成。
    当隐藏层只有一层时,该网络为两层神经网络;

    1. 输入层:

    输入层未做任何变换,可以不看做单独的一层;
    实际中网络输入层的每个神经元代表了一个特征,输入层个数代表了分类标签的个数;

    1. 隐藏层

    单个隐藏层的意义就是把输入数据的特征,抽象到另一个维度空间,来展现其更抽象化的特征;
    多个隐藏层其实是对输入特征多层次的抽象,最终的目的就是为了更好的线性划分不同类型的数据;
    隐藏层层数以及隐藏层神经元是由人工设定 ;

    补充:理论上隐藏层越多可以将特征划分的更清楚,但是会带来两个问题:

    1. 层数越多参数会爆炸式增多
    2. 到了一定层数再往深了增加隐藏层,分类效果的增强会越来越不明显
    1. 输出层

    在做二分类的时候,如果采用sigmoid分类器,输出层的神经元个数为1个;如果采用softmax分类器输出层神经元个数为2个

    1. 隐藏单元

    我们把网络中的每一个结点称之为一个神经元(单元),隐藏单元即为隐藏层中的神经元(单元);
    其中,神经元:人工神经元(Artificial Neuron),简称神经元(Neuron),是构成神经网络的基本单元,其主要是模拟生物神经元的结构和特性,接受一组输入信号并产出输出。

    1. 激活函数

    激活函数是用来加入非线性因素的,解决线性模型所不能解决的问题;
    在神经网络中,我们可以经常看到对于某一个隐藏层的节点,该节点的激活之计算一般分为两步:
    (1) 输入该节点的值后先进行一个线性变换,计算出值
    (2)再进行一个非线性变换,也就是经过一个非线性激活函数

    常用的激活函数包括:sigmoid函数、tanh函数、ReLU函数。

    sigmoid函数:

    • 该函数数将取值为(−∞,+∞) 的数映射到(0,1)之间,其公式以及函数图如下所示:
      g(z)=\frac{1}{1+e^{-z}}

      求导推导为:
      g'(z) = (\frac{1}{1+e^{-z}})'=\frac{e^{-z}}{(1+e^{-z})^2}=g(z)(1-g(z))
    • sigmoid存在几个缺点,所以被使用的频率较低
      1. 当值非常大或者非常小是sigmoid的导数会趋近为0,则会导致梯度消失
      2. 函数的输出不是以0位均值,不便于下一层的计算
      3. 当目标是解决一个二分类问题,可在输出层使用sigmoid函数进行二分类。

    tanh函数

    • 该函数数将取值为(−∞,+∞) 的数映射到(-1,1)之间,其公式以及函数图如下所示:
      g(z)=\frac{e^{z}-e^{-z}}{e^{z}+e^{-z}}

      tanh函数的均值为0,弥补了sigmoid函数均值为0.5的缺点
      tanh函数的求导推导为:
      g(z)=(\frac{e^{z}-e^{-z}}{e^{z}+e^{-z}})^{'}=\frac{4}{(e^{z}+e^{-z})^2}=1-g(z)^2
      • tanh与sigmoid存在相同的问题,当值很大或者很小的时候会出现梯度消失的问题

    ReLU函数

    • ReLU函数又称为修正线性单元, 是一种分段线性函数,其弥补了sigmoid函数以及tanh函数的梯度消失问题。ReLU函数的公式以及图形如下:
      g(z)=\begin{cases}z, if z > 0\\ 0, if z < 0 \end{cases}

      ReLU函数求导为:
      g'(z)=\begin{cases}1, if z > 0\\ 0, if z < 0 \end{cases}
    • ReLU的优点:1. 当输入大于0时,不存在梯度消失的问题2. 由于ReLU函数只有线性关系,所以计算速度要快很多
    • Relu的缺点:当输入小于0时,梯度为0,会产生梯度消失问题。
    1. 感知机相关

    感知机是二分类的线性分类模型,输入为实例的特征向量,输出为实例的类别(取+1和-1);
    感知机目的在求一个可以将实例分开的超平面,为了求它,我们用到基于误分类的损失函数和梯度下降的优化策略。

    感知机模型理解见:https://www.leiphone.com/news/201706/FEz9czQa8TMPGyqr.html

    1. 正则化

    它的形式很简单,是在目标函数后额外附加一项,使其影响目标函数最优点的选取。这种方法叫做正则化方法。
    L1正则化、L2正则化原理参考:https://blog.csdn.net/u012950413/article/details/80464318#L1_86

    • 数据集增强

    数据集增强的原因:一般而言,比较成功的神经网络需要大量的参数,许许多多的神经网路的参数都是数以百万计,而使得这些参数可以正确工作则需要大量的数据进行训练,而实际情况中数据并没有我们想象中的那么多

    • 数据集增强的作用:
      1. 增加训练的数据量,提高模型的泛化能力
      2. 增加噪声数据,提升模型的鲁棒性

    如何进行数据增强:

    • 利用已有的数据比如翻转、平移或旋转,创造出更多的数据,来使得神经网络具有更好的泛化效果。
    1. 离线增强:直接对数据集进行处理,数据的数目会变成增强因子 * 原数据集的数目 ,这种方法常常用于数据集很小的时候
    2. 在线增强 : 这种增强的方法用于,获得 batch 数据之后,然后对这个 batch 的数据进行增强,如旋转、平移、翻折等相应的变化,由于有些数据集不能接受线性级别的增长,这种方法长用于大的数据集。
    • Early stoping

    Early stopping可以实现在指定位置停止训练,获得一个泛化能力较强的模型,其主要步骤如下:

    1. 将原始的训练数据集划分成训练集和验证集
    2. 只在训练集上进行训练,并每个一个周期计算模型在验证集上的误差,例如,每15次epoch(mini batch训练中的一个周期)
    3. 当模型在验证集上的误差比上一次训练结果差的时候停止训练
    4. 使用上一次迭代结果中的参数作为模型的最终参数

    补充:在现实中,模型在验证集上的误差并不平滑,也就是模型在验证集上的表现可能短暂的变差之后有可能继续变好,所以早停法主要是训练时间和泛化错误之间的权衡。

    • Dropout层

    我们在前向传播的时候,让某个神经元的激活值以一定的概率p停止工作,这样可以使模型泛化性更强,因为它不会太依赖某些局部的特征
    工作流程及使用参见:https://blog.csdn.net/program_developer/article/details/80737724

    FastText

    1. 模型架构

    fasttext算法是一种有监督的结构,它通过上下文预测标签即文本的类别
    fasttext模型的输入是一个词/一句话/一段文本的序列,输出的是这个序列属于不用类别的概率。
    在序列中的词和词组构成特征向量,特征向量通过线性变换映射到中间层,再由中间层映射到标签。
    fasttext在预测标签时使用了非线性激活函数,但在中间层不使用非线性激活函数。


    fasttext代码整体结构
    1. 利用FastText模型进行文本分类

    注意:win无法直接用pip install fasttext安装fasttext,我首先在python的第三方安装包网站https://www.lfd.uci.edu/~gohlke/pythonlibs/#fasttext*
    下载fasttext‑0.8.22‑cp36‑cp36m‑win_amd64.whl后再本地安装

    fasttext本地安装方法
    本地调用fasttext:
    import fastText.FastText as ff
    

    补充:实验进行文本分类的文件已事先分词、去停用词后的结果

    • 首先读文件
    def read_file(path):
        with open(path, 'r', encoding="UTF-8") as f:
            data = []
            labels = []
            for line in f:
                data.append(line.split('\t')[0])
                labels.append(line.split('\t')[1])
        return data, labels
    
    data, labels = read_file('E:/task6/merge.txt')
    
    • 对数据进行预处理

    fasttext训练数据是直接对文件进行读取,所以在训练前应当对数据进行处理,
    fasttext读取的文件有固定格式:

    第一列 第二列 第三列
    label前缀 标签值 编码后文本

    本次实验文本处理后格式为:

    __label__0 379 3 2 322 75 19
    __label__0 1284 134 811 546 2508 57 20 48 233 20 43 17 2 20 47 173 1284 134
    __label__1 116 29 812 139 79 4
    __label__1 21 281 79 68
    __label__0 49 32
    

    实现代码如下所示:

    def get_tokenizer_data(data):
        '''
            fasttext传入文本必须对其进行预处理和编码
        '''
        tokenizer = Tokenizer(num_words=None)
        # 得到文本的字典
        tokenizer.fit_on_texts(data)
        # 将每个string的每个词转成数字
        data = tokenizer.texts_to_sequences(data)
        return data
    
    # 划分数据集
    X_train, X_test, y_train, y_test = train_test_split(data, 
                                                        labels,
                                                        test_size = 0.2,
                                                        random_state=33)
    # 在标签值前增加前缀
    label_train = [('__label__' + i).replace('\n', '') for i in y_train]
    # 向量化文本
    tokenizer_train = get_tokenizer_data(X_train)
    # 将label列与文本列合并为一行
    train = [i + ' ' + str(j).replace('[', '').replace(']', '').replace(',', '') for i, j in zip(label_train, tokenizer_train)]
    
    • 最后使用fasttext训练文本并预测
    def fast_text_model(X_test):
        '''
            使用fasttext进行文本分类
        '''
        # 分类训练
        classifier = ff.train_supervised('E:/task6/train.txt', label='__label__')
        # 模型预测,返回预测标签和概率
        label, prob = classifier.predict(X_test)
        print(label)
        print(prob)
        # 根据给定数据集对模型进行评价,返回样本个数、准确率、召回率
        result = classifier.test('E:/task6/test.txt')
        print(result)
        return label, prob, result
    

    补充:用gensim.model.fasttext获取词向量

    from gensim.models.fasttext import FastText
    FASTEXT_SIZE = 100
    
    
    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
        # 获取词向量词典
        word_voc_dict = fasttext_model.wv.vocab
        word_voc_list = fasttext_model.wv.index2word
        # 获取词向量列表
        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 word_voc_dict, word_voc_list, wordEmbedding
    

    完整代码+数据集见github

    相关文章

      网友评论

          本文标题:Task6 神经网络基础

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