BP神经网络-手动编写Python类实现网络结构

该neuralnetwork类的代码:


class neuralNetwork:
    # 初始化神经网络,构造函数
    def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
        # 设置每个输入、隐藏、输出层中的节点数
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes

        # 链接权重矩阵,wih和who
        # weights inside the arrays are w_i_j, where link is from node i to node j in the next layer
        # w11 w21
        # w12 w22 etc
        self.wih = np.random.normal(0.0, pow(self.inodes, -0.5), (self.hnodes, self.inodes)) # 正态分布函数
        self.who = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes))

        # 学习率
        self.lr = learningrate

        # 创建激活函数(函数的另一种定义方法,这样以后可以直接调用)
        self.activation_function = lambda x: S.expit(x)

        pass

    # 训练神经网络
    def train(self, inputs_list, targets_list):
        # 将输入列表转换成二维数组
        inputs = np.array(inputs_list, ndmin=2).T
        targets = np.array(targets_list, ndmin=2).T

        # 将输入信号计算到隐藏层
        hidden_inputs = np.dot(self.wih, inputs)
        # 计算隐藏层中输出的信号(使用激活函数计算)
        hidden_outputs = self.activation_function(hidden_inputs)
        # 将传输的信号计算到输出层
        final_inputs = np.dot(self.who, hidden_outputs)
        # 计算输出层中输出的信号(使用激活函数)
        final_outputs = self.activation_function(final_inputs)

        # 计算输出层的误差:(target - actual)(预期目标输出值-实际计算得到的输出值)
        output_errors = targets - final_outputs
        # 隐藏层的误差:是输出层误差按权重分割,在隐藏节点上重新组合
        hidden_errors = np.dot(self.who.T, output_errors)

        # 反向传播,更新各层权重
        # 更新隐层和输出层之间的权重
        self.who += self.lr * np.dot((output_errors * final_outputs * (1.0 - final_outputs)),
                                     np.transpose(hidden_outputs))
        # 更新输入层和隐藏层之间的权重
        self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), np.transpose(inputs))
        # pass一般用于占位置,定义一个空函数程序会报错,当没有想好函数的内容可以用pass填充,使得程序正常运行
        pass

    # 查询神经网络:接受神经网络的输入,返回神经网络的输出
    def query(self, inputs_list):
        # 将输入列表转换成二维数组
        inputs = np.array(inputs_list, ndmin=2).T

        # 将输入信号计算到隐藏层
        hidden_inputs = np.dot(self.wih, inputs)
        # 将信号从隐藏层输出
        hidden_outputs = self.activation_function(hidden_inputs)
        # 将信号引入到输出层
        final_inputs = np.dot(self.who, hidden_outputs)
        # 将信号从输出层输出
        final_outputs = self.activation_function(final_inputs)
        # 返回输出层的输出值
        return final_outputs

代码解释:
1.
np.random.normal(0.0, pow(self.inodes, -0.5), (self.hnodes, self.inodes))
正态分布函数实现初始化
numpy.random.normal(loc=0.0, scale=1.0, size=None)
参数的意义为:
loc:float

概率分布的均值,对应着整个分布的中心center

scale:float

概率分布的标准差,对应于分布的宽度,scale越大越矮胖,scale越小,越瘦高

size:int or tuple of ints

输出的shape,默认为None,只输出一个值

我们更经常会用到np.random.randn(size)所谓标准正太分布(μ=0, σ=1),对应于np.random.normal(loc=0, scale=1, size)
2.
S.expit(x) :sigmod激活函数
BP神经网络-手动编写Python类实现网络结构_第1张图片
3.
hidden_inputs = np.dot(self.wih, inputs)
矩阵点积
4.
np.ndarray.T 矩阵转置
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.T.html
5。
np.array(inputs_list, ndmin=2).T
ndmin代表结果输出最小的纬度,这里使其输出为二维数组
6.

# 更新隐层和输出层之间的权重
  self.who += self.lr * np.dot((output_errors * final_outputs * (1.0 - final_outputs)),
                                     np.transpose(hidden_outputs))
# 更新输入层和隐藏层之间的权重
 self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), np.transpose(inputs))

这两行是BP反向传播的公式,是这个BP结构最重要的部分

下面给出一个使用该network类的代码示例

# 设置输入、隐藏、输出层中的节点数,和学习率
input_nodes = 30
hidden_nodes = 30*2+1
output_nodes = 1
learning_rate = 0.1

# 训练神经网络
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
epochs = 400
print('begin training...')
for e in range(epochs):
    # go through all records in the training data set
    for i in range(80):
        inputs=X[i, :]
        targets=Y[i]
        n.train(inputs, targets)  # 开始训练
    if e%100==0:
        print("train", e, 'finished!')

# 开始测试
print('测试:。。。')
ans=[]

for i in range(0, 103):
    inputs = X[i, :]
    targets = Y[i]
    ans.append(n.query(inputs))

print('ans:', np.array(ans))

# 权重层输出
print('输出权重:')
print(n.wih)
print(n.who)

epochs是训练轮数,将训练集中的每个样本都进行一遍训练算作一轮。
可以看出,该BP网络类,可以实现内部权重输出的操作,有利于对对该神经网络的黑箱性模型进行观测

你可能感兴趣的:(机器学习)