本文主要是介绍deeplearning.ai 吴恩达网上课程学习(四)——Logistic代码实战,基于Linux,Python 3.4,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
此文章偏向于实践和自己的理解,本文讲述了Python代码的一些基本操作,由浅入深最后实现logistic的代码。(原文中代码实现基于jupyter notebook,文中代码实现基于之前搭建的Linux的Python平台,二者代码会有细小的区别。
搭建平台的链接深度学习(一):搭建TensorFlow)
原创内容来自:
https://www.missshi.cn/api/view/blog/59aa08fee519f50d04000170
一、使用numpy构建基本函数(numpy是Python在科学计算中最常用的库)
练习1:利用np.exp()实现sigmod函数:
np.exp和math.exp()的区别:
math.exp()只对标量(有些物理量,只具有数值大小,而没有方向)执行,np.exp可用于向量或者矩阵。
所以,具体实现一个真正的、可用于矢量或矩阵的sigmod函数:
sigmod函数,可用于矢量和矩阵
import numpy as np
def sigmod(x):s = 1.0 / (1 + np.exp(-x))return s
x = np.array([0,1, 2, 3])
print sigmod(x)
#注意最后一步原文中写错了
[ 0.73105858, 0.88079708, 0.95257413]练习2:计算sigmod函数的导数
sigmod函数的导数公式:
import numpy as np
def sigmoid_derivative(x):s = 1.0 / (1 + 1 / np.exp(x))ds = s * (1 - s) return ds
x = np.array([1, 2, 3])
print "sigmoid_derivative(x) = " + str(sigmoid_derivative(x))
sigmoid_derivative(x) = [0.19661193 0.10499359 0.04517666]
练习3:将一副图像转为为一个向量
在numpy中,有两个常用的函数:np.shape和np.reshape()。其中,X.shape可以用于查看当前矩阵的维度。X.reshape()可以用于修改矩阵的维度或形状。
例如,对于一副彩色图像,其通常是由一个三维矩阵组成的(RGB三个通道),我们通常需要将其转换为一个矢量,其长度为3*length*width。
import numpy as np
def image2vector(image):v = image.reshape((image.shape[0] * image.shape[1] * image.shape[2], 1))return vimage = np.array([[[ 0.67826139, 0.29380381],[ 0.90714982, 0.52835647],[ 0.4215251 , 0.45017551]],[[ 0.92814219, 0.96677647],[ 0.85304703, 0.52351845],[ 0.19981397, 0.27417313]],[[ 0.60659855, 0.00533165],[ 0.10820313, 0.49978937],[ 0.34144279, 0.94630077]]])print "image2vector(image) = " + str(image2vector(image))
练习4:按行归一化:数据进行归一化后,梯度下降算法的收敛速度会明显加快。
下面对一个矩阵进行按行归一化,归一化后的结果是每一个的长度为1。
import numpy as np
def normalizeRows(x):x_norm = np.linalg.norm(x, axis=1, keepdims = True) #归一化,见下面函数解释x = x / x_norm #利用numpy的广播,用矩阵与列向量相除。return xx = np.array([[0, 3, 4],[1, 6, 4]])
print "normalizeRows(x) = " + str(normalizeRows(x))
关于 np.linalg.norm:参考https://blog.csdn.net/hqh131360239/article/details/79061535
练习5:广播的使用及softmax函数的实现
广播能帮助我们对不同维度的矩阵、向量、标量之前快速计算。
import numpy as np
def softmax(x):x_exp = np.exp(x) x_sum = np.sum(x_exp, axis = 1, keepdims = True) s = x_exp/x_sum return sx = np.array([[9, 2, 5, 0, 0],[7, 5, 0, 0 ,0]])
print "softmax(x) = " + str(softmax(x)
# softmax(x) = [[ 9.80897665e-01 8.94462891e-04 1.79657674e-02 1.21052389e-04 1.21052389e-04] [ 8.78679856e-01 1.18916387e-01 8.01252314e-04 8.01252314e-04 8.01252314e-04]]
矢量化:
练习1:L1误差函数的实现
import numpy as np
def L1(yhat, y):loss = np.sum(np.abs(y - yhat))return lossyhat = np.array([.9, 0.2, 0.1, .4, .9])
y = np.array([1, 0, 0, 1, 1])
print "L1 = " + str(L1(yhat,y))
# L1 = 1.1练习2:L2误差函数的实现
import numpy as np
def L2(yhat, y):loss = np.sum(np.power((y - yhat), 2))return lossyhat = np.array([.9, 0.2, 0.1, .4, .9])
y = np.array([1, 0, 0, 1, 1])
print "L2 = " + str(L2(yhat,y))
# L2 = 0.43
Logistic的实现:
包括:初始化、计算代价函数和梯度、使用梯度下降算法进行优化等并把他们整合成为一个函数。
本实验用于通过训练来判断一副图像是否为猫。
1. 引入相关库文件:
import numpy as np
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage%matplotlib inline #设置matplotlib在行内显示图片
上面是基于jupyter notebook的代码,在之前搭建的TensorFlow平台不可用。
()如果出现import 库报错,请进行下列的步骤,如果没有,可以跳过:
下面就要安装对应的库:
① 安装matplotlib库,Ctrl+Alt+T键调出终端,输入
sudo apt-get install python-matplotlib
② 安装h5py的库,Ctrl+Alt+T键调出终端,输入:
sudo apt-get install libhdf5-dev
sudo apt-get install python-h5py
③安装scipy:
sudo apt-get install python-scipy
%matplotlib inline是jupyter notebook里的命令, 意思是将那些用matplotlib绘制的图显示在页面里而不是弹出一个窗口
此时在py文件中写入代码:
import numpy as np
import h5py
import matplotlib.pyplot as plt
import scipy
from PIL import Image
from scipy import ndimage
2. 读取数据和预处理:
在训练之前,首先要读取数据,数据来源:http://www.missshi.cn/#/books搜索train_catvnoncat.h5和test_catvnoncat.h5进行下载,尊重原创:
代码如下:(下载数据后注意更改数据文件名称(和原文代码有区别))
def load_dataset():train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r") #读取H5文件train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set featurestrain_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labelstest_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set featurestest_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labelsclasses = np.array(test_dataset["list_classes"][:]) # the list of classestrain_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0])) #对训练集和测试集标签进行reshapetest_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, classestrain_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes = load_dataset()
数据说明:(和原文代码有区别)
index = 25
plt.imshow(train_set_x_orig[index])
plt.show() #plt.imshow()函数负责对图像进行处理,并显示其格式,而plt.show()则是将plt.imshow()处理后的函数显示出来。
print "y = " + str(train_set_y_orig[:, index]) + ", it's a '" + classes[np.squeeze(train_set_y_orig[:, index])].decode("utf-8") + "' picture."
x1 = np.squeeze(x) # 从数组的形状中删除单维条目,即把shape中为1的维度去掉
关闭图像显示结果:
# y = [1], it's a 'cat' picture.
我们先看看我们得到的是怎么样的数据:(和原文代码有区别)
m_train_x = train_set_x_orig.shape
m_test_x = test_set_x_orig.shape
m_train_y = train_set_y_orig.shape
m_test_y = test_set_y_orig.shape
print "m_train_x" + str(m_train_x)
print "m_test_x" + str(m_test_x)
print "m_train_y" + str(m_train_y)
print "m_test_y" + str(m_test_y)
得到的结果:
也就是我们的训练集train_x有209张照片,每张照片是RGB的,为64*64*3.训练集的train_y是个1*209的list表示的是训练集标签(0或者1);我们的测试集test_x有50张照片,每张照片是RGB的,为64*64*3.测试集的test_y是个1*50的list表示的是测试集标签(0或者1);
我们也可以根据需要计算出训练集的大小、测试集的大小以及图片的大小:
m_train = train_set_x_orig.shape[0]
m_test = test_set_x_orig.shape[0]
num_px = train_set_x_orig.shape[1]
print (m_train, m_test, num_px)
#结果 209, 50, 64
train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T
3. Logistic的结构:
先粘过来上节课的伪代码流程图:
Step1:实现sigmod函数
def sigmoid(z):s = 1.0 / (1 + 1 / np.exp(z))return s
Step2:初始化参数def initialize_with_zeros(dim):w = np.zeros((dim, 1))b = 0return w, b
Step3:前向传播与反向传播
def propagate(w, b, X, Y):m = X.shape[1]# FORWARD PROPAGATION (FROM X TO COST)A = sigmoid(np.dot(w.T, X) + b) # compute activationcost = -1.0 / m * np.sum(Y * np.log(A) + (1.0 - Y) * np.log(1.0 - A)) # compute cost# BACKWARD PROPAGATION (TO FIND GRAD)dw = 1.0 / m * np.dot(X, (A - Y).T) #整除运算,需要将1改为1.0,否则运算结果全部为0db = 1.0 / m * np.sum(A - Y)cost = np.squeeze(cost)grads = {"dw": dw,"db": db}return grads, cost
Step4:更新参数
def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):costs = [] for i in range(num_iterations): #每次迭代循环一次, num_iterations为迭代次数# Cost and gradient calculation grads, cost = propagate(w, b, X, Y)# Retrieve derivatives from gradsdw = grads["dw"]db = grads["db"]# update rule w = w - learning_rate * dwb = b - learning_rate * db# Record the costsif i % 100 == 0:costs.append(cost)# Print the cost every 100 training examplesif 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
Step5:利用训练好的模型对测试集进行预测:
首先理解下shape这个函数:
比如2*3的矩阵:
def predict(w, b, X):m = X.shape[1]Y_prediction = np.zeros((1,m))w = w.reshape(X.shape[0], 1)# Compute vector "A" predicting the probabilities of a cat being present in the pictureA = sigmoid(np.dot(w.T, X) + b)for i in range(A.shape[1]):# Convert probabilities A[0,i] to actual predictions p[0,i]if A[0][i] > 0.5:Y_prediction[0][i] = 1else:Y_prediction[0][i] = 0return Y_prediction
Step6:将以上功能整合到一个模型中:
def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):# initialize parameters with zeros w, b = initialize_with_zeros(X_train.shape[0])# Gradient descentparameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)# Retrieve parameters w and b from dictionary "parameters"w = parameters["w"]b = parameters["b"]# Predict test/train set examples Y_prediction_test = predict(w, b, X_test)Y_prediction_train = predict(w, b, X_train)# Print train/test Errorsprint("train accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100))print("test accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100))d = {"costs": costs,"Y_prediction_test": Y_prediction_test, "Y_prediction_train" : Y_prediction_train, "w" : w, "b" : b,"learning_rate" : learning_rate,"num_iterations": num_iterations}return d
Step7:模型测试:
#前边定义的所有函数
。。。此处省略
#数据输入(和原文代码有区别)
train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes = load_dataset()#数据输入train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T #数据预处理
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).Ttrain_set_x = train_set_x_flatten/255. #归一化
test_set_x = test_set_x_flatten/255.
m_train = train_set_x_orig.shape[0] #获得一些大小参数
m_test = test_set_x_orig.shape[0]
num_px = train_set_x_orig.shape[1]
#调用模型
d = model(train_set_x, train_set_y_orig, test_set_x, test_set_y_orig, num_iterations = 2000, learning_rate = 0.005, print_cost = True)
注意原博客中数据带入有错误,请自行改正。结果:
下面挑选其中的一些图片来看我们的预测结果:(和原文代码有区别)
index = 14
plt.imshow(test_set_x[:,index].reshape((num_px, num_px, 3)))
plt.show()
print ("y = " + str(test_set_y_orig[0,index]) + ", you predicted that it is a \"" + classes[int(d["Y_prediction_test"][0,index])].decode("utf-8") + "\" picture.")
Step8:画出代价函数变化曲线:
costs = np.squeeze(d['costs'])
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations (per hundreds)')
plt.title("Learning rate =" + str(d["learning_rate"]))
plt.show()
Step9:学习速率对最终的结果的影响
learning_rates = [0.01, 0.001, 0.0001]
models = {}
for i in learning_rates:print ("learning rate is: " + str(i))models[str(i)] = model(train_set_x, train_set_y_orig, test_set_x, test_set_y_orig, num_iterations = 1500, learning_rate = i, print_cost = False)print ('\n' + "-------------------------------------------------------" + '\n')for i in learning_rates:plt.plot(np.squeeze(models[str(i)]["costs"]), label= str(models[str(i)]["learning_rate"]))plt.ylabel('cost')
plt.xlabel('iterations')legend = plt.legend(loc='upper center', shadow=True)
frame = legend.get_frame()
frame.set_facecolor('0.90')
plt.show()
结果:
Step10:用一副你自己的图像,而不是训练集或测试集中的图像进行分类:
## START CODE HERE ## (PUT YOUR IMAGE NAME)
my_image = "Penguins.jpg" # change this to the name of your image file
## END CODE HERE ### We preprocess the image to fit your algorithm.
fname = "image/" + my_image
image = np.array(plt.imread(fname, flatten=False)) #读取图片
my_image = scipy.misc.imresize(image, size=(num_px,num_px)).reshape((1, num_px*num_px*3)).T #放缩图像
my_predicted_image = predict(d["w"], d["b"], my_image) #预测plt.imshow(image)
print("y = " + str(np.squeeze(my_predicted_image)) + ", your algorithm predicts a \"" + classes[int(np.squeeze(my_predicted_image)),].decode("utf-8") + "\" picture.")
如果用个cat.jpg:
imread在1.2.0版本用imageio.imread代替
Read an image from a file as an array.从文件中把图片读成数组
This function is only available if Python Imaging Library (PIL) is installed.该功能只在安装了PIL情况下使用
imresize功能将在1.2.0版本中,被skimage.transform.resize取代
Resize an image.调整图片大小
This function is only available if Python Imaging Library (PIL) is installed.该功能只在安装了PIL情况下使用
这篇关于deeplearning.ai 吴恩达网上课程学习(四)——Logistic代码实战,基于Linux,Python 3.4的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!