# 多层感知机概述 ## 生活中的神经网络 ![使用多层感知机进行文档分类-图1](picture/使用多层感知机进行文档分类-图1.png) 人的大脑是由无数的神经元组成的复杂网络。神经元是具有长突起的细胞,它由细胞体和轴突、树突组成。 ![使用多层感知机进行文档分类-图2](picture/使用多层感知机进行文档分类-图2.png) 每个神经元可以有一或多个树突,可以接受刺激并将兴奋传入细胞体。每个神经元只有一个轴突,可以把兴奋从胞体传送到另一个神经元或其他组织,如肌肉或腺体。 ![使用多层感知机进行文档分类-图3](picture/使用多层感知机进行文档分类-图3.png) ## 神经网络算法概述 神经网络算法就是模拟了人体神经元的工作原理,多个输入参数,分别具有各自的权重,经过激励函数的处理后,得到输出。输出可以再对接下一级的神经网络的输入,从而组成更加复杂的神经网络。 ![使用多层感知机进行文档分类-图4](picture/使用多层感知机进行文档分类-图4.png) 大脑里的生物神经细胞和其他的神经细胞是相互连接在一起的。为了创建一个人工神经网络,人工神经细胞也要以同样方式相互连接在一起。为此可以有许多不同的连接方式,其中最容易理解并且也是最广泛地使用的,就是把神经细胞一层一层地连结在一起。这一种类型的神经网络就叫前馈网络。 ![使用多层感知机进行文档分类-图5](picture/使用多层感知机进行文档分类-图5.png) 如果对预测错误的神经元施加惩罚,从输出层开始层层向上查找预测错误的神经元,微调这些神经元对应的权重,达到修复错误的目的,这样的算法就叫做反向传播算法。Scikit-learn中的神经网络实现都是使用反向传播算法。本文重点介绍算法在安全领域的应用,神经网络的公式推导请参考其他机器学习专业书籍。本书介绍的是神经网络中最简单的一种形式,即多层感知机。 # 数据集 数据集依然使用搜狗实验室提供的"搜狐新闻数据",该数据来自搜狐新闻2012年6月—7月期间国内,国际,体育,社会,娱乐等18个频道的新闻数据,提供URL和正文信息。 对应的网址为: http://www.sogou.com/labs/resource/cs.php 我们选择其中数量最大的三个频道的数据进行分析,数据清洗过程请参考我之前的文章《使用fasttext进行文档分类》 # 特征提取 ## 词袋&TFIDF 特征提取的方式采用词袋结合TFIDF的方式。 #切割词袋 vectorizer = CountVectorizer() # 该类会统计每个词语的tf-idf权值 transformer = TfidfTransformer() x = transformer.fit_transform(vectorizer.fit_transform(x)) ## n-gram&TFIDF 特征提取还可以使用词袋模型的加强版n-gram,比如最常见的2-gram,这样可以更好的提取单词前后之间的关系。 #切割词袋 vectorizer = CountVectorizer(ngram_range=(2,2)) # 该类会统计每个词语的tf-idf权值 transformer = TfidfTransformer() x = transformer.fit_transform(vectorizer.fit_transform(x)) ## one-hot编码 由于这次需要区分的标签一共有三种,不能直接使用过去二分类问题的方式进行处理了。针对多分类问题,需要使用one-hot编码处理标签。所谓的one-hot编码,又称为一位有效编码,主要是采用位状态寄存器来对个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。比如我们有三类标签,就可以编码为: [1,0,0] [0,1,0] [0,0,1] 在keras中可以非常方便的进行转换。 #转换成one hot编码 y=to_categorical(t, num_classes=3) # 训练与效果验证 在scikit-learn中构造多层感知机的分类器非常方便,通常只需要设计神经网络的结构即可。本例中设计的隐藏层有两层,结点数分为为5和3,通常最后一层的结点数与标签类型数相同。 #mlp clf = MLPClassifier(solver='lbfgs', alpha=1e-5, hidden_layer_sizes=(5, 3), random_state=1) 其中比较重要的几个参数的含义为: - hidden_layer_sizes,表示隐藏层的结构 - activation,激活函数,{‘identity’, ‘logistic’, ‘tanh’, ‘relu’}, 默认relu - solver,优化方式,{‘lbfgs’, ‘sgd’, ‘adam’}, 默认adam。lbfgs使用quasi-Newton方法的优化器,sgd使用随机梯度下降,adam也是一种随机梯度的优化器 - alpha,可选的,默认0.0001,正则化项参数 效果验证使用5折交叉验证,考核的指标是f1和accuracy。使用cross_val_score函数可以非常方便的实现交叉验证的功能,其中cv参数指定交叉验证的方式,比如5代表5折交叉验证。 scores = cross_val_score(clf, x, y, cv = 5,scoring='f1_micro') print("f1: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2)) scores = cross_val_score(clf, x, y, cv = 5,scoring='accuracy') print("accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2)) 这里需要特别说明的是,在二分类问题中,我们考核f1即可,但是在多分类问题中,f1以微平均和宏平均两个指标的形式存在,分别为f1\_micro和f1\_macro。f1\_micro对数据集中的每一个实例不分类别进行统计建立全局混淆矩阵,然后计算相应指标。f1\_macro是先对每一个类统计指标值,然后在对所有类求算术平均值。通常使用其中任何一个即可。 运行程序,当使用词袋&TFIDF模型时,效果如下: f1: 0.98 (+/- 0.04) accuracy: 0.97 (+/- 0.05) 当使用n-gram&TFIDF模型的效果,有兴趣的读者可以自行验证。