Logistic Regression with a Neural Network mindset
阿新 • • 發佈:2021-06-16
文章內容為吳恩達深度學習第二週的程式設計作業
**ipynbg格式程式碼及資料集-->陳能豆 **
密碼: o1bn
#!/usr/bin/env python # coding: utf-8 # # 吳恩達深度學習第二週程式設計作業 # ## 題目部分 # 先來看一下 英文的題目部分 # Logistic Regression with a Neural Network mindset # Welcome to your first (required) programming assignment! You will build a logistic regression classifier to recognize cats. This assignment will step you through how to do this with a Neural Network mindset, and so will also hone your intuitions about deep learning. # # Instructions: # # Do not use loops (for/while) in your code, unless the instructions explicitly ask you to do so. # You will learn to: # # Build the general architecture of a learning algorithm, including: # Initializing parameters # Calculating the cost function and its gradient # Using an optimization algorithm (gradient descent) # Gather all three functions above into a main model function, in the right order. # ### 簡單解釋一下要求 # 要求我們建議一個邏輯迴歸分類器來識別貓的圖片 # # #### 要求如下: # * 不要在程式碼中使用迴圈(for/while),除非指令明確要求您這樣做。 # # * 演算法的架構如下: # 1. 引數初始化 # 2. 成本函式及梯度的計算 # 3. 優化演算法 # # 你需要編寫上面提到的方法,並進行組合,成為一個模型 # # #### 資料集概述 # 這裡會提供給我們一個數據集,名字為”data.h5“(和下面程式碼用的是同一個資料集,不過名字改成了”train_catvnoncat.h5“) # 裡面包含了相關資料集,更具體的可以看程式碼的資料匯入方法。 # 主要包括: # 1. 標籤設定好的訓練集,標記是否為cat(0/1) # 2. 標籤設定好的測試集 # 3. 圖片的形狀為(64, 64, 3) # # # 資料集及程式碼附上鍊接--> [陳能豆](https://pan.baidu.com/s/1VMCuVU8IKWLycKM6B20O_g) # 提取密碼:q73d # # #### ok 下面看程式碼 # # In[98]: # pip --version # 這裡看一下python的版本 ,3.6 以及別的版本應該也是可行的 # ### 程式碼部分 # #### 程式碼段後面附上相關重點提示 # #### 相關函式用法 不會的百度 # In[197]: import numpy as np import matplotlib.pyplot as plt import h5py import random # 下面兩個用於測試模型 from PIL import Image import imageio # 匯入相關包 # In[198]: # 匯入資料函式 def load_datasets(): train_datasets = h5py.File('datasets/train_catvnoncat.h5',"r") train_set_x_origi = np.array(train_datasets["train_set_x"][:]) train_set_y_origi = np.array(train_datasets["train_set_y"][:]) # 讀取訓練集 test_datasets = h5py.File('datasets/test_catvnoncat.h5',"r") test_set_x_origi = np.array(test_datasets["test_set_x"][:]) test_set_y_origi = np.array(test_datasets["test_set_y"][:]) # 測試集 classes = np.array(test_datasets["list_classes"][:]) # 儲存可能的結果 0 non-cat 1 cat # 初始化矩陣格式 train_set_y_origi = train_set_y_origi.reshape( (1,train_set_y_origi.shape[0]) ) test_set_y_origi = test_set_y_origi.reshape( (1,test_set_y_origi.shape[0]) ) return train_set_x_origi,train_set_y_origi,test_set_x_origi,test_set_y_origi,classes # 從資料集中匯入資料 其中classes 用於儲存可能的結果 # classes: array([b'non-cat', b'cat'], dtype='|S7') # In[199]: # 讀入資料 train_set_x_origi,train_set_y,test_set_x_origi,test_set_y,classes = load_datasets() # In[200]: # 顯示一下訓練集的資料 index = random.randint(1,train_set_y.shape[1]) plt.imshow(train_set_x_origi[index]) # 列印圖片 # 列印結果 print( "The picture number is " +str(index) + " The ans is " +classes[ np.squeeze(train_set_y[:,index])].decode("utf-8") ) print("使用np.squeeze:" + str(np.squeeze(train_set_y[:,index])) ) print("不使用np.squeeze: " + str(train_set_y[:,index]) ) # 顯示的是資料集中隨機的一張圖片及結果 # 可改為指定編號 # squeeze 函式的作用為壓縮維度 # 是否使用squeeze的區別見程式碼 # # In[201]: # 檢視矩陣維數 im_number_train = train_set_y.shape[1] im_number_test = test_set_y.shape[1] im_size = train_set_x_origi.shape[1] # 列印 print("訓練集圖片數量: "+str(im_number_train)) print("測數集圖片數量: "+str(im_number_test)) print("圖片寬度高度為: "+str(im_size)) print("每張圖片大小為" +str(im_size)+","+str(im_size)+",3") print("訓練集x維數為 "+str(train_set_x_origi.shape)) print("訓練集y維數為 "+str(train_set_y.shape)) print("測試集x維數為 "+str(test_set_x_origi.shape)) print("測試集y維數為 "+str(test_set_y.shape)) # shaape 函式 返回矩陣維數 # 返回資料型別為n元組 可通過下標引用 # In[202]: # 降維 資料預處理 train_set_x_flatten = train_set_x_origi.reshape(train_set_x_origi.shape[0],-1).T test_set_x_flatten = test_set_x_origi.reshape(test_set_x_origi.shape[0],-1).T # 列印降維後的維數 print("訓練集降維後的維數為 "+str(train_set_x_flatten.shape)) print("測試集降維後的維數為 "+str(test_set_x_flatten.shape)) # reshape 函式用於改變矩陣維數 # -1 表示 自動計算下一維度 # In[203]: # 核對維數 print("訓練集x的位數為 "+str(train_set_x_flatten.shape)) print("訓練集y維數為 "+str(train_set_y.shape)) print("測試集x的維數為 "+str(test_set_x_flatten.shape)) print("測試集y維數為 "+str(test_set_y.shape)) # In[204]: # 資料標準化 # 圖片儲存的值為畫素值 0-255 # 例如資料集中 print(np.amax(train_set_x_flatten)) print(np.amin(train_set_x_flatten)) train_set_x = train_set_x_flatten/255 test_set_x = test_set_x_flatten/255 # In[205]: def sigmoid(z): # 引數為z陣列 # 返回s = sigmoid(z) s = 1/(1+np.exp(-z)) return s # 啟用函式有很多種 # ![image.png](attachment:image.png "啟用函式") # In[206]: # 測試siggmod 函式 是否符合預期 print( "sigmoid(0) = "+str(sigmoid(0))) print( "sigmoid(1) = "+str(sigmoid(1))) print( "sigmoid(10) = "+str(sigmoid(10))) print( "sigmoid(-1) = "+str(sigmoid(-1))) print( "sigmoid(-10) = "+str(sigmoid(-10))) # In[207]: def initialize_zeros_vector(size): # 函式作用 生成 並返回一個(size,1) 的0向量 同時初始化 b=0 w = np.zeros( (size,1) ) b = 0 # 斷言確保維數 assert( w.shape== (size,1) ) assert( isinstance(b,float) or isinstance(b,int) ) return (w , b) # In[208]: def two_way_propogate(W,b,X,Y ): # 實現正向傳播和反向傳播 m = X.shape[1] # 正向傳播 A = sigmoid(np.dot(W.T,X )+b) cost = (-1/m)*np.sum(Y*np.log(A) + (1-Y)*np.log(1-A)) # 反向傳播 dw = (1/m)* np.dot(X,(A-Y).T) db = (1/m)* np.sum(A-Y) assert(dw.shape==W.shape) assert(db.dtype == float) cost = np.squeeze(cost) # 儲存dw db grads = { "dw":dw, "db":db } return grads, cost # ### 這裡附上課程中求導計算過程中的部分截圖,便於理解 # 向量化之前: # ![image.png](attachment:image.png) # 向量化後: # ![image.png](attachment:image.png) # In[209]: # 測試 two_way_propogate # 隨便初始化一些引數 W ,b ,X, Y = np.array([ [2],[2] ]),2,np.array([ [1,0],[0,0] ]),np.array([0,0]) grabs, cost = two_way_propogate(W,b,X,Y) print("dw = " + str(grabs["dw"])) print("db = " + str(grabs["db"])) print("cost = " + str(cost)) # 迭代一次 看效果如何 learning_rate = 0.1 W = W -learning_rate*grabs["dw"] b= b- learning_rate * grabs["db"] grads, cost = two_way_propogate(W,b,X,Y) print("迭代一次後") print("dw = " + str(grabs["dw"])) print("db = " + str(grabs["db"])) print("cost = " + str(cost)) # In[210]: def optimize( W , b , X , Y , num_iteration , learning_rate , print_cost=False , print_frequency = 100): # 該函式作用 運用梯度下降優化W 和b # 引數描述放在下面 """ 此函式通過執行梯度下降演算法來優化w和b 引數: w - 權重,大小不等的陣列(num_px * num_px * 3,1) b - 偏差,一個標量 X - 維度為(num_px * num_px * 3,訓練資料的數量)的陣列。 Y - 真正的“標籤”向量(如果非貓則為0,如果是貓則為1),矩陣維度為(1,訓練資料的數量) num_iterations - 優化迴圈的迭代次數 learning_rate - 梯度下降更新規則的學習率 print_cost - 每100步列印一次損失值 返回: params - 包含權重w和偏差b的字典 grads - 包含權重和偏差相對於成本函式的梯度的字典 成本 - 優化期間計算的所有成本列表,將用於繪製學習曲線。 提示: 我們需要寫下兩個步驟並遍歷它們: 1)計算當前引數的成本和梯度,使用propagate()。 2)使用w和b的梯度下降法則更新引數。 """ costs =[] for i in range(num_iteration): grads , cost = two_way_propogate( W , b, X , Y ) dw = grads["dw"] db = grads["db"] W = W- dw * learning_rate b = b- db * learning_rate if(i%print_frequency==0): costs.append(cost) if(print_cost and i%print_frequency==0): print("迭代次數為:%i , 誤差值為: %f" % (i,cost)) params = { "W": W, "b": b } grads = { "dw": dw, "db": db } return (params , grabs , costs) # w - 權重矩陣 # b - 偏差值 一個數 # X - 維度為 訓練集 # Y - 訓練標籤集 真正的“標籤”向量(如果非貓則為0,如果是貓則為1),矩陣維度為(1,訓練資料的數量) # num_iterations - 優化迴圈的迭代次數 # learning_rate - 梯度下降更新規則的學習率 # print_cost - 是否列印cost # print_frequency - 列印頻率,迭代多少次列印一次cost # In[211]: # 測試 optimize W, b, X, Y = np.array([[2], [3]]), 3, np.array([[0,1], [2,2]]), np.array([[0, 2]]) params , grads , costs = optimize(W , b , X , Y , num_iteration=100 , learning_rate = 0.009) print ("w = " + str(params["W"])) print ("b = " + str(params["b"])) print ("dw = " + str(grads["dw"])) print ("db = " + str(grads["db"])) # In[212]: def predict(W , b , X): # 根據引數 預測結果 m = X.shape[1] # 這裡引數的維度假設是符合的 不需要判斷 A = sigmoid( np.dot(W.T,X )+b) assert(A.shape==(1,m)) for i in range(A.shape[1]): A[0,i] = 1 if A[0,i] >0.5 else 0 # 預設0.5為臨界值 assert(A.shape==(1,m) ) return A # 這裡的0.5 可以修改為一個指定的臨界值 或設定為引數 # In[213]: # 測試predict w, b, X, Y = np.array([[1], [2]]), 2, np.array([[1,2], [3,4]]), np.array([[1, 0]]) print("predictions = " + str(predict(w, b, X))) # In[214]: def model ( X_train , Y_train , X_test , Y_test , num_iterations = 2000 , learning_rate = 0.5, print_cost = False , print_frequency = 100): W , b = initialize_zeros_vector(X_train.shape[0]) parameters , grabs , costs = optimize(W , b , X_train , Y_train , num_iterations , learning_rate , print_cost, print_frequency) W , b = parameters["W"] , parameters["b"] # 預測測試集 Y_prediction_tset = predict(W , b , X_test) Y_prediction_train = predict(W , b , X_train) # 列印準確性 print("訓練集準確性: " , format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100 ) , "%") print("測試集準確性: " , format(100 - np.mean(np.abs(Y_prediction_tset - Y_test)) * 100 ) , "%") d = { "costs" : costs, "Y_prediction_test" : Y_prediction_tset, "Y_prediction_train" : Y_prediction_train, "W" : W, "b" : b, "learning_rate" : learning_rate, "num_iterations" : num_iterations } return d # In[215]: # 測數model d = model(train_set_x,train_set_y,test_set_x,test_set_y,num_iterations=2000,learning_rate=0.005,print_cost=True) # In[216]: costs = np.squeeze( d["costs"] ) plt.plot(costs) plt.ylabel("cost") plt.xlabel("iterations(per 100)") plt.title("Learning rate= "+ str(d["learning_rate"])) plt.show # In[217]: # 測試不同的學習率 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,test_set_x,test_set_y,num_iterations=2000,learning_rate=i,print_cost=False) print("\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 # In[218]: def test_my_image( my_image): image_name = my_image fname = "images/" + my_image # 在當前目錄下有一個images資料夾 用於存放我們的圖片 image = np.array(imageio.imread(fname)) my_image = Image.fromarray(image).resize(( im_size , im_size )) my_image = np.array(my_image).reshape((1, im_size * im_size * 3)).T my_predicted_image = predict(d["W"], d["b"], my_image) plt.imshow(image) print("image name is: "+image_name) print( "y = " + str(np.squeeze(my_predicted_image)) + ", your algorithm predicts a \"" + classes[int(np.squeeze(my_predicted_image)),].decode("utf-8") + "\" picture.") # 下面我們自己整一張圖片試一試 # In[220]: my_image1 = "my_image1.jpg" # my_image2 = "my_image1.jpg" # my_image3 = "my_image2.jpg" # my_image4 = "my_image3.jpg" # my_image5 = "my_image4.jpg" test_my_image(my_image1) # test_my_image(my_image2) # test_my_image(my_image3) # test_my_image(my_image4) # test_my_image(my_image5) # #### 宣告: 本人蔘考了[Kulbear](https://github.com/Kulbear/deep-learning-coursera) 的github上的文章 ,加以自己理解,編寫了本篇內容。盡力讓人輕鬆理解課程內容及作業