监督式学习:在监督式学习下,输入数据被称为“训练数据”,每组训练数据有一个明确的标识或结果,如对防垃圾邮件系统中“垃圾邮件”“非垃圾邮件”,对手写数字识别中的“1“,”2“,”3“,”4“等。在建立预测模型的时候,监督式学习建立一个学习过程,将预测结果与“训练数据”的实际结果进行比较,不断的调整预测模型,直到模型的预测结果达到一个预期的准确率。监督式学习的常见应用场景如分类问题和回归问题。常见算法有逻辑回归(Logistic Regression)和反向传递神经网络(Back Propagation Neural Network)
非监督式学习:在非监督式学习中,数据并不被特别标识,学习模型是为了推断出数据的一些内在结构。常见的应用场景包括关联规则的学习以及聚类等。常见算法包括Apriori算法以及k-Means算法。
半监督式学习:在此学习方式下,输入数据部分被标识,部分没有被标识,这种学习模型可以用来进行预测,但是模型首先需要学习数据的内在结构以便合理的组织数据来进行预测。应用场景包括分类和回归,算法包括一些对常用监督式学习算法的延伸,这些算法首先试图对未标识数据进行建模,在此基础上再对标识的数据进行预测。如图论推理算法(Graph Inference)或者拉普拉斯支持向量机(Laplacian SVM.)等。
二、神级网络简介
一个计算模型,要划分为神经网络,通常需要大量彼此连接的节点 (也称 ‘神经元’),并且具备两个特性:每个神经元,通过某种特定的输出函数 (也叫激励函数 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)
inputs <- snnsDataeight16.pat[,inputColumns(snnsDataeight_016.pat)]
outputs <- snnsDataeight16.pat[,outputColumns(snnsDataeight_016.pat)]
par(mfrow=c(1,2))
modelElman <- elman(inputs, outputs, size=8, learnFuncParams=c(0.1), maxit=1000)
modelElman
modelJordan <- jordan(inputs, outputs, size=8, learnFuncParams=c(0.1), maxit=1000)
modelJordan
plotIterativeError(modelElman)
plotIterativeError(modelJordan)
summary(modelElman)
summary(modelJordan)
linout = FALSE, entropy = FALSE, softmax = FALSE,
censored = FALSE, skip = FALSE, rang = 0.7, decay = 0,
maxit = 100, Hess = FALSE, trace = TRUE, MaxNWts = 1000,
abstol = 1.0e-4, reltol = 1.0e-8, ...)
algae <- algae[-manyNAs(algae), ] #去除无效值(包含多个无效值的行数据)
norm.data <- scale(clean.algae[,4:12])
#使用nnet命令,参数规定隐层单元个数为10,权重调整速度为0.1,最大迭代次数为1000次,线性输入。
nn <- nnet(a1~., norm.data, size = 10, decay = 0.01,
maxit = 1000, linout = T, trace = F)
#利用模型进行预测
norm.preds <- predict(nn, norm.data)
#绘制预测值与真实值之间的散点图
plot(norm.preds~ scale(clean.algae$a1))
(nmse2 <- mean((norm.preds-scale(clean.algae$a1))^2)/
mean((mean( scale(clean.algae$a1))- scale(clean.algae$a1))^2))
再来看看处理分类数据的表现,利用iris数据来判断花的种类
model.nnet <-nnet(Species ~ ., linout = F,size = 10, decay = 0.01,
maxit = 1000,trace = F,data = iris)
#对分类数据预测需要加上type参数
pre.forest=predict(model.nnet, iris,type='class')
table(pre.forest,iris$Species)
支持向量机SVM是九十年代中期发展起来的新的机器学习技术,与传统的神经网络NN技术不同,SVM是以统计学习理论SLT为基础,NN是以传统统计学理论为基础。传统统计学的前提条件是要有足够多的样本,而统计学习理论是着重研究小样本条件下的统计规律和学习方法的,它为机器学习问题建立了一个很好的理论框架。
library(e1071)
model.svm <- svm(a1~., norm.data)
preds <- predict(model.svm, norm.data)
plot(preds~ scale(clean.algae$a1))
model.svm <-svm(Species ~ .,data = iris)
pre=predict(model.svm, iris,type='class')
table(pre,iris$Species)
library(earth)
model.mars <- earth(a1~., clean.algae)
preds <- predict(model.mars, clean.algae)
plot(preds~ clean.algae$a1)
(nmse2 <- mean((preds-clean.algae$a1)^2)/
mean((mean( clean.algae$a1)- clean.algae$a1)^2))
model.mars <-earth(Species ~ .,data = iris)
pre=predict(model.mars, iris,type='class')
table(pre,iris$Species)
net为神经网络训练;
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)