1.什么是神经网络?
先举个例子:找工作
在考虑入要不要接受一个岗位,需要综合的考虑一些因素,比如:薪资,气氛,工作环境,离家远近等等,但是一个岗位不太可能所以的条件都满足,需要有些取舍。
怎么取舍呢?
当然是根据重要程度来,比如薪资肯定比气氛重要吧,
重要程度如何衡量?我们可以想到用权重表表示重要程度,权重越大表示越重要,权重越小表示越不重要
每个因素达到预期情况下,对结果的重要程度用如下权重表示
薪资: 0.5
气氛: 0.3
工作环境: 0.2
离家距离: 0.1
假设当这些因素加起来总权重大于0.6时就接受,有两种情况
1.薪资不错+(气氛,工作环境,距离三张至少满足一个)
2.薪资不行+(气氛,工作环境,距离三个都满足要求)
这些情况可以用下图表示:
中间的圆圈表示判断逻辑:当4个输入值的总和大于0.6输出1,小于0.6输出0
跟神经网络有什么关系呢?
神经网络有N个节点组成,每个节点跟上面判断单元一样,有输入端,逻辑处理,输出端组成,如下图所示
几个性质:
- 1.神经网络至少有3层,从左到有分别是 输入层,隐藏层,输出层
- 2.上面节点之前的连线代表权重,每条连线的权重值都是不一样的
- 3.每层的每个节点与上层的所有节点都相连,所以又叫做全连接神经网络
神经网络有什么作用呢?
上面我们假定了每个因素的重要程度,但是现实是我们只有一堆历史数据,要根据历史数据来计算每个输入的权重,也就是我们所说的调参,有了这些参数后对于每个输入在通过计算后就可以预测结果了
为啥神经网络能起作用?
我们经常能听到“历史总是惊人的相识”这句话,从侧面也能反应事情凡事都是有一定规律的,神经网络通过多层,多参数能找到这种规律
怎么衡量神经网络模型好坏?
预测结果和实际结果比较,统计差距,差距小说明越好,差距越大说明越差
实际案例:手写数字分类
# coding: utf-8
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer
from sklearn.metrics import confusion_matrix, classification_report
def logistic(x):
return 1.0 / (1 + np.exp(-x))
def logistic_deriv(x):
"""
逻辑函数的导数
"""
fx = logistic(x)
return fx * (1 - fx)
class NeuralNetwork(object):
def __init__(self, layers, activation='logistic'):
"""
:param layers: 层数,如[4, 3, 2] 表示两层len(list)-1,(因为第一层是输入层,,有4个单元),
第一层有3个单元,第二层有2个单元
:param activation:
"""
if activation == 'tanh':
self.activation = tanh
self.activation_deriv = tanh_deriv
elif activation == 'logistic':
self.activation = logistic
self.activation_deriv = logistic_deriv
# 初始化随即权重
self.weights = []
#np.random.random([4,3]) 生成第一层的权重,4*3的矩阵,列表示每个神经元的对应输入的权重权重
for i in range(len(layers) - 1):
#tmp = (np.random.random([layers[i], layers[i + 1]]) * 2 - 1) * 0.25
tmp = (np.random.random([layers[i], layers[i + 1]]) * 2 - 1) * 0.25
self.weights.append(tmp)
# 偏向
self.bias = []
# 根据每层的个数来计算bias
for i in range(1, len(layers)):
self.bias.append((np.random.random(layers[i]) * 2 - 1) * 0.25)
def fit(self, X, y, learning_rate=0.2, epochs=10000):
X = np.atleast_2d(X)
y = np.array(y)
# 随即梯度
for k in range(epochs):
i = np.random.randint(X.shape[0])
#i 表示第几个样本
a = [X[i]] # 随即取某一条实例
#weights[j] 表示第j层的权重矩阵
for j in range(len(self.weights)):
#由于a是2维数组 所以a[0]就等于第一个样本的数据,第1层的权重是 64*100 的矩阵
#得到第1层节点的输入值,遍历下来,得到第一个样本数值,中间N层的值,最后的输出值
a.append(self.activation(np.dot(a[j], self.weights[j]) + self.bias[j] ))
# a[-1] 表示最后的输出 one-hot 编码
errors = y[i] - a[-1]
#errors 比如 y[i]=[0 0 1 0 0 0 0 0 0 0 ] 第i个样本对应的是2,因为对应的下标是2
#假设此时a[-1] = [0.2 0.3 0.4 0.2 0.3 0.4 0.5]
#则对应的误差为y[i]-a[-1]=[-0.2 -0.3 0.6 ... 0.5]
deltas = [errors * self.activation_deriv(a[-1]) ,] # 输出层的误差
# 反向传播,对于隐藏层的误差
for j in range(len(a) - 2, 0, -1):
tmp = np.dot(deltas[-1], self.weights[j].T) * self.activation_deriv(a[j])
deltas.append(tmp)
deltas.reverse()
# 更新权重
for j in range(len(self.weights)):
layer = np.atleast_2d(a[j])
delta = np.atleast_2d(deltas[j])
#偏导*learning_rate
self.weights[j] += learning_rate * np.dot(layer.T, delta)
# 更新偏向
for j in range(len(self.bias)):
self.bias[j] += learning_rate * deltas[j]
def predict(self, row):
a = np.array(row) # 确保是 ndarray 对象
for i in range(len(self.weights)):
a = self.activation(np.dot(a, self.weights[i]) + self.bias[i])
return a
if __name__ == "__main__":
nn = NeuralNetwork(layers=[64, 100, 10])
digits = datasets.load_digits()
X = digits.data
#1797个样本,每个样本64维,所以样本可以表示为 1797*64 的矩阵
y = digits.target
# 拆分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y)
# 分类结果离散化
labels_train = LabelBinarizer().fit_transform(y_train)
labels_test = LabelBinarizer().fit_transform(y_test)
nn.fit(X_train, labels_train)
# 收集测试结果
predictions = []
for i in range(X_test.shape[0]):
o = nn.predict(X_test[i] )
predictions.append(np.argmax(o))
# 打印对比结果
print (confusion_matrix(y_test, predictions) )
print (classification_report(y_test, predictions))