1. 损失函数的定义
与之前介绍的单个神经元的工作原理不同之处在于损失函数的定义,这里把损失函数定义为:
推导思路:利用最大似然估计。先表达出p(y|x),然后求其最大值。大致推导过程如下:
课程中另一个重点是“消除for循环”,也就是说用向量来代替显示的for循环,这样做的好处是提高计算效率。实验测试100万条测试数据,向量化要比循环快上300倍。因此在以后的编码中,尽量把数据初始化成一个矩阵来处理。在这里值得注意的是,构造的矩阵应该每一列表示一个测试样例。
2. 代码实现
下面给出基于神经网络的二分类代码(python):
import numpy as np import h5py import math def load_dataset(): train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r") train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set features train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labels test_dataset = h5py.File('datasets/test_catvnoncat.h5', "r") test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set features test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labels classes = np.array(test_dataset["list_classes"][:]) # the list of classes train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0])) test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0])) return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes def train_model(learning_rate=0.1): train_data_x, train_data_y, test_data_x, test_data_y, classes = load_dataset() # 获取数据集 train_data_x = train_data_x.reshape(209, 64*64*3).T # 把训练数据构造成二维矩阵,行数为X的维度,列值为训练样本的个数 row_count = 64*64*3 # 表示一个样例的维度 examples_count = 209 # 表示样例的数量 weight = np.zeros((64*64*3, 1)) # 初始化权值向量为0 b = 0 # 初始化阈值为0 dw = 0 db = 0 for i in range(1000): z = np.dot(weight.T, train_data_x) + b # 计算z y_hat = 1.0 / (1 + math.e**(-z)) # 计算预测值 result = np.sum(abs(y_hat - train_data_y )) # 以累加y_hat-y的值来表示预测效果,result越小越好 if result == 0: break print '%d:%d' %(i, result) dz = y_hat - train_data_y # 计算dL/dz dw = np.dot(train_data_x, dz.T) # 计算dL/dw db = np.sum(dz) dw = dw * 1.0 / examples_count db = db * 1.0 / examples_count weight = weight - learning_rate * dw b = b - learning_rate * db return weight, b def predict_data(weight, b): train_data_x, train_data_y, test_data_x, test_data_y, classes = load_dataset() # 获取数据集 row_count = 64 * 64 * 3 # 一个样例的维度 example_count = 50 # 测试样例个数 test_data_x = test_data_x.reshape(example_count, row_count).T # 转换成对应格式的矩阵 z = np.dot(weight.T, test_data_x) + b predict_y = 1.0 / (1 + math.e**(-z)) # 计算预测值 print 'correct rate:',np.sum(predict_y == test_data_y)* 1.0 / example_count print predict_y if __name__ == '__main__': train_data_x, train_data_y, test_data_x, test_data_y, classes = load_dataset() # 获取数据集 weight, b = train_model(learning_rate = 0.1) # 训练参数 predict_data(weight, b) # 根据训练的参数进行预测
这里有一点需要注意,在构造矩阵的时候"test_data_x = test_data_x.reshape(example_count, row_count).T"并不等价于"test_data_x = test_data_x.reshape(row_count,example_count)",如果直接用第二个语句,则会打乱原来每个样例的数据,构造的矩阵毫无实际意义。
在该测试样例中,训练时大概需要迭代600多次即可收敛,最后预测的准确率约为:72%。