1. 理解神经网络
- 生物中的神经网络
- 生物信号(Signal In)传递给神经元,达到一定阈值后,生物会做出反应,即产生Signal Out传递给下一个神经元
- 从生物神经元到人工神经元
- 一个神经元相当于一个多元线性回归方程
激活函数:将神经元的净输入信号转换成单一的输出信号,以便进一
步在网络中传播。
网络拓扑:描述了模型中神经元的数量以及层数和它们连接的方式
训练算法:指定如何设置连接权重,以便抑制或增加神经元在输入信号中的比重 - 激活函数
通常如以下几种激活函数:
阈值函数: - 逻辑函数:
- 其他:
- 网络拓扑层—单层网络
- 网络拓扑层—多层网络
神经网络没有必要深究,开发人员做的就是定义激活函数,然后调用封装好的神经网络算法就可以,而一般采用逻辑回归函数(Sigmoid)作为激活函数
- 神经网络与多元线性回归对比
2. 案例:利用神经网络预测水泥强度
部分数据:
R语言代码:
# 导入数据,把csv文件读到dataframe中
concrete <- read.csv("concrete.csv")
# 定义一个归一化函数
# 归一化:缩放,把每列的数据都放到[0,1]之间
normalize <- function(x){
return ((x - min(x)) / (max(x) - min(x)))
}
归一化之后部分数据:
# 把concrete这个dataframe中的每个向量(表格中的每一列)都调用归一化函数
# 并把结果再报存dataframe,lapply函数默认返回矩阵
concrete_norm <- as.data.frame(lapply(concrete, normalize))
# 把数据分为训练集和测试集,通常比例为7:3或者8:2
concrete_train <- concrete_norm[1:773,]
concrete_test <- concrete_norm[774:1030,]
# 调用神经网络训练方法
concrete_model <- neuralnet(strength ~ cement + slag + ash + water + superplastic + coarseagg + fineagg + age, data=concrete_train)
# 画出训练结果图
plot(concrete_model)
训练结果图如下:
# 测试,传入测试集的1-8列(不包含强度那一列)
model_results <- compute(concrete_model, concrete_test[1:8])
predicted_strength <- model_results$net.result
# 求测试结果和实际结果的相关系数
cor(predicted_strength, concrete_test$strength)
结果:0.8063194089
# 调整了隐藏层节点的个数,可以降低误差,但计算变得更复杂
concrete_model2 <- neuralnet(strength ~ cement + slag + ash + water + superplastic + coarseagg + fineagg + age, data=concrete_train, hidden=5)
plot(concrete_model2)
# 测试,传入测试集的1-8列(不包含强度那一列)
model_results2 <- compute(concrete_model2, concrete_test[1:8])
predicted_strength2 <- model_results2$net.result
# 求测试结果和实际结果的相关系数
cor(predicted_strength2, concrete_test$strength)
结果:0.9342932783,系数变大,说明误差小了
这个案例中对数据进行了归一化,归一化有两个好处:
1)归一化后加快了梯度下降求最优解的速度;
2)归一化有可能提高精度。
概念:过拟合
神经网络的隐藏层足够多(谷歌是5,所以5已经是很大的隐藏层数量),隐藏节点足够多(一般调优会调整隐藏节点的数,而不调整隐藏层的数量)时,计算的结果会符合每一种情况,即代表结果的线会穿过所有的点,但是如果有几个数据是脏数据,本身就不正确,那么结果拟合了这些数据反而使得模型变得不准确,我们把这种拟合了全部数据包括脏数据的现象称为过拟合,神经网络很容易造成过拟合。