手工搭建一层感知器线性回归网络(神经网络)

1. numpy预备知识

1.1 点乘(*)和矩阵相乘(np.dot)
  • * 代表矩阵对应元素相乘,要求两个矩阵行数和列数都相同
  • np.dot(matrix_1, matrix_2)是数学中的矩阵相乘,要求第一个矩阵的列数等于第二个矩阵的行数
Y = np.array([[1],[2],[3]])
Y*Y  # array([[1],[4],[9]])
1.2 reshape()

假设一组图片的训练集数据matrix.shape=(209,64,64,3), 其中209代表训练集个数,64代表图片长度和宽度像素点,3代表RGB三个通道把它转化为二位矩阵,使其维度为(64*64*3,209),那么:

matrix.reshape(209,-1).T  # 转化为209行,不管多少列。 然后在进行矩阵转置
matrix.reshape(-1,209)   # 这种是错误的转换方式:第一行209个数据全是第一张照片的数据!

2. 算法介绍

构造 z = w1x1+w2x2+w3x3+…+wnxn+b,进行多次前向传播反向传递,修正参数

注释

  • n代表一条训练数据的维度,即一条数据可以看作一个n维向量
  • m代表训练集或测试集的数据条数,可以说这样说:”这个训练集有m条数据“
  • z代表一个结果值,而Z表示训练集或测试集结果值,维度为(1, m)
  • 以下公式点乘 ‘*’ 显式写出来,其它为数学中矩阵相乘的形式

2.1 参数初始化

令 w = [0, 0, 0, … 0]T,b = 0,其中w为矩阵(向量),维度为(n, 1)

2.2 进行一次前向传播(propagate)

目的:获得当前w和b数值下的损失函数cost(记为L), 获得梯度 d L d w 、 d L d b \frac{dL}{dw}、\frac{dL}{db} dwdLdbdL(记为dw、db)以在反向传播过程中修正参数
KaTeX parse error: Undefined control sequence: \ at position 209: …+(1-Y)*ln(1-A)]\̲ ̲
注释

  • Y:真实值,维度为(m, 1)
  • A:预测值,维度也为(m, 1), A = sigmoid(Z) = sigmoid(wTX + b)

∗ ∗ ( 2 ) 梯 度 d L d w 、 d L d b ( d w 、 d b ) 的 计 算 ∗ ∗ 矩 阵 表 达 ( 代 码 中 使 用 ) : d w = 1 m X ( A − Y ) 矩 阵 表 达 ( 代 码 中 使 用 ) : d b = 1 m ∑ i = 1 m ( A − Y ) **\bold{(2)梯度\frac{dL}{dw}、\frac{dL}{db}(dw、db)的计算}**\\ 矩阵表达(代码中使用):dw=\frac{1}{m}X(A-Y)\\ 矩阵表达(代码中使用):db=\frac{1}{m}\sum_{i=1}^{m}(A-Y) (2)dwdLdbdL(dwdb)(使):dw=m1X(AY)(使):db=m1i=1m(AY)

dw的推导过程(利用求导链式法则):
已 知 : L ( a , y ) = − [ y l n a + ( 1 − y ) l n ( 1 − a ) ] a = s i g m o i d ( z ) = 1 1 + e − z z = w 1 x 1 + w 2 x 2 + . . . 则 d w 1 = d L d w 1 = d L d a d a d z d z d w 1 = ( a − y ) x 1 d w 2 = d L d w 2 = d L d a d a d z d z d w 2 = ( a − y ) x 2 . . . . . . 对 于 每 个 样 本 计 算 出 来 的 d w 1 进 行 累 加 再 除 以 样 本 数 m 取 平 均 值 作 为 最 终 值 即 d w 1 = 1 m ∑ 1 m d w 1 , d w 2 = 1 m ∑ 1 m d w 2 . . . 故 转 化 为 矩 阵 形 式 : d w = 1 m X ( A − Y ) 已知:L(a,y)=-[ylna+(1-y)ln(1-a)] \\ a=sigmoid(z)=\frac{1}{1+e^{-z}} \\ z=w_1x^1+w_2x^2+... \\ 则dw_1=\frac{dL}{dw_1}=\frac{dL}{da}\frac{da}{dz}\frac{dz}{dw_1}=(a-y)x^1\\ dw_2=\frac{dL}{dw_2}=\frac{dL}{da}\frac{da}{dz}\frac{dz}{dw_2}=(a-y)x^2\\ ......\\ 对于每个样本计算出来的dw_1进行累加再除以样本数m取平均值作为最终值\\ 即dw_1=\frac{1}{m}\sum_{1}^{m}dw_1,dw_2=\frac{1}{m}\sum_{1}^{m}dw_2...\\ 故转化为矩阵形式:dw=\frac{1}{m}X(A-Y)\\ :L(a,y)=[ylna+(1y)ln(1a)]a=sigmoid(z)=1+ez1z=w1x1+w2x2+...dw1=dw1dL=dadLdzdadw1dz=(ay)x1dw2=dw2dL=dadLdzdadw2dz=(ay)x2......dw1mdw1=m11mdw1,dw2=m11mdw2...:dw=m1X(AY)

2.3 进行一次反向传播(optimize)

目的:根据上一步算出的dw、db对 w 和 b 进行优化
w = w − α ∗ d w b = b − α ∗ d b α : 学 习 速 率 w=w-\alpha*dw\\ b=b-\alpha*db\\ \alpha:学习速率 w=wαdwb=bαdbα:

2.4 进行多次正向传播和反向传播

eg. 附一张吴恩达老师的图

在这里插入图片描述

=====================>

代码

import numpy as np
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage
from lr_utils import load_dataset

%matplotlib inline

1. 数据获取和整理

1.1 数据读取
train_file = h5py.File('./datasets/train_catvnoncat.h5')  # 训练集
print(train_file.keys())  # 获取文件的键
train_org_x = np.array(train_file["train_set_x"][:]) # 获取train_set_x并转化为array
train_org_y = np.array(train_file["train_set_y"][:]) 
test_file = h5py.File('./datasets/test_catvnoncat.h5') # 测试集
print(test_file.keys())
test_org_x = np.array(test_file["test_set_x"][:]) # 获取train_set_x并转化为array
test_org_y = np.array(test_file["test_set_y"][:]) 

print(train_org_x.shape)
print(train_org_y.shape)
print(test_org_x.shape)
(209, 64, 64, 3)
(209,)
(50, 64, 64, 3)
  • (209,)这种格式并不好,一般我们将其转化为(209,1)这种格式
train_y = train_org_y.reshape(-1,1)  # 不管多少行,但是仅一列
test_y = test_org_y.reshape(-1,1)   
train_y.shape
(209, 1)
1.2 reshape转化为需要的格式
train_x = train_org_x.reshape(209,-1).T
test__x = test_org_x.reshape(50,-1).T
train_x.shape
(12288, 209)
train_x = train_x / 255
test_x = test__x / 255

2. 参数初始化

def init(dim):
    w = np.zeros((dim,1))
    b = 0
    return w,b

3.一次前向传播

sigmoid函数

def sigmoid(Z):
    A = 1.0 / (1.0 + np.exp(-1.0 * Z))
    return A

前向传播

def propagate(w, b, X, Y):  # 参数:train_x train_y w b
    m = X.shape[1]    
    A = sigmoid(np.dot(w.T,X) + b).T
    
    cost = -(1.0 / m) * np.sum(Y*np.log(A) + (1-Y)*np.log(1-A))
    
    dw = (1 / m) * np.dot(X, (A - Y))   # 梯度dw, 这里A和Y都是(209,1)
    db = (1 / m) * np.sum(A - Y)   #  梯度db
    
    assert(dw.shape == w.shape)  
        
    return cost, dw, db   # 返回损失值,梯度(dw、db)

4. 反向传播

def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):   
    costs = []
    
    for i in range(num_iterations): 
        cost, dw, db = propagate(w, b, X, Y)
        
        w = w - learning_rate * dw
        b = b - learning_rate * db
        
        if i % 100 == 0:
            costs.append(cost)
        
        if print_cost and i % 100 == 0:
            print ("Cost after iteration %i: %f" %(i, cost))
    
    params = {"w": w,
              "b": b}
    
    grads = {"dw": dw,
             "db": db}
    
    return params, grads, costs

5. 模型训练

w, b =init(train_x.shape[0])   
params, grads, costs = optimize(w, b, train_x, train_y, num_iterations=2000, learning_rate=0.005)   
w = params['w']
b = params['b']
# 测试集预测
def predict(w, b, X):
  
    m = X.shape[1]
    Y_prediction = np.zeros((1,m))
    w = w.reshape(X.shape[0], 1)
   
    A = sigmoid(np.dot(w.T,X) + b)
    
    for i in range(A.shape[1]):
        if A[0, i] >0.5:
            Y_prediction[0,i] = 1
        else:
            Y_prediction[0,i] = 0        
    
    assert(Y_prediction.shape == (1, m))
    return Y_prediction
Y_prediction_train = predict(w, b, train_x)
Y_prediction_test = predict(w,b, test_x)
print("train accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_train - train_y.T)) * 100))
print("test accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_test - test_y.T)) * 100))
train accuracy: 99.04306220095694 %
test accuracy: 70.0 %
plt.plot(costs)    # 在训练集上的损失值变化

在这里插入图片描述

数据集在这:===>
github数据集

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值