Task6 神经网络基础

任务

  • 前馈神经网络、网络层数、输入层、隐藏层、输出层、隐藏单元、激活函数的概念。
  • 感知机相关;定义简单的几层网络(激活函数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)之间,其公式以及函数图如下所示:


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

tanh函数

  • 该函数数将取值为(−∞,+∞) 的数映射到(-1,1)之间,其公式以及函数图如下所示:


    tanh函数的均值为0,弥补了sigmoid函数均值为0.5的缺点
    tanh函数的求导推导为:
    • tanh与sigmoid存在相同的问题,当值很大或者很小的时候会出现梯度消失的问题

ReLU函数

  • ReLU函数又称为修正线性单元, 是一种分段线性函数,其弥补了sigmoid函数以及tanh函数的梯度消失问题。ReLU函数的公式以及图形如下:


    ReLU函数求导为:
  • 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 神经网络基础)