R机器学习:神经网络算法的理解与实操,实例解析
神经网络算法是一种模仿生物神经网络(尤其是人脑)结构和功能的算法。它由大量相互连接的节点(称为神经元)组成,这些神经元组织成层,通过传递信号来处理信息。神经网络算法在机器学习、人工智能等领域中扮演着至关重要的角色,尤其擅长处理复杂的模式识别、分类和预测问题。今天给大家介绍下这个算法。
回忆一下高中生物知识,高中的时候我们学过生物神经元:
生物神经元通过树突接收信号,通过轴突发送信号。神经元之间通过突触连接,信号的强弱由突触的“强度”控制。在人工神经网络中,人工神经元模拟了生物神经元的工作原理。它也接收多个输入,每个输入与一个权重相乘,最后通过激活函数生成输出。
整个过程其实是类似的:在生物神经元中,信号由树突接收,经过突触传递到下一个神经元。而在人工神经元中,输入信号经过加权和激活函数后生成输出信号,类似地传递到下一层神经元,类比如图示:
神经网络的基本组成包括:
- 神经元(Neuron): 神经网络的基本单元,也称为节点。每个神经元接收来自其他神经元的输入信号,通过加权求和并应用激活函数进行处理,然后将输出信号传递给其他神经元。
- 连接(Connection): 神经元之间的连接,每个连接都有一个权重(Weight),表示连接的强度。权重决定了输入信号对输出信号的影响程度。
- 层(Layer): 神经元按层组织,常见的层包括: 输入层(Input Layer): 接收外部输入信号。 隐藏层(Hidden Layer): 位于输入层和输出层之间,负责对输入信号进行复杂的处理。一个神经网络可以有多个隐藏层,构成深度神经网络。 输出层(Output Layer): 输出最终的计算结果。
- 激活函数(Activation Function): 应用于神经元输出的函数,引入非线性特性,使神经网络能够处理非线性问题。常用的激活函数包括 Sigmoid、ReLU、Tanh 等。
神经网络层的图示如下:
就是这么个意思,大家千万不要被神经网络这么高级的名词吓到,其实基本构成还是很简单的。
神经网络的工作原理:
我们依然先来回忆一下生物大脑的学习:大脑通过突触可塑性学习和调整神经元之间的连接强度。通过反复的学习和经验积累,突触的强度会发生变化,从而影响信息的处理方式。
神经网络的学习(反向传播)也是这样:神经网络的学习过程就是通过反向传播算法来调整神经元之间的权重。神经网络会根据预测结果和实际结果之间的误差,调整连接权重,以减少预测误差。
类比解释一下就是:在大脑中,学习是通过调整突触强度来改变神经元之间的连接。在神经网络中,学习是通过调整权重来优化模型的输出。这个权重调整的过程就是训练的过程,调整的过程也涉及到一些优化算法比如梯度下降,但是你都不需要去记,你只需要记住神经网络就是输入数据:数据从输入层进入网络,网络又可分为好几层。输入的时候每个输入有一个“权重”(类似重要性)和一个“偏置”(调整值)。然后通过激活函数对计算结果应用一个数学函数,让输出更灵活,比如让它可以表示“非线性关系”。最后输出结果:经过层层计算,得到预测结果。
神经网络通过以下两个主要过程进行工作:
- 前向传播(Forward Propagation): 输入信号从输入层开始,逐层传递到隐藏层,最终到达输出层。在每个神经元中,输入信号与连接权重相乘并求和,然后应用激活函数得到输出。
- 反向传播(Backpropagation): 将输出结果与实际值之间的误差反向传播回网络,根据误差调整连接权重,使网络的输出更接近实际值。这个过程通常使用梯度下降等优化算法。
神经网络又可以可以分为多种类型,常见的包括:
- 前馈神经网络(Feedforward Neural Network): 信息单向传递,没有循环或反馈连接。常用于分类和回归问题。
- 循环神经网络(Recurrent Neural Network,RNN): 具有循环连接,可以处理序列数据,例如文本、语音等。
- 卷积神经网络(Convolutional Neural Network,CNN): 专门用于处理图像和视频等具有空间结构的数据。
- 自编码器(Autoencoder): 用于数据降维、特征提取等。
- 生成对抗网络(Generative Adversarial Network,GAN): 用于生成新的数据样本。
实操演示
我们依然是用iris数据集来做一个简单的神经网络分类模型,先用neuralnet 包来做,具体代码如下:
model <- neuralnet(Species ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width,
data = iris,
hidden = c(5), # 隐藏层的神经元数量
linear.output = FALSE) # 因为这是分类任务,不需要线性输出
summary(model)
plot(model)
上面代码中需要注意hidden (hidden = c(5))这个参数:
- hidden指定隐藏层的结构。可以通过调整这个参数来控制模型的复杂度,增加隐藏层数量或神经元数量。c(5)表示网络有一个隐藏层,且该层包含5个神经元,输出如下:
图中每条箭头线上标注的数字就是连接权重,表示输入信号对目标神经元的影响大小。例如,从Petal.Width到某隐藏层神经元的一条箭头上标注的数字4.93165,表示Petal.Width的输入被放大了4.93165倍后传递到该隐藏层神经元。
每个隐藏层神经元和输出层神经元都有一个偏置节点(图中顶部标记为1的圆圈)。偏置项通过权重(蓝色箭头上的数字)调节网络的输出,从而增加模型的灵活性。
随意瞅一下该模型分类的准确性哦。只能说真牛,是比前两篇文章中介绍的算法都牛的哦:
nnet 包也可以用来做神经网络分析,但是只能做单层神经网络,有局限性,代码如下:结果就不贴出来了:
library(nnet)
# 训练一个包含一个隐藏层的多层感知器
nn <- nnet(iris[, 1:4], class.ind(iris$Species), size = 3, softmax = TRUE)
predictions <- predict(nn, iris[, 1:4], type = "class")
table(predictions, iris$Species)
plotnet(nn)
运行代码后也可以出图,但这个图有点呆哦,不太好看的样子:
神经网络的可视化
再单开一块给大家介绍下模型可视化的技巧,对于neuralnet生成的神经网络模型我们可以用plot.neuralnet函数来出图,有很多的参数可以调节,例如我想将输入节点颜色设置为蓝色,隐藏层节点颜色设置为绿色,输出层节点颜色设置为红色,字体大小调整为10我就可以写出如下代码:
plot(nn_model,
rep = "best", # 显示最佳模型
col.entry = "blue",# 输入节点颜色
col.hidden = "green", # 隐藏层节点颜色
col.out = "red", # 输出层节点颜色
show.weights = TRUE, # 显示权重值
fontsize = 10) # 调整字体大小
运行代码后输出如下,其余的参数也都可以调整试试:
同样的我们用nnet包做出模型后也可以使用plotnet函数输出模型图,也有很多可以调整的参数,circle_col 参数设置输入层和其余层的节点颜色。circle_cex 控制节点的大小, cex_text 和 cex_val 设置节点标签和权重文字的字体大小,比如我想让输入层为蓝色,其余层为绿色,并且设置文字和节点圈圈的大小我就可以写出如下代码:
plotnet(nn,
alpha = 0.8,
circle_col = list("blue", "red"),
circle_cex = 3,
cex_text = 1,
cex_val = 0.6,
# pos_col = "darkgreen",
# neg_col = "red",
max_sp = F)
运行后输出如下,大家也可自己调整参数看看哦: