AI智能
改变未来

PaddlePaddle-百度架构师手把手带你零基础实践深度学习-笔记01(代码详解)


案例一:波士顿房价预测问题(代码详解)

  • 预测问题分类
区别 回归任务 分类任务
预测输出类型 连续的实数值 离散的标签
常用损失函数loss()举例 均方差损失函数Loss=(y-z)^2 交叉熵损失函数
  • 深度学习基本步骤
# numpy.fromfile()fromfile(...)fromfile(file, dtype=float, count=-1, sep=\'\', offset=0)Construct an array from data in a text or binary file.
具体代码详解

Step1-数据处理:读取数据和预处理操作

# 数据处理def load_data():                                                    # 数据预处理(数据导入、数据形状变换、数据集划分、数据归一化处理和封装load data函数)# 从文件导入数据datafile = \'./work/housing.data\'data = np.fromfile(datafile, sep=\' \')# 每条数据包括14项,其中前面13项是影响因素,第14项是相应的房屋价格中位数feature_names = [ \'CRIM\', \'ZN\', \'INDUS\', \'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.8offset = int(data.shape[0] * ratio)training_data = data[:offset]# 计算训练集的最大值,最小值,平均值maximums, minimums, avgs = training_data.max(axis=0), training_data.min(axis=0), \\training_data.sum(axis=0) / training_data.shape[0]# 对数据进行归一化处理for i in range(feature_num):#print(maximums[i], minimums[i], avgs[i])data[:, i] = (data[:, i] - avgs[i]) / (maximums[i] - minimums[i])# 训练集和测试集的划分比例training_data = data[:offset]test_data = data[offset:]return training_data, test_data                           # 返回训练集和测试集# ---------------------------------------------------------------------------------------------------------------# 获取数据,调用load_data()函数training_data, test_data = load_data()   # 得到划分好的数据集# 二维数组切片,将前13列和后1列划分开x = training_data[:, :-1]                # 将测试集再次划分为前13个xy = training_data[:, -1:]                # 将剩下的第14个数据项赋值给y# 注意这里的x,y都是长度为404的向量,其中x为二维向量(404*13),y为一维向量(404*1)# ----------------------------------------------------------------------------------------------------------------

Step2-模型设计:网络结构(假设)

# 模型设计class Network(object):def __init__(self, num_of_weights):               # 权重 num_of_weights = 13# 随机产生w的初始值# 为了保持程序每次运行结果的一致性,# 此处设置固定的随机数种子np.random.seed(0)                             # 保证每次生成的随机值都是相同的self.w = np.random.randn(num_of_weights, 1)self.b = 0.def forward(self, x):                               # 前向计算,参考前面的神经元,输出在当下参数下的预测值z = np.dot(x, self.w) + self.breturn z

Step3-训练配置:优化器(寻解算法)和计算资源配置

# 训练配置 设置损失函数,便于衡量参数的优劣class Network(object):def __init__(self, num_of_weights):# 随机产生w的初始值# 为了保持程序每次运行结果的一致性,此处设置固定的随机数种子np.random.seed(0)self.w = np.random.randn(num_of_weights, 1)self.b = 0.def forward(self, x):z = np.dot(x, self.w) + self.breturn zdef loss(self, z, y):                                # 添加了loss()损失函数error = z - ycost = error * errorcost = np.mean(cost)   # 求取平均值               # n个cost相加然后取平均return cost

Step4-训练过程:循环调用训练过程,前向计算+损失函数(优化目标)+后向传播

# 训练过程(找到合适的参数)# 训练过程是深度学习模型的关键要素之一,其目标是让定义的损失函数Loss尽可能的小,也就是说找到一个参数解w(13,1)和b(1,)使得损失函数取得极小值# 方法:梯度下降法-----从当前的参数取值,一步步的按照下坡的方向下降,直到走到“最低点”-最小损失函数对应的参数# 计算梯度class Network(object):def __init__(self, num_of_weights):# 随机产生w的初始值# 为了保持程序每次运行结果的一致性,此处设置固定的随机数种子np.random.seed(0)self.w = np.random.randn(num_of_weights, 1)self.b = 0.def forward(self, x):z = np.dot(x, self.w) + self.b   # 矩阵乘法return zdef loss(self, z, y):error = z - ynum_samples = error.shape[0]cost = error * errorcost = np.sum(cost) / num_samplesreturn costdef gradient(self, x, y):                     # 利用Numpy广播功能计算w、b的梯度z = self.forward(x)gradient_w = (z-y)*xgradient_w = np.mean(gradient_w, axis=0)gradient_w = gradient_w[:, np.newaxis]gradient_b = (z - y)gradient_b = np.mean(gradient_b)return gradient_w, gradient_b# ------------------------------------------------------------------------------------------------------------------------# 更新梯度(确定损失函数更小的点)# 基本思路是沿着梯度的反方向移动一小步(梯度反方向是损失函数值下降最快的方向)class Network(object):def __init__(self, num_of_weights):# 随机产生w的初始值# 为了保持程序每次运行结果的一致性,此处设置固定的随机数种子np.random.seed(0)self.w = np.random.randn(num_of_weights, 1)self.b = 0.def forward(self, x):z = np.dot(x, self.w) + self.breturn zdef loss(self, z, y):error = z - ynum_samples = error.shape[0]cost = error * errorcost = np.sum(cost) / num_samplesreturn costdef gradient(self, x, y):z = self.forward(x)gradient_w = (z-y)*xgradient_w = np.mean(gradient_w, axis=0)gradient_w = gradient_w[:, np.newaxis]gradient_b = (z - y)gradient_b = np.mean(gradient_b)return gradient_w, gradient_bdef update(self, gradient_w, gradient_b, eta = 0.01):            # 更新wself.w = self.w - eta * gradient_wself.b = self.b - eta * gradient_bdef train(self, x, y, iterations=100, eta=0.01):                 # 沿梯度反方向进行重复训练,默认迭代次数iterations=100次losses = []for i in range(iterations):z = self.forward(x)L = self.loss(z, y)gradient_w, gradient_b = self.gradient(x, y)self.update(gradient_w, gradient_b, eta)losses.append(L)                                        # 向losses中添加每次迭代的损失函数值if (i+1) % 10 == 0:print(\'iter {}, loss {}\'.format(i, L))return losses# 获取数据train_data, test_data = load_data()x = train_data[:, :-1]y = train_data[:, -1:]# 创建网络net = Network(13)num_iterations=1000# 启动训练losses = net.train(x,y, iterations=num_iterations, eta=0.01)# 画出损失函数的变化趋势plot_x = np.arange(num_iterations)plot_y = np.array(losses)plt.plot(plot_x, plot_y)plt.show()# ---------------------------------------------------------------------------------------------------------------# 随机梯度下降法# 每次从总的数据集中随机抽取出小部分数据来代表整体,基于这部分数据计算梯度和损失来更新参数,这种方法被称作随机梯度下降法(Stochastic Gradient Descent,SGD)# min-batch:每次迭代时抽取出来的一批数据被称为一个min-batch# batch_size:一个mini-batch所包含的样本数目称为batch_size# epoch:当程序迭代的时候,按mini-batch逐渐抽取出样本,当整个数据集都遍历到了,则完成了一轮训练,也叫一个epoch# 启动训练时,可以将训练的轮数num_epochs和batch_size作为参数传入,利用batch_size将测试数据划分为一个个小的mini-batch进行训练# 获取数据train_data, test_data = load_data()# 将数组进行随机打乱,每次运行结果都不一样,以此来避免模型记忆影响训练效果np.random.shuffle(train_data)                                        # 一维数组不变,只是二维数组最外层顺序随机打乱# 将train_data分成多个mini_batchbatch_size = 10n = len(train_data)# 这里range中步长为10,然后从train_data中划分出包含10各元素的mini_batchmini_batches = [train_data[k:k+batch_size] for k in range(0, n, batch_size)]# 创建网络net = Network(13)# 依次使用每个mini_batch的数据for mini_batch in mini_batches:x = mini_batch[:, :-1]y = mini_batch[:, -1:]loss = net.train(x, y, iterations=1)# ---------------------------------------------------------------------------------------------------------------# 采用随机梯度下降方法修改后的模型import numpy as npclass Network(object):def __init__(self, num_of_weights):# 随机产生w的初始值# 为了保持程序每次运行结果的一致性,此处设置固定的随机数种子#np.random.seed(0)self.w = np.random.randn(num_of_weights, 1)self.b = 0.def forward(self, x):z = np.dot(x, self.w) + self.breturn zdef loss(self, z, y):error = z - ynum_samples = error.shape[0]cost = error * errorcost = np.sum(cost) / num_samplesreturn costdef gradient(self, x, y):z = self.forward(x)N = x.shape[0]gradient_w = 1. / N * np.sum((z-y) * x, axis=0)gradient_w = gradient_w[:, np.newaxis]gradient_b = 1. / N * np.sum(z-y)return gradient_w, gradient_bdef update(self, gradient_w, gradient_b, eta = 0.01):self.w = self.w - eta * gradient_wself.b = self.b - eta * gradient_bdef train(self, training_data, num_epoches, batch_size=10, eta=0.01):n = len(training_data)losses = []for epoch_id in range(num_epoches):# 在每轮迭代开始之前,将训练数据的顺序随机打乱# 然后再按每次取batch_size条数据的方式取出np.random.shuffle(training_data)# 将训练数据进行拆分,每个mini_batch包含batch_size条的数据mini_batches = [training_data[k:k+batch_size] for k in range(0, n, batch_size)]for iter_id, mini_batch in enumerate(mini_batches):    # enumerate()返回每次迭代的索引和元素#print(self.w.shape)#print(self.b)x = mini_batch[:, :-1]y = mini_batch[:, -1:]a = self.forward(x)loss = self.loss(a, y)gradient_w, gradient_b = self.gradient(x, y)self.update(gradient_w, gradient_b, eta)losses.append(loss)print(\'Epoch {:3d} / iter {:3d}, loss = {:.4f}\'.format(epoch_id, iter_id, loss))   # 注意区分,epoch_id为整体数据的第?次迭代,iter_id为每个mini_batch里的第?次迭代return losses# 获取数据train_data, test_data = load_data()# 创建网络net = Network(13)# 启动训练losses = net.train(train_data, num_epoches=50, batch_size=100, eta=0.1)  # 将404条数据分为5各mini_batch进行训练,整体数据训练100次# 画出损失函数的变化趋势plot_x = np.arange(len(losses))plot_y = np.array(losses)plt.plot(plot_x, plot_y)plt.show()

Step5-保存模型:将训练好的模型保存

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » PaddlePaddle-百度架构师手把手带你零基础实践深度学习-笔记01(代码详解)