深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)

一、神经网络的表示


上一个教程中已经详细介绍了Logistic Regression模型,神经网络其实就是多个 Logistic Regression模型的组合,每个功能层(含有激活函数的层)中的每个神经元都对应一个Logistic Regression模型。在下面的例子中,神经网络只含有一个隐层,单个输入样本 x 经过第一层的线性处理和非线性映射,得到了z1和 a1,随后将 a1 作为第二层(输出层)的输入,依次计算 z2 和 a2 ,a2即为我们最终的输出,最后计算损失函数,这就是一个完整的正向传播过程。我们可以看到这里有两次激活函数的使用,两个激活函数可以相同也可以不同。

深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第1张图片

接下来通过另一个例子具体来表示单隐层的神经网络,依次分别计算各层各个神经元的输出:

深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第2张图片


从上面的例子中可以看出,我们针对某一层分别计算单个神经元的输出是非常低效的,在具体的编程中需要通过for循环来实现,那么我们尝试将上述方程组转堆叠到一起来计算:
深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第3张图片

最终我们将单层的计算过程向量化(需要特别注意的是每个向量的shape,因为向量乘法对两个向量的shape有要求,不熟悉的可以顺着推导下),得到如下的表达形式:

深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第4张图片

二、向量化加速


上面只是对单层进行了向量化,但实际上我们的输入的样本不只一个,依次计算每个样本的输出也是一个for循环过程,因此我们考虑将所有样本 x 堆叠到一个向量 X 里作为输入,后续各个中间向量z,a和最终结果向量的shape也会相应变化,下面例子中大写字母均为向量。

深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第5张图片


三、激活函数


常用的激活函数有sigmoid函数,tanh函数,relu函数等。对于二分类问题,一般在中间各层采用tanh函数或者relu函数,而在输出层采用sigmoid函数,其他非二分类的情况绝对不要用。如果不采用激活函数,那么神经网络只是把输入数据进行线性组合再输出,对于深度神经网络,如果使用线性激活函数(梯度为固定值)或者没有激活函数,那么无论你的神经网络有多少层,它所在做的只是计算线性激活函数,所以添加再多的隐层也都是在做无用功。

深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第6张图片

深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第7张图片

深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第8张图片
深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第9张图片

四、神经网络的梯度下降


深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第10张图片

深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第11张图片

五、随机初始化


对于Logistic Regression我们可以以零作为初始值,但是对于神经网络则不能,因为权重参数设置为零时,所有的隐藏单元都是对称的,不管你跑多久梯度下降,它们都在计算完全一样的函数。我们实际建立神经网络模型时,希望隐层的每个神经单元都是不同的,这样才能保证我们能去计算不同的函数。一般采用如下方式来初始化权重向量:

深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第12张图片
这里所乘的0.01是一个经验参数(可以自己试验确定),只是用来将权重参数初始化成非常小非常小的随机值。因为如果你用的tanh或者sigmoid激活函数,当权重太大,所计算的激活函数值极有可能落在tanh或者sigmoid函数的平缓部分(接近饱和),这也意味着梯度下降法会非常慢,所以学习会很慢。

六、实现代码


这次测试的数据和上次Logistic Regression一样,也是对猫图像进行分类识别的,数据为RGB三通道 图像,大小为64*64,训练集209张,验证集50张。这里设计了一个单隐层的神经网络,隐层神经单元为20个,激活函数为tanh,输出层神经单元个数为1,激活函数为sigmoid。

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

# Input data
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()
train_num = train_set_x_orig.shape[0]
test_num = test_set_x_orig.shape[0]
pix_num = train_set_x_orig.shape[1]
chanel_num = train_set_x_orig.shape[3]
print('\n' + '---------------Input information---------------' + '\n')
print('train_set_x_orig.shape = ' + str(train_set_x_orig.shape))
print('train_set_y.shape = ' + str(train_set_y.shape))
print('test_set_x_orig.shape = ' + str(test_set_x_orig.shape))
print('test_set_y.shape = ' + str(test_set_y.shape))
print('train_num = ' + str(train_num))
print('test_num = ' + str(test_num))
print('pix_num = ' + str(pix_num))
print('chanel_num = ' + str(chanel_num))

# Reshape data
train_set_x_flat = train_set_x_orig.reshape(train_num,-1).T
test_set_x_flat = test_set_x_orig.reshape(test_num,-1).T
print('\n' + '---------------After reshaping---------------' + '\n')
print('train_set_x_flat = ' + str(train_set_x_flat.shape))
print('test_set_x_flat = ' + str(train_set_x_flat.shape))

# Standarize data
train_set_x = train_set_x_flat/255.0
test_set_x = test_set_x_flat/255.0
print('\n' + '---------------After Standaring---------------' + '\n')
print('Check for traindata = ' + str(train_set_x[0:5,0]))
print('Check for testdata = ' + str(test_set_x[0:5,0])) 

def tanh(x):
    s = (np.exp(x)-np.exp(-x))/((np.exp(x)+np.exp(-x)))
    return s

def tanh_prime(x):
    s = 1 - np.power(tanh(x), 2)
    return s

def sigmoid(x):
    s = 1/(1+ np.exp(-x))
    return s

def sigmoid_prime(x):
    s = sigmoid(x)*(1 - sigmoid(x))
    return s

def relu(Z):
    s = np.maximum(0,Z)
    return s

def relu_prime(Z):
    s = Z
    s[Z <= 0] = 0
    s[Z>0]=1
    return s
    
def initial_weights(input, hidden, output, m):
    np.random.seed(3)
    w1 = np.random.randn(hidden,input)* 0.01
    b1 = np.zeros((hidden,1))
    w2 = np.random.randn(output,hidden)* 0.01
    b2 = np.zeros((output,1))
    return w1,b1,w2,b2

def train(X,y,hidden=20,learning_rate=0.01,itr_num=3000,isprint=True):
    h_i = X.shape[0]
    m = X.shape[1]
    h_o = y.shape[0]
    h_h = hidden
    w1,b1,w2,b2 = initial_weights(h_i, h_h, h_o, m)
    costs = []
    for i in range(itr_num):
        # Forward
        A1 = tanh(np.dot(w1, X) + b1)  # h_h * m
        A2 = sigmoid(np.dot(w2,A1) + b2)                 # h_o * m
        cost =  -(1.0/m)*np.sum(y*np.log(A2)+(1-y)*np.log(1-A2))
    
        # Backword
        dz2 = A2 - y
        dw2 = (1.0/m)*np.dot(dz2 , A1.T)
        db2 = (1.0/m)*np.sum(dz2, axis=1,keepdims=True)
    
        dz1 = np.dot(w2.T,dz2)*tanh_prime(np.dot(w1, X) + b1)  # h_h * m
        dw1 = (1.0/m)*np.dot(dz1, X.T)
        db1 = (1.0/m)*np.sum(dz1, axis=1,keepdims=True)
    
        # Update weights
        w1 = w1 - learning_rate*dw1
        b1 = b1 - learning_rate*db1
        w2 = w2 - learning_rate*dw2
        b2 = b2 - learning_rate*db2
        
        if isprint and  i % 100 ==0:
            print('cost after ' + str(i) + ' iteration is :' + str(cost))
        if i%100 ==0: 
            costs.append(cost)
    d = {"w1":w1,"b1":b1,"w2":w2,"b2":b2,"costs":costs,"learning_rate":learning_rate}
    costs = np.squeeze(costs)
    plt.plot(costs)
    plt.ylabel('cost')
    plt.xlabel('Iteration(per hundreds)')
    plt.title("Learning rate=" + str(d["learning_rate"]))
    plt.show()
    return d

def predict(X,y,d):
    w1 = d["w1"] 
    b1 =d["b1"]
    w2 =d["w2"]
    b2 =d["b2"]
    nx = X.shape[0]
    m = X.shape[1]
    Y_prediction = np.zeros((1,m))
    A1 = relu(np.dot(w1, X) + b1)  
    prob = sigmoid(np.dot(w2,A1) + b2)
    for i in range(m):
        if prob[0,i] > 0.5:
            Y_prediction[0,i]  = 1
        else:
            Y_prediction[0,i] = 0
    print("accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction - y)) * 100))
    return Y_prediction

model = train(train_set_x,train_set_y,hidden=20,learning_rate=0.01,itr_num=3000)
y = predict(test_set_x,test_set_y,model)
深度学习与神经网络-吴恩达(Part1Week3)-单隐层神经网络编程实现(python)_第13张图片




你可能感兴趣的:(人工智能,深度学习,神经网络,吴恩达,python,算法)