88-R单神经元神经网络手动实现
2020-10-19 本文已影响0人
wonphen
> library(pacman)
> p_load(dplyr)
1、生成虚拟数据
> set.seed(123)
> x1 <- runif(200, 0, 10)
>
> set.seed(456)
> x2 <- runif(200, 0, 10)
>
> y <- sign(-0.89 + 2.07 * x1 - 3.09 * x2)
>
> dat <- tibble(y = y, x1 = x1, x2 = x2)
>
> str(dat)
## tibble [200 × 3] (S3: tbl_df/tbl/data.frame)
## $ y : num [1:200] 1 1 -1 -1 -1 -1 1 1 1 -1 ...
## $ x1: num [1:200] 2.88 7.88 4.09 8.83 9.4 ...
## $ x2: num [1:200] 0.896 2.105 7.33 8.521 7.884 ...
2、构造算法
> # 如果小于0返回-1,大于0返回1
> step_fun <- function(x) {
+ x = ifelse(x < 0, -1, 1)
+ return(x)
+ }
>
> pocket_perceptron <- function(dat, learning_rate, max_iter) {
+ # 行数
+ n = nrow(dat)
+ # 特征数等于总列数减去因变量
+ n_fea = ncol(dat) - 1
+ # 初始化权重
+ w = rnorm(n_fea + 1, 0, 2)
+ # 当前迭代次数初始值
+ current_iter = 0
+ # 是否收敛初始值
+ has_converged = F
+ # 最佳权重值设为当前初始值
+ best_w = w
+ # 初始最佳错误数为最坏情况,所有都错
+ best_err = n
+ # 只要算法还没收敛并且没有达到最大迭代次数,就开始一次循环
+ while((has_converged == F) & (current_iter < max_iter)) {
+ # 将收敛设置为TRUE
+ has_converged = T
+ # 当前错误数为0
+ current_err = 0
+ # 对输入数据框所有行循环
+ for(i in 1:n) {
+ # 添加x0为1
+ xi = unlist(cbind(x0 = 1, dat[i, -1]))
+ yi = dat$y[i]
+ # 计算y的预测值
+ yhat = step_fun(sum(w * xi))
+ # 如果因变量y的实际值不等于预测值
+ if(yi != yhat) {
+ # 更新迭代次数 + 1
+ current_iter = current_iter + 1
+ # 更新是否收敛为FALSE,此时会继续循环
+ has_converged = F
+ # 更新权重值
+ w = w + learning_rate * sign(yi - yhat) * xi
+ }
+ }
+ # 如果当前错误数比最佳错误数更低
+ if(current_err < best_err) {
+ # 设置当前错误数为最佳错误数
+ best_err = current_err
+ # 设置当前权重为最佳权重
+ best_w = w
+ }
+ # 更新当前迭代次数 + 1
+ current_iter = current_iter + 1
+ }
+ # 返回模型信息,权重、是否收敛和迭代次数
+ model = list("weight" = best_w, "converged" = has_converged,
+ "iterations" = current_iter)
+ return(model)
+ }
3、验证
输入数据框、学习率和最大迭代次数。
> pocket_perceptron(dat, 0.1, 1000)
## $weight
## x0 x1 x2
## -0.1636973 0.9394905 -2.7558517
##
## $converged
## [1] TRUE
##
## $iterations
## [1] 347
模型在347次迭代后收敛。