神经网络结构
核心术语
-
神经元(neuron)
人工神经网络中的最小单位,神经元拥有一个权重向量,一个 -
层(layer)
第一层称为输入层,最后一层称为输出层,输入层和输出层之间的层都称为隐藏层。输入层没有前层节点,输出层没有后续节点,因此,在正向求值和反向传播时有区别。 -
反向传播
反向传播将在神经网络的输出中发现误差,并用它来修正神经元的权重。某个神经元对误差担负的责任越大,对其修正就会越多。但误差从何而来?我们如何才能知道存在误差呢?误差由被称为训练(training)的神经网络应用阶段获得(说白了,就是如果这个神经网络不训练,不反向传播就仅仅是一个静态的模型,没有任何价值)。
我们必须知道通过某些输入能够获得的正确输出,以便用预期输出和实际输出的差异来查找误差并修正权重。换句话说,神经网络在最开始时是一无所知的,直至它们知晓对于某组特定输入集的正确答案,在这之后才能为其他输入做好准备。反向传播仅发生在训练期间。
反向传播的第一步,是计算神经网络针对某些具体输入的真实输出结果与预期输出结果之间的误差。输出层中的所有神经元都会具有这一误差(每个神经元都有一个预期输出及其实际输出)。然后,输出神经元的激活函数的导数将会应用于该神经元在其激活函数被应用之前输出的值(这里缓存了一份应用激活函数前的输出值)。
反向传播的第二步是:将求导结果再乘以神经元的误差,求其delta(是一个为网络所有隐藏层中的每个神经元计算delta。输出层中的delta将会用于计算上一个隐藏层中的delta。根据下层各神经元权重的点积和在下层中已算出的delta,可以算出上一层的delta。将这个值乘以调用神经元最终输出(在调用激活函数之前已缓存)的激活函数的导数,即可获得当前神经元的delta。
最后就是梯度下降
一旦权重更新完毕,神经网络就可以用其他输入和预期输出再次进行训练。此过程将一直重复下去,直至该神经网络的用户认为其已经训练好了,这可以用正确输出已知的输入进行测试来确定。(循环往复)
代码实现
导包(打脸)
from typing import List
from math import exp
from random import random
from functools import reduce
定义一些工具函数
点积,激活函数,激活函数
包括点积,激活函数,激活函数的导数以及数据处理时将用到的归一化函数
# dot product of two vectors 点集两个向量
def dot_product(xs: List[float], ys: List[float]) -> float:
return sum(x * y for x, y in zip(xs, ys))
# the classic sigmoid activation function
def sigmoid(x: float) -> float:
return 1.0 / (1.0 + exp(-x))
def derivative_sigmoid(x: float) -> float:
sig: float = sigmoid(x)
return sig * (1 - sig)
归一化函数
归一化操作大致可以分为两种,两种方法各有优缺点。
- ①:对所有数据进行归一化
- ②:对同一类(同一属性—>列)的数据进行归一化
一般情况下,都是使用第二种,对同一属性的数据进行归一化。
归一化公式:
分别对应了下面两种:
# assume all rows are of equal length
# 归一化操作 (函数是否有问题)
# and feature scale each column to be in the range 0 - 1
def normalize_by_feature_scaling(dataset: List[List[float]]) -> None:
for col_num in range(len(dataset[0])):#内层(对每一个列进行操作)
column: List[float] = [row[col_num] for row in dataset]
maximum = max(column)
minimum = min(column)
for row_num in range(len(dataset)):# 外层(对每一行进行操作)
dataset[row_num][col_num] = (dataset[row_num][col_num] - minimum) / (maximum - minimum)
return dataset
def normalize(dataset=[[5,2,2],[3,2,1]]):
flatten=[]
for i in range(len(dataset)):
flatten.extend(dataset[i])
max_num=max(flatten)
min_num=min(flatten)
# 归一化
for i in range(len(dataset)):
for j in range(len(dataset[i