本教程参考《RDeepLearningEssential》

这一篇我们通过实践来进行神经网络的学习,预测和分类等

2.1 R语言神经网络-nnet

我们先进行浅层神经网络的学习,使用nnet包和RSNNS包,我们通过caret包来调用nnet包。caret包是‘Classification and Regression Training’的缩写。我们第一个例子也是基本所有深度学习都会进行的第一个例子:手写字体识别

2.1.1神经网络构建(多层感知器模型)-最简单尝试

我们从kaggle中读取数据:Digit Recognizer | Kaggle

数据包括训练数据和测试数据,这是是标准的数据形式,因为就像我们上学的时候平时做练习感觉自己学会了,这么检验呢,就是去考试检验一下,这个考试的卷子就是测试数据。

dig_train <- read.csv("C:\\Users\\Huzhuocheng\\Desktop\\digit-recognizer\\train.csv")
dim(dig_train) #数据维度查看
head(colnames((dig_train), 5)) #查看前五个列名
tail(colnames((dig_train),5)) #查看后五个列名
head(dig_train[, 1:5])

我们可以理解第一列是我们方程的Y,也就是靶,而后面的几列是我们的x,有700多个x,解方程用手解应该是不太显示,所以我们才有机器学习和深度学习,因为方程用手解可能解不出确切值,这个我们叫没有数值解,但是计算机可能解出来近似解,这个解可以通过算法优化得到最优解,一句话:人工智能得出的是最接近的答案! 

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_深度学习

 第二步,我们要把标签(第一列)转换为因子,这样它就不会作为纯粹的Y的数值,你懂数字1和‘数字1’的区别,就能理解这个操作,并且我们选择其中的6000个数据进行练习。我们再检查一下数据的真实分布(也就是正确的Y的分布)

dig_train$label <- factor(dig_train$label, levels = 0:9)
i <- 1:6000
dig_X <- dig_train[i, -1]
dig_Y <- dig_train[i, 1]
barplot(table(dig_Y))

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_数据_02

接下来我们正式开始使用神经网络:

这里我们设置隐藏层为5的神经网络,并且设置正则化值为0.1(也就是惩罚值,这个我觉得我在以后出的机器学习教程里会更详细的论述,你可以先理解为防止训练过拟合,也就是只会刷题不会考试了)我们训练完可以看一下我们预测的分布:

在神经网络的训练中,maxit参数控制了反向传播算法的最大迭代次数。将其设置为100次迭代,主要是为了在模型训练的过程中提供一个停止条件,以确保模型能够在合理的计算时间内完成训练。反向传播算法是神经网络的核心学习规则之一,它通过计算损失函数关于模型参数的梯度,然后根据一定的优化策略(如梯度下降)来更新模型参数,以期最小化损失函数。在这个过程中,迭代次数起到了至关重要的作用。

迭代次数决定了模型训练的深度。理论上,如果迭代次数足够多,模型能够更精细地调整其参数以适应训练数据。但是,随着迭代次数的增加,模型训练的时间也会相应增长,而且在某些情况下,过多的迭代次数可能会导致模型在训练数据上过拟合,反而降低了模型在新数据上的泛化能力。

library('caret')
set.seed(1234)
dig_m1 <- train(x = dig_X, y = dig_Y,
                method = 'nnet',
                tuneGrid = expand.grid(
                  .size = c(5),
                  .decay = 0.1),
                trControl = trainControl(method = "none"),
                MaxNWts = 10000,
                maxit = 100
                )

dig_Yhat1 <- predict(dig_m1)  #预测值
barplot(table(dig_Yhat1))

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_深度学习_03

预测出来是一坨,因为我特意将一些参数改的比较小,这个不是一个非常好的神经网络。

 2.1.2 模型训练预测的评价

我们不能总是通过可视化分布来看模型的效果,而是应该通过数学指标,我们通过阳性预测和阴性预测来实现对于灵敏度和特异度的计算:

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_r语言_04

 比如数字‘1’的灵敏度如果为80%,则表示80%的0被正确预测,而如果数字‘1’的特异度为75%,则表示75%的被预测为非数字‘1’的数字不是数字‘1’,当然我觉得特异度是更为重要的指标,因为认错人比没认出来更为严重,我们使用R语言计算一下这些指标:

cm <- caret::confusionMatrix(xtabs(~dig_Yhat1 + dig_Y))
# 可视化混淆矩阵
plot(cm$table, main = "Confusion Matrix", col = cm$byClass, las = 1)

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_深度学习_05

 通过这个结果我们可以看到每个数字的识别情况,主要是关注前两个,也就是灵敏度和特异度

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_深度学习_06

 2.1.3 模型优化

我们增加网络的节点数目和最大权重来进行第一次优化,你会发现你的运行速度明显变慢了

#第一次优化
set.seed(1234)
dig_m2 <- train(x = dig_X, y = dig_Y,
                method = 'nnet',
                tuneGrid = expand.grid(
                  .size = c(10),
                  .decay = 0.1),
                trControl = trainControl(method = "none"),
                MaxNWts = 50000,
                maxit = 100
)
dig_Yhat2 <- predict(dig_m2)  #预测值
barplot(table(dig_Yhat2))


cm2 <- caret::confusionMatrix(xtabs(~dig_Yhat2 + dig_Y))

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_深度学习_07

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_数据_08

这次我们的分布和各种参数有了明显的好转,不过说实话总体的准确率没有超过70%,相当于还是在抛硬币,是不可以被接受的。我们进行下一次优化:

#第二次优化
set.seed(1234)
dig_m3 <- train(x = dig_X, y = dig_Y,
                method = 'nnet',
                tuneGrid = expand.grid(
                  .size = c(45),
                  .decay = 0.1),
                trControl = trainControl(method = "none"),
                MaxNWts = 50000,
                maxit = 100
)
dig_Yhat3 <- predict(dig_m3)  #预测值
barplot(table(dig_Yhat3))


cm3 <- caret::confusionMatrix(xtabs(~dig_Yhat3 + dig_Y))
cm3

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_深度学习_09

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_数据_10

 经过漫长的等待,我们的预测结果已经非常好了,整体的预测率到达了0.86!当然如果还需要更好的结果可以进一步优化节点及惩罚值的大小。

2.2R语言神经网络-SNNS

我们使用斯图加特神经网络仿真器(Stuttgart Neural Network Simulator)来进行训练,它的有点在于更加灵活且可以训练更多神经网络架构,包括循环神经网络及更广泛的学习函数。

install.packages('RSNNS')
library("RSNNS") 
head(decodeClassLabels(dig_Y))
set.seed(1234)
dig_m4 <- mlp(as.matrix(dig_X),
              decodeClassLabels(dig_Y),
              size = 40,
              learnFunc = 'Rprop',
              shufflePatterns = F,
              maxit = 60)
dig_Yhat4 <- fitted.values(dig_m4)
dig_Yhat4 <- encodeClassLabels(dig_Yhat4)
barplot(table(dig_Yhat4))

caret::confusionMatrix(xtabs(~ I(dig_Yhat4 - 1) + dig_Y))

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_数据_11

r语言logistic 亚组 分析 森林图绘制 r语言ar1模型预测_人工智能_12

 预测效果也不错的0.86。

2.3 生成预测

我们对于分类的可能性不可能同等地位去审视,就像体检,说有30%可能性近视和有30%概率患癌症,这完全是不一样的。我们可以给一个阈值,我们可以展示一下样本内数据的原始概率及对预测值的影响:

dig_Yhat4_insample <- fitted.values(dig_m4)
head(round(dig_Yhat4_insample, 2))

table(encodeClassLabels(dig_Yhat4_insample,
                        method = "WTA", h = .5))

(1)method = "WTA": 这里指定了编码类别标签的方法为"WTA",即Winner-Takes-All。这是一种常见的策略,用于解决多标签分类问题,其中一个实例可以同时属于多个类别。在这种方法中,只有得分最高的类别会被选中作为该实例的标签。
(2)h = .5: 这个参数可能控制着WTA方法的某种阈值或者决策边界。h可被用来确定何时一个类别足够强以至于被认为是“赢家”。数值.5表示比如当某个类别的预测概率超过0.5时,它就被认为是获胜者。

我们可以使用predict()来生成预测值。

i2 <- 5001:10000
dig_yha4_pred <- predict(dig_m4,
                         as.matrix(dig_train[i2, -1])
                         )
table(encodeClassLabels(dig_yha4_pred,
                        method = 'WTA', h=0))

 2.4浅浅分析结果-过拟合问题

过拟合是什么呢,就是一个人他平时学习学的太猛了,习题做的太会了,导致考试反而不会了。

我们的样本内准确度87%,之前拟合的是83%,所以我们过拟合了4%。

caret::confusionMatrix(xtabs(~dig_train[i2, 1] +
                               I(encodeClassLabels(dig_yha4_pred) -1)))

 2.5小结

通过这次的学习,你应该已经能自己使用神经网络进行浅层预测了,我们下次使用一个例子来更深入的理解神经网络。