评论

收藏

[JavaScript] python实现单隐层神经网络基本模型

开发技术 开发技术 发布于:2021-06-23 22:28 | 阅读数:229 | 评论:0

  应朋友之请写了一份python实现单隐层BP Ann model的code,好久没写博客,就顺便发上来。这篇代码比较干净利落,比较纯粹的描述了Ann的基本原理,初学机器学习的同学可以参考。

模型中几个比较重要的参数:1.学习率学习率是影响模型收敛的重要因素,一般来说要根据具体场景灵活调整,过高的学习率会使得函数快速发散。2.隐元数量一般来说,增加隐层中神经元的数量比直接增加隐层更加有效,这也是单隐层神经网络的特点。对于复杂程度不算太高的问题而言,单隐层的效果优于多隐层。3.随机种子位数代码中增加了这一参数,来控制初始化连接权与阈值的精度。由于神经网络中初始权重与阈值是随机生成的,那么其随机精度会对结果产生一定的影响。在输入元、隐元的数量较多时,调整随机精度会起到减小误差的作用。
代码中举了一个非常简单的训练示例,笔者自拟了一个规则:    输入两个变量,当变量A = 变量B时,返回类型1,矩阵化为[1,0]。当变量A != 变量B时,返回类型2,矩阵化为[0,1]。
让神经网络去学习这个simple的规则,并给出20条测试数据去验证。最终使用了5000条训练数据,就获得了100%的正确分类能力。
#---Author:伍思磊---Mail:wusilei@1006.tv---2015/7/27
import random
import math
---神经网络Model
class Ann:
#构造函数 初始化模型参数
def __init__(self, i_num, h_num, o_num):
    #可调参数
    self.learn_rate = 0.1  #学习率
    self.num_long = 2    #输出结果位数
    self.random_long = 10  #随机种子位数
#输入参数
    self.input_num = i_num   #输入层 数量
    self.hidden_num = h_num  #隐层 数量
    self.output_num = o_num  #输出层 数量
#模型参数
    self.input = []      #输入层
    self.hidden = []     #隐层
    self.output = []     #输出层
    self.error = []      #误差
    self.expectation = []  #期望
    self.weight_ih = self.__ini_weight(self.input_num, self.hidden_num)   #输入层->隐层 连接权
    self.weight_ho = self.__ini_weight(self.hidden_num, self.output_num)  #隐层->输出层 连接权
    self.threshold_h = self.__ini_threshold(self.hidden_num)        #隐层 阈值
    self.threshold_o = self.__ini_threshold(self.output_num)        #输出层 阈值
  #初始连接权生成器
  def __ini_weight(self, x, y):
result = []
    long = math.pow(10, self.random_long)
    for i in range(0, x, 1):
      res = []
      for j in range(0, y, 1):
        num = round(random.randint(-1*long,long)/long, self.random_long)
        res.insert(j, num)
      result.insert(i, res)
    return result
  #初始阈值生成器
  def __ini_threshold(self, n):
result = []
    long = pow(10, self.random_long)
    for i in range(0, n, 1):
      num = round(random.randint(-1*long,long)/long, self.random_long)
      result.insert(i, num)
    return result
  #激励函数 sigma
  def excitation(self, value):
sigma = 1/(1+(math.exp(-1*value)))
    return sigma
  #输入数据
  def input_param(self, data, expectation = []):
self.input = []
    for value in data:
      self.input.append(value)
    if(expectation):
      self.expectation = []
      for value in expectation:
        self.expectation.append(value)
  #隐层计算
  def count_hidden(self):
self.hidden = []
    for h in range(0, self.hidden_num, 1):
      Hval = 0
      for i in range(len(self.input)):
        Hval += self.input[i] * self.weight_ih[i][h]
      Hval = self.excitation(Hval+self.threshold_h[h])
      self.hidden.insert(h, Hval)
  #输出层计算
  def count_output(self):
self.output = []
    for o in range(0, self.output_num, 1):
      Oval = 0
      for h in range(len(self.hidden)):
        Oval += self.hidden[h] * self.weight_ho[h][o]
      Oval += self.threshold_o[o]
      Oval = round(Oval, self.num_long)
      self.output.insert(o, Oval)
  #误差计算
  def count_error(self):
self.error = []
    for key in range(len(self.output)):
      self.error.insert(key, self.expectation[key] - self.output[key])
  #连接权反馈训练 输入层->隐层
  def train_weight_ih(self):
for i in range(len(self.weight_ih)):
      for h in range(len(self.weight_ih[i])):
        tmp = 0
        for o in range(0, self.output_num, 1):
          tmp += self.weight_ho[h][o] * self.error[o]
        self.weight_ih[i][h] = self.weight_ih[i][h] + self.learn_rate * self.hidden[h] * (1 - self.hidden[h]) * self.input[i] * tmp
  #连接权反馈训练 隐层->输出层
  def train_weight_ho(self):
for h in range(len(self.weight_ho)):
      for o in range(len(self.weight_ho[h])):
        self.weight_ho[h][o] = self.weight_ho[h][o] + self.learn_rate * self.hidden[h] * self.error[o]
        
  #阈值反馈训练 隐层
  def train_threshold_h(self):
    for h in range(len(self.threshold_h)):
      tmp = 0
      for o in range(0, self.output_num, 1):
        tmp += self.weight_ho[h][o] * self.error[o]
      self.threshold_h[h] = self.threshold_h[h] + self.learn_rate * self.hidden[h] * (1 - self.hidden[h]) * tmp
  #阈值反馈训练 输出层
  def train_threshold_o(self):
for o in range(len(self.threshold_o)):
      self.threshold_o[o] = self.threshold_o[o] + self.error[o]
  #反馈训练
  def train(self):
self.train_weight_ih()
    self.train_weight_ho()
    self.train_threshold_h()
    self.train_threshold_o()
  #归一化函数
  def normal_num(self, max, min, data):
data = (data - min)/(max - min)
    return data
  #寻找集合的最大值和最小值

---业务部分(示例)

要训练的规则,输入两个值,如果两值相等返回[1,0],反之返回[0,1]

  def testFunc(val):
  if(val[0] == val[1]):
return [1,0]
  else:
    return [0,1]
构造神经网络模型

  ann = Ann(2,3,2)

生成训练数据,随机生成5000组[0,1][1,0][1,1][0,0]随机数组

  data = []
  for i in range(0, 10000, 1):
  x = random.randint(0,1)
  y = random.randint(0,1)
  data.append([x,y])

取得训练数据中的最大值和最小值

  for i in range(len(data)):
  for j in range(len(data)):
if(i == 0 and j == 0):
      max = min = data[i][j]
    elif(data[i][j] > max):
      max = data[i][j]
    elif(data[i][j] < min):
      min = data[i][j]
训练数据归一化

  dataNormal = []
  for i in range(len(data)):
  dataNormal.insert(i, [])
  for j in range(len(data)):
dataNormal[i].append(ann.normal_num(max, min, data[i][j]))
计算训练数据期望值,并进行反馈训练

  for i in range(len(data)):
  #计算期望值
  exp = testFunc(data)
  #输入训练数据与期望
  ann.input_param(dataNormal, exp)
  #计算隐层
  ann.count_hidden()
  #计算输出层
  ann.count_output()
  #计算误差
  ann.count_error()
  #反馈训练
  ann.train()

生成测试数据,随机生成20组

  testdata = []
  for i in range(0, 20, 1):
  x = random.randint(0,1)
  y = random.randint(0,1)
  testdata.append([x,y])

进行测试,同时输出神经网络预测值与实际期望值

  for i in range(len(testdata)):
  exp = testFunc(testdata)
  ann.input_param(testdata)
  ann.count_hidden()
  ann.count_output()
  print("Ann:")
  print(ann.output)
  print("Exp:")
  print(exp)
print("\r")

关注下面的标签,发现更多相似文章