第1章 BP神经网络的数据分类——语音特征信号的分类

1.1 案例背景

1.1.1 BP神经网络概述

  BP 神经网络是一种多层前馈神经网络,该网络的主要特点是信号前向传递,误差反向传
播。在前向传递中,输入信号从输入层经隐含层逐层处理,直至输出层. 每一层的神经元状态
只影响下一层神经元状态。如果输出层得不到期望输出,则转入反向传播, 根据预测误差调整
网络权值和阔值,从而使BP 神经网络预测输出不断逼近期望输出。BP 神经网络的拓扑结构
如图1 - 1 所示。


1435099-f45e5e4f9e5c6f87.jpg
图1-1 BP 神经网络拓扑结构图

代码基本完成 还待完善

# 清空环境变量
rm(list = ls())
setwd("C:/Users/Administrator/Desktop/R语言神经网络43个案例分析/chapter1")

# 导入所有语音信号
library(data.table) 
data <- fread("data.txt")
# 王小川的matlab代码里有导入4类语音信号我这里已经合并好放在txt文件里了
data <- as.matrix(data)
# 输入输出数据
input <- data[, -1]
output1 <- data[, 1]

# 设定每组输入输出信号(R语言只需要调用nnet包的class.ind)
library(nnet)
output <- class.ind(output1)

# 输入数据归一化
# matalb的归一化函数可以反归一,目前我只有自己写的这个,所以我先做了
mapminmax <- function(x){ 
  x_max <- max(x)
  x_min <- min(x)
  x <- (x - x_min) / (x_max - x_min)
  return(x)
} # 这个函数有bug的,不能针对常量进行标准化
inputn <- t(apply(input, 2, mapminmax))

# 从中随机抽取1500组(75%)数据作为训练数据,500组数据作为预测数据
n <- sample(nrow(data),0.75*nrow(data))

input_train <- t(input[n, ])
output_train <- t(output[n, ])
input_test <- t(input[-n, ])
output_test <- t(output[-n,])

# 1.3.3 BP 神经周络结椅却始化
# 根据语音特征信号特点确定BP 神经网络的结构为24-30-4,随机初始化BP神经网络
# 权值和阔值

# 网络结构
innum <- nrow(input_test)
midnum <- 25 # 隐藏层数量是要自己确定的
outnum <- ncol(output)

# 权值
w1 <- matrix(runif(innum*midnum), nrow = midnum)
b1 <- matrix(runif(midnum), ncol = 1)
w2 <- matrix(runif(outnum*midnum), nrow = midnum)
b2 <- matrix(runif(outnum), ncol = 1) 

w2_1 <- w2
w2_2 <- w2_1
w1_1 <- w1
w1_2 <- w1_1
b1_1 <- b1
b1_2 <- b1_1
b2_1 <- b2
b2_2 <- b2_1

loopNumber <- 1000

E <- NULL 
I <- NULL
Iout <- NULL
FI <- NULL
db1 <- NULL
dw1 <- matrix(ncol = midnum, nrow = innum)

# 1.3.4 bp神经网络训练
# 用训练数据训练BP神经网络,在训练过程中根据网络预测误差调整网络的权值和阔值.
for (ii in 1:loopNumber){ 
  xite <- loopNumber/100
  E[ii] <- 0
  for (i in 1:(0.75*nrow(data))){
    # 选择本次训练数据
    x <- matrix(inputn[, i], ncol = 1)
    
    # 隐含层输出
    for(j in 1:midnum){
      I[j] <- t(x) %*% w1[j,] + b1[j]
      Iout[j] <- 1 / (1 + exp(-I[j]))
    }
    I <- matrix(I, nrow = 1)
    Iout <- matrix(Iout, nrow = 1)
    # 输出层输出
    yn = t(Iout %*% w2)  + b2

    # 权值阀值修正
    # 计算误差
    e = output_train[, i] - yn
    E[ii] = E[ii] + sum(abs(e))
    
    # 计算w2,b2调整量
    dw2 <- e %*% Iout
    db2 <- t(e)
    
    # 计算w1,b1调整量
    for (j in 1:midnum){
      S = 1 / (1 + exp(- I[j]))
      FI[j] = S * (1 - S)
    }
    for (k in 1:innum){
      for (j in 1:midnum)
      {
        dw1[k,j] <- FI[j] * x[k] * sum(e * w2[j, ])
        db1[j] <-  FI[j] * sum(e * w2[j, ])
      }
    }
    db1 <- matrix(db1, nrow = 1)
    # 权值阈值更新
    w1 <- w1_1 + xite * t(dw1)
    b1 <- b1_1 + xite * t(db1)
    w2 <- w2_1 + xite * t(dw2)
    b2 <- b2_1 + xite * t(db2)
    
    w1_2 <- w1_1
    w1_1 <- w1
    w2_2 <- w2_1
    w2_1 <- w2
    b1_2 <- b1_1
    b1_1 <- b1
    b2_2 <- b2_1
    b2_1 <- b2
  }
}
fore <- NULL
for (i in 1:(0.25*nrow(data))){
  # 隐含层输出
  for (j in 1:midnum){
    I[j] <- sum(input_test[, i] %*% t(w1)) + b1[j]
    Iout[j] <- 1 / (1 + exp(-I[j]))
  }
  fore <- cbind(fore, t(Iout %*% w2)  + b2)
}

## 结果分析
# 根据网络输出找出数据属于哪类
output_force <- apply(fore, 2, which.max)

# BP网络预测误差
error <- output_force - output1[-n]
table(output_force, output1[-n])

数据集
链接:https://pan.baidu.com/s/1T_74Lkw8W4WqoYfhPCxX_g
密码:cny4

原书作者微博:@王小川_MATLAB
本人微博:@蒋小受的吴小胖

猜你喜欢

转载自blog.csdn.net/weixin_33937913/article/details/87212549