二、神级网络简介
一个计算模型,要划分为神经网络,通常需要大量彼此连接的节点 (也称 ‘神经元’),并且具备两个特性:每个神经元,通过某种特定的输出函数 (也叫激励函数 activation function),计算处理来自其它相邻神经元的加权输入值;
神经元之间的信息传递的强度,用所谓加权值来定义,算法会不断自我学习,调整这个加权值。在此基础上,神经网络的计算模型,依靠大量的数据来训练,还需要:
成本函数 (cost function):用来定量评估根据特定输入值,计算出来的输出结果,离正确值有多远,结果有多靠;
学习的算法 ( learning algorithm ):这是根据成本函数的结果,自学,纠错,最快地找到神经元之间最优化的加权值;
iris = iris[sample(1:nrow(iris),length(1:nrow(iris))),1:ncol(iris)]
irisValues= iris[,1:4]
irisTargets = decodeClassLabels(iris[,5])
iris = splitForTrainingAndTest(irisValues, irisTargets, ratio=0.15)
iris = normTrainingAndTestSet(iris)
model = mlp(iris$inputsTrain, iris$targetsTrain, size=5, learnFunc="Quickprop", learnFuncParams=c(0.1, 2.0, 0.0001, 0.1),maxit=100, inputsTest=iris$inputsTest, targetsTest=iris$targetsTest)
predictions = predict(model,iris$inputsTest)
confusionMatrix(iris$targetsTest,predictions)
install.packages("AMORE")
library(AMORE) #生成输入数据 P <- matrix(sample(seq(-1,1,length=1000), 1000, replace=FALSE), ncol=1) #生成输出数据 target <- P^2 #生成2个隐藏层的神经网络结构, net <- newff(n.neurons=c(1,3,2,1), learning.rate.global=1e-2, momentum.global=0.5, error.criterium="LMS", Stao=NA, hidden.layer="tansig",output.layer="purelin", method="ADAPTgdwm") # n.neurons=c(输入节点个数,……中间节点,输出节点个数), # error.criterium="LMS"判断收敛的依据,最小平均平方法, #hidden.layer="tansig"隐藏层的激活函数, #output.layer="purelin"输出层的激活函数
result <- train(net, P, target, error.criterium="LMS", report=TRUE, show.step=100, n.shows=5 ) #对待测集进行预测 y<-sim(result$net,P) plot(P,y, col="blue", pch="+") points(P,target, col="red", pch="x")
(四)Neuralnet包
neuralnet(formula, data, hidden)函数:神经网络训练函数。
hidden一个向量的整数,指定在每一层中的隐层神经元(顶点)的数目。
hidden=c(3)表示第一个隐藏层的3个隐藏单元;
hidden=c(3, 2)分别表示第一、第二隐藏层的3个和2个隐藏单元。
compute(x, covariate):神经网络计算一个给定的变量向量。
x为NN的模型;
covariate用来训练神经网络的数据框或矩阵。相当于predict函数(neuralnet中无predict函数)
案例一、 1、准备数据(MASS package中的 Boston dataset ) 目标:Our goal is to predict the median value of owner-occupied homes (medv) using all the other continuous variables available. set.seed(500) library(MASS) data <- Boston 检查是否存在缺失值 apply(data,2,function(x) sum(is.na(x))) 结果显示不存在缺失值
将数据随机分成训练集和测试集,我们先通过多元线性回归的方法来预测,采用函数gml() ,以便对比神经网络和线性回归的方法差距。 index <- sample(1:nrow(data),round(0.75*nrow(data))) train <- data[index,] test <- data[-index,]
lm.fit <- glm(medv~., data=train) summary(lm.fit) pr.lm <- predict(lm.fit,test) MSE.lm <- sum((pr.lm - test$medv)^2)/nrow(test) #多元线性回归的均方误差 2、神经网络数据前期处理 1)数据处理: 在训练神经网络时最好先对数据进行标准化,强调一点标准化数据很重要。可以通过不同的方法对数据进行标准化(z-normalization, min-max scale, etc…),这里采用min-max scale方法,将数据映射到[0,1]区间。 maxs <- apply(data, 2, max)
mins <- apply(data, 2, min)
scaled <- as.data.frame(scale(data, center = mins, scale = maxs - mins)) #scale函数返回的是一个矩阵,而我们需要将其转换成一个数据框格式,以便后面的数据处理。
train_ <- scaled[index,] test_ <- scaled[-index,]
2)参数选择:
对于隐藏层和节点数的确定没有一个确定的规则。通常来说,一个隐藏层对大部分神经网络已经足够了。一般来说隐藏层数一般介于输入层和输出层之间,通常为输入层的2/3.在本例中我们采用双层隐藏层,分别为5、3个节点数,因此神经网络的结构为13:5:3:1。
3)神经网络训练
library(neuralnet)
n <- names(train_)
f <- as.formula(paste("medv ~", paste(n[!n %in% "medv"], collapse = " + "))) #神经网络回归公式的生成
nn <- neuralnet(f,data=train_,hidden=c(5,3),linear.output=T)
注意:
对于公式 y~.
的形式在neuralnet() 函数中是不被接受的,你必须将整个回归公式写出来;
hidden 参数允许通过一个向量确定每个隐藏层的节点数;
linear.output=TRUE 表明做的是一般的回归,linear.output=FALSE表明做的是分类回归。
plot(nn) #画出神经网络图
4)神经网络预测 pr.nn <- compute(nn,test_[,1:13]) pr.nn_ <- pr.nn$net.result*(max(data$medv)-min(data$medv))+min(data$medv) test.r <- (test_$medv)*(max(data$medv)-min(data$medv))+min(data$medv) MSE.nn <- sum((test.r - pr.nn_)^2)/nrow(test_) print(paste(MSE.lm,MSE.nn)) #对比两种回归方式的误差 通过图表来表示对比两种方式下的误差 par(mfrow=c(1,2)) plot(test$medv,pr.nn_,col='red',main='Real vs predicted NN',pch=18,cex=0.7) abline(0,1,lwd=2) legend('bottomright',legend='NN',pch=18,col='red', bty='n')
plot(test$medv,pr.lm,col='blue',main='Real vs predicted lm',pch=18, cex=0.7) abline(0,1,lwd=2) legend('bottomright',legend='LM',pch=18,col='blue', bty='n', cex=.95)
或者 plot(test$medv,pr.nn_,col='red',main='Real vs predicted NN',pch=18,cex=0.7)
points(test$medv,pr.lm,col='blue',pch=18,cex=0.7) abline(0,1,lwd=2) legend('bottomright',legend=c('NN','LM'),pch=18,col=c('red','blue'))
3、模型交叉验证(A(fast) cross validation) train-test split 1)Do the train-test split 2)Fit the model to the train set 3)Test the model on the test set 4)Calculate the prediction error 5)Repeat the process K times We are going to implement a fast cross validation using a for loop for the neural network and thecv.glm()
function in theboot
package for the linear model. 多元线性回归的交叉验证 library(boot) set.seed(200) lm.fit <- glm(medv~.,data=data) cv.glm(data,lm.fit,K=10)$delta[1]
神经网络的交叉验证
Note that I am splitting the data in this way: 90% train set and 10% test set in a random way for 10 times. I am also initializing a progress bar using the plyr
library because I want to keep an eye on the status of the process since the fitting of the neural network may take a while.
set.seed(450)
cv.error <- NULL
k <- 10
library(plyr)
pbar <- create_progress_bar('text')
pbar$init(k)
for(i in 1:k){
index <- sample(1:nrow(data),round(0.9*nrow(data)))
train.cv <- scaled[index,]
test.cv <- scaled[-index,]
nn <- neuralnet(f,data=train.cv,hidden=c(5,2),linear.output=T)
pr.nn <- compute(nn,test.cv[,1:13])
pr.nn <- pr.nn$net.result*(max(data$medv)-min(data$medv))+min(data$medv)
test.cv.r <- (test.cv$medv)*(max(data$medv)-min(data$medv))+min(data$medv)
cv.error[i] <- sum((test.cv.r - pr.nn)^2)/nrow(test.cv)
pbar$step()
}
计算平均均方误差 mean(cv.error) 可以看出神经网络比多元线性回归的误差要小的多,拟合效果更加好。 boxplot(cv.error,xlab='MSE CV',col='cyan',border='blue',names='CV error (MSE)',main='CV error (MSE) for NN',horizontal=TRUE)
案例二
我们将会模拟一组很简单的数据实现输入和输出,其中,输出的变量是独立分布的随机数,输入的变量则是输出变量的平方。本次试验中,将会训练10个隐藏神经元。 install.packages('neuralnet') library(grid) library(MASS) library(neuralnet) # 构造50个独立分布在0到100之间的随机数 ,然后将他们保存成数据框架(data.frame) traininginput <- as.data.frame(runif(50, min=0, max=100)) trainingoutput <- sqrt(traininginput) # 通过cbind函数将输入和输出向量构造成一个数据,用一些训练数据测试该神经网络 trainingdata <- cbind(traininginput,trainingoutput) colnames(trainingdata) <- c("Input","Output") # 训练10个隐藏神经元的神经网络 net.sqrt <- neuralnet(Output~Input,trainingdata, hidden=10, threshold=0.01) print(net.sqrt) # 绘制神经网络拓扑图 plot(net.sqrt) testdata <- as.data.frame((1:10)^2) net.results <- compute(net.sqrt, testdata) ls(net.results) # 查看结果 print(net.results$net.result) 让结果更直观些 cleanoutput <- cbind(testdata,sqrt(testdata),as.data.frame(net.results$net.result)) colnames(cleanoutput) <- c("Input","Expected Output","Neural Net Output") print(cleanoutput)