基于神经网络的二分类问题

来源:互联网 发布:英文小说推荐 知乎 编辑:程序博客网 时间:2024/06/08 17:59

       在之前的文章中,介绍了神经网络的概念和算法思想,甚至给出了公式推导。但依然没有掌握神经网络的精髓,于是打算进一步学习就在网上观看了吴恩达大佬的《神经网络和深度学习》这门课程,觉得收获很大。目前只学习了单个神经元的原理及应用,下面简单总结一下。


1. 损失函数的定义


       与之前介绍的单个神经元的工作原理不同之处在于损失函数的定义,这里把损失函数定义为:


       推导思路:利用最大似然估计。先表达出p(y|x),然后求其最大值。大致推导过程如下:



        课程中另一个重点是“消除for循环”,也就是说用向量来代替显示的for循环,这样做的好处是提高计算效率。实验测试100万条测试数据,向量化要比循环快上300倍。因此在以后的编码中,尽量把数据初始化成一个矩阵来处理。在这里值得注意的是,构造的矩阵应该每一列表示一个测试样例。


2. 代码实现


        下面给出基于神经网络的二分类代码(python):

import numpy as npimport h5pyimport 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, classesdef 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, bdef 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%。