手写神经网络

要求

  用Python中numpy库手写一个单层神经网络(严格来说是用逻辑回归做二分类问题),用GD(Gradient Descent)作为optimizer。

 

Gradient Descent

  见西瓜书

 

Stochastic Gradient Descent

  相当于每次只随机挑出一条数据forward然后优化,其他和Gradient Descent基本一样

 

代码要点

  熟悉numpy相关的函数接口

    np.random.randn()  #产生符合高斯分布的随机数

    np.random.randint()  #产生随机整数

    np.around()  #四舍五入,相当于round()

    np.dot()  #向量乘法,点乘用*

    np.sum()  #求和,可以用于向量求和

  训练流程

    1. data preparation

    2. forward data to model

    3. compute loss  #其实自己写的时候不算loss也是可以的,只要对其求导就可以了

    4. optimize  #使用各种优化算法,更新参数

    5. predict  #测试

    (如果有分batch的话还有这一步需要准备)

import numpy as np

# generate x in [100, 4], which follows the Gaussian distribution 
# y = round(sigmoid(x*w+b)) w = [0.3, 0.6, -0.7, -1.3] b = 0.2

# Given x, y, use GD(SGD); get [w,b]

# two class logistic regression


def sigmoid(x, derivative = False):
    sigm = 1 / (1 + np.exp(-x))
    if derivative:
        return sigm * (1 - sigm)
    return sigm

def generate_data(x):
    w = np.array([0.3, 0.6, -0.7, -1.3])
    b = np.array(0.2)
    y = np.around(sigmoid(np.dot(x,w)+b))
    return y

def forward(x, w, b):
    return sigmoid(np.dot(x,w)+b)

def compute_loss(y_, y):
    m = y_.shape[0]
    assert m == y.shape[0]
    return -1/m * np.sum(y * np.log(y_) + (1 - y) * np.log(1 - y_))

def GD_optimizer(w, b, x, y, y_, lr=0.01):
    # backpropagate
    m = y.shape[0]
    dw = - 1/m * np.dot((y - y_), x)
    db = - 1/m * np.sum(y- y_)
    # renew parameter
    w = w - lr * dw
    b = b - lr * db
    return w, b
        
def predict(w, b):
    x_test = np.random.randn(200,4)
    y_test = generate_data(x_test)
    y_ = np.around(forward(x_test, w, b))
    acc = np.sum(y_test == y_) / 200
    print("acc:", acc)

if __name__ == "__main__":
    # initialization
    x = np.random.randn(1000,4)
    w = np.random.randn(4)
    b = np.zeros((1))
    y = generate_data(x)

    iter_num = 5001

    #train
    for i in range(iter_num):
        # forward
        y_ = forward(x, w, b)
        # compute loss
        loss = compute_loss(y_, y)
        # renew parameter
        w, b = GD_optimizer(w, b, x, y, y_)
        # print info
        if i % 100 == 0:
            print("loss after iteration {}: {}".format(i, loss) )
            predict(w, b)

    print("w:", w)
    print("b:", b)
    predict(w, b)

 

其他变种

改为softmax多分类

  将损失函数改为对softmax交叉熵的loss,optimize中求导的地方也要稍微改改

改为SGD(随机梯度下降)optimizer

  每个epoch都先用np.random.shuffle()打乱数据,然后再每次forward一条数据进行optimize,相当于loss不求平均,而是只有一条数据的loss

改为多层神经网络

  参数变多,求导的地方也会变得复杂一些

 

softmax分类损失函数求导:

1. https://blog.csdn.net/wangyangzhizhou/article/details/75088106

2. https://blog.csdn.net/qian99/article/details/78046329

 

逻辑回归损失函数求导:(和softmax基本差不多)

https://www.cnblogs.com/zhongmiaozhimen/p/6155093.html

 

posted @ 2019-03-12 21:59  sbj123456789  阅读(474)  评论(0编辑  收藏  举报