文章目录
假设-评价-优化
深度学习的最基本的概念
神经网络
神经网络有三个核心点:
- 神经元: 神经网络中每个节点称为神经元,由加权和,非线性变化(激活函数)组成。
- 多层连接:大量这样的节点按照不同的层次排布,形成多层的结构连接起来,即称为神经网络
- 前向计算(得到输出)和后向传播(更新参数)
入门案例:波士顿房价预测(机器学习界的HelloWorld)
采用模型:多元线性回归
深度学习构建模型和完成训练的套路一致(五步法)
- 数据处理:从本地或url读取数据,并完成预处理操作(如数据校验,格式转化等),保证模型可读取
- 模型设计:(模型要素1)网络结构设计,相当于模型的假设空间,即模型能够表达的关系集合
- 训练配置:(模型要素2)设定模型采用的寻解方法,即优化器,并指定计算资源
- 训练过程:(模型要素3)循环调用训练过程,每轮都包括前向计算,损失函数(优化目标)和后向传播三个步骤
- 模型保存:将训练好的模型保存,模型预测是调用
将数据集划分为训练集和数据集:
数据处理:归一化
使用python和numpy构建神经网络模型
数据处理:
def load_data():
# 从文件导入数据
datafile = 'housing.data'
data = np.fromfile(datafile, sep='')
# 每条数据包含14项,其中前13项是影响因数,第14项是相应的房屋价格中位数
feature_names = ['CRIM', 'ZN', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
feature_num = len(feature_names)
# 将原始数据进行reshape,变成[N,14]这样的形状
data = data.reshape([data.shape[0]//feature_num, feature_num])
# 将原数据集拆分成训练集和测试集
# 这里使用80%的数据做训练,20%的数据做测试
# 测试集和训练集必须是没有交集的
ratio = 0.8
offset = int(data.shape[0]*radio)
data_slice = data[:offset]
# 计算train数据集的最大值,最小值,平均值
maximums, minimums, avgs = data_slice.max(axis=0), data_slice.min(axis=0), data_slice.sum(axis=0)/data_slice.shape[0]
# 对数据进行归一化处理
for i in range(feature_num)
# print(mmaximunms,...)
data[:,i] = (data[;, i] - avgs[i])/(maximunms[i] - minimums[i])
# 训练集和测试集的比例划分
# ratio = 0.8
# offset = int(data.shape[0]*ratio)
train_data = data[:offset]
test_data = data[offset:]
return train_data, test_data
设计模型
在此案例中即用不到激活函数
以类的方式实现网络结构(前向计算)
- 使用时可以生成多个模型实例
- 类成员变量有w和b,在类初始化函数中初始化变量
- 函数成员forward完成从输入特征x到输出z的计算过程(即前向计算)
class Network(object):
def __init__(self, num_of_weights):
# 随机产生w的初始值
# 为了保持程序的每次运行结果的一致性
# 此处设置固定的随机数种子
np.random.seed(0)
self.w = np.random(num_of_wrights, 1)
self.b = 0
def forward(self, x):
z = np.dot(x, self.w) + self.b
return z
此时模型还未进行学习不具有预测能力,只是搭起了一个框架
模型的损失和优化
梯度下降思想(盲人下坡)
梯度下降的代码实现(上)
# 首先取出一个样本,并查看其数据内容和维度
x1 = x[0]
y1 = y[0]
z1 = net.forward(x1)
print('x1 {}, shape {}'.format(x1, x1.shape))
print('y1 {}, shape {}'.format(y1, y1.shape))
print('z1 {}, shape {}'.format(z1, z1.shape))
梯度的代码实现(中)
利用Numpy的广播机制进行梯度计算
- 基于Numpy的广播机制,扩展参数的维度
使用Numpy矩阵操作,计算梯度的代码中直接用(z1-y1)*x1,得到一个13维的向量,每个向量分别代表该维度的梯度
gradient_w = (z1-y1)*x1
print('gradient_w {}, gradient.shape {}'.format(gradient_w, gradient_w.shape))
- 同样,利用Numpy的广播机制扩展样本的维度
三个样本贡献的梯度
# 这里是一次取出三个样本的数据,不是取出第三个样本
x3samples = x[0:3]
y3samples = y[0:3]
z3samples = net.forward(x3samples)
gradient_w = (z3samples - y3samples) * x3samples
print('gradient_w {}, gradient.shape{}'.format(gradient_w, gradient_w.shape))
gradient_w 的维度是[3,13] ,扩展了两个维度
计算有所样本:
Numpy的广播机制实际上可以把一个向量和一个矩阵像一个变量一样去操作
z = net.forward(x)
gradient_w = (z - y) * x
print('gradient_w {}, gradient.shape{}'.format(gradient_w, gradient_w.shape))
# axis = 0表示把每一行做相加然后再除以总的行数
gradient_w = np.mean(geadient_w, axis = 0)
print('gradient_w', gradient_w.shape)
print('w ', net.w.shape)
print(gradient_w)
print(net.w)
w的维度:[13: 1]
gradient_w的维度: [13, ]
由于np.mean操作降低了维度
将gradient_w的维度重新设置为[13 : 1]
z = net.forward(x)
gradient_w = (z - y) * x
gradient_w = np.mean(gradient_w, axis = 0)
gradient_w = gradient_w[;, np.newaxis]
类似的过程可以计算出b的梯度,由于b只是一个数值,所以梯度也是一个数值,而不是向量
gradient_b = (z-y)
gradient_b = np.mean(gradient_b)
# 此处b是一个数值,所以可以直接用np,mean得到一个标量
gradient_b
梯度下降的代码实现(下)
训练的全流程实现