識別貓的單隱藏層神經網絡(我的第一個模型)
摘要:算法詳解;代碼;可視化查看超參數影響
目標:識別一張圖是不是貓
數據集:訓練數據209張64*64
測試數據50張 64*64
方案:二分分類法
算法:logistic回歸 ,限定了你的輸入(X),和做優化時,需要優化哪些量(W,b)
激活函數:sigmod
sigmod函數圖像:
特點:所有輸出y值都落在0-1之間
ps:logistic回歸是算法,但其激活函數取sigmod,是因為,你想得到一個在(0-1)之間的值,所以,這才用到了sigmod函數。
損失函數:
成本函數:
成本函數的由來:假設第1張圖真實值是1(第一張圖本來就是貓),
預測時,認為
它是貓的概率是0.8,體現在sigmod函數輸出0.8,(a=0.8)
則正確率
同理,如果假設某圖不是只貓,其y=0,
其正確率
合並
得
log是一個單調遞增的函數,可以變成一個凸函數,便於使用梯度下降進行優化
把上式log化
上式還不是成本函數,因為,上式值越大表明,越準確
按照習慣來說,需要成本函數越小,預測值與真實值越接近,越準確
所以,直接加個負號就行了
所以,成本函數就是
計算圖
代碼:
- 載入數據
- 處理數據(/255),縮小數據,因為1比255更好計算
- 初始化(w,b),w是一個n維列向量,b=0
- 建立sigmod函數
- 利用訓練數據集 建立正反向傳播函數,如計算圖,並求梯度,以便使用梯度下降
- 建立優化(梯度下降)函數,利用好梯度,選取下降方向,另需選取學習率
- 利用叠代num_iterations次後,出來的w,b。組裝好sigmod函數,預測,測試集數據
- 測試/訓練集 正確率輸出,利於判斷
- 可視化輸出,比較出一個好的學習率,和叠代次數。(超參數選擇,一個無法學習的東西
- import numpy as np
- import matplotlib.pyplot as plt
- import h5py
- import sys
- sys.path.append(r‘F:\study\assignment2‘)
- from lr_utils import
- ‘‘‘‘‘
- 數據讀取與標準化
- 讀取的x數據是(209,64,64,3)的格式
- 需要將其平鋪成(64*64*3,209)
- ‘‘‘
- train_x_orig,train_y_orig,test_x_orig,test_y_orig,classes=load_dataset()
- train_x_flatten=train_x_orig.reshape(train_x_orig.shape[0],-1).T
- test_x_flatten=test_x_orig.reshape(test_x_orig.shape[0],-1).T
- #上面一定要記得轉置,因為reshape成了(m,n)的形式
- #-1,是不用去考慮到底要轉換成多少列了,只要是負數就行
- #然後是將數據縮小,便於計算,因為1比255更好計算,反正也不影響計算機結果
- #標準化數據 rgb值都小於255的
- train_x=train_x_flatten / 255
- test_x=test_x_flatten / 255
- train_y=train_y_orig
- test_y=test_y_orig
- #上面就把數據整理好了
- ‘‘‘‘‘
- 下面開始寫函數了
- ‘‘‘
- #建立sigmod函數
- def sigmod(x):
- return (1/(1+np.exp(-x)))
- #初始化w,b, ps:w是一個列向量
- def initialize(n_x):
- w=np.zeros(shape=(n_x,1))
- b=0
- return(w,b)
- #建立正反向傳播函數
- def propagate(w,b,X,Y):
- """
- 正向傳播
- """
- A=sigmod(np.dot(w.T,X)+b)
- m=X.shape[1]
- cost=(-1/m)*np.sum(Y * np.log(A)+(1-Y) * np.log(1-A))
- ‘‘‘‘‘ ps:尼瑪不知道為什這個三點冒號也要按照縮進格式來
- 反向傳播
- ‘‘‘
- dw=np.dot(X,(A-Y).T)/m
- db=np.sum(A-Y)/m
- ‘‘‘‘‘
- 組裝數據
- ‘‘‘
- grads={‘dw‘:dw,‘db‘:db}
- return (grads,cost)
- #建立優化函數
- def optimize(w,b,X,Y,num_iterations,learning_rate,print_cost):
- costs=[]
- for i in range(num_iterations):
- grads,cost=propagate(w,b,X,Y)
- dw=grads[‘dw‘]
- db=grads[‘db‘]
- 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(‘叠代次數:%i.誤差值:%f‘ %(i,cost))
- #組裝數據
- params={‘w‘:w,‘b‘:b}
- return (params,costs)
- #建立預測函數
- def predict(w,b,X):
- value=sigmod(np.dot(w.T,X)+b)
- Y_prediction=(value>0.5)+0
- ‘‘‘‘‘
- 對於上一代碼詳解
- value>0.5是個判斷語句,>0.5會返回True
- +0.是讓布爾值轉化成數字,1
- ‘‘‘
- return Y_prediction
- #下面是整合所有函數了
- def model(X_train,Y_train,X_test,Y_test,num_iterations=2000,learning_rate=0.01,print_cost=False):
- #先調用X_train,Y_train,來訓練處w,b
- m=X_train.shape[1]
- w,b=initialize(X_train.shape[0])
- params,costs=optimize(w,b,X_train,Y_train,num_iterations,learning_rate,print_cost)
- w,b=params[‘w‘],params[‘b‘]
- #計算預測值
- Y_prediction_train=predict(w,b,X_train)
- Y_prediction_test=predict(w,b,X_test)
- #比較
- print(‘TrainRightRate:‘,format(100-np.mean(np.abs(Y_prediction_train-Y_train))*100),‘%‘)
- print(‘TestRightRate:‘,format(100-np.mean(np.abs(Y_prediction_test-Y_test))*100),‘%‘)
- ‘‘‘‘‘
- 上面代碼詳解
- abs(Y_p-T_r),此處兩相比較,相同,預測對了,則詳減為0,預測錯了,則為1或者-1
- abs,全部取正
- mean,平均值,即有多少個+-1在所有數據中,即在所有數據中錯誤的個數/總數據
- 我要的是正確率,所以前面要用100來減
- ‘‘‘
- #數據組裝
- d={
- ‘costs‘:costs,
- ‘Y_prediction_train‘:Y_prediction_train,
- ‘Y_prediction_test‘:Y_prediction_test,
- ‘w‘:w,
- ‘b‘:b,
- ‘learning_rate‘:learning_rate,
- ‘num_iterations‘:num_iterations}
- return d
- #d=model(train_x,train_y,test_x,test_y,num_iterations=2000,learning_rate=0.005,print_cost=True)
- ‘‘‘‘‘
- 上面就算是整個模型搭建完了,下面是可視化
- 表示叠代次數,學習率,與成本函數的關系
- ‘‘‘
- learning_rate=[0.01,0.001,0.0001]
- models={}
- for i in learning_rate:
- print ("learning rate is: " + str(i))
- models[str(i)]=model(train_x,train_y,test_x,test_y,num_iterations=500,learning_rate=i)
- print (‘\n‘ + "-------------------------------------------------------" + ‘\n‘)
- for i in learning_rate:
- 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()
代碼筆記
- 從另外一個文件中導入py文件中的某個函數
import sys
sys.path.append(r‘path‘)
from lr_utils import load_datasert
- 記住X要組裝成(n,m)矩陣,w是一個(n,1)的列向量
有利於記住使用np.dot()時,哪個放前面,哪個放後面,也 有利於廣播時是否需要轉置的判斷
- 數據處理
本例子中是將每個元/255,讓[0,255],的數據計算,變成了[0,1]的數據計算,加快計算
還有很多其他的數據處理方式,還沒學到,多做多學
- np.reshape(a,-1)中-1的妙用,只要把一個數組的行寫出來了,列向量可以使用-1,讓計算機自動計算分配,只要是負值就行
- w-=learning_rate*dw 不知道為什麽不能使用,需要常規操作,w=w-learning_rate*dw
- A and B,兩個判斷,只要有一個是False,那整個語句就是錯的,本例子,使用and來控制是否輸出叠代次數與誤差
- 布爾值轉數字 讓布爾值‘+0‘就行了,numpy對於判斷語句,也是並行運行的
- 對於同類型的數據,多用字典dict組裝,如梯度,初始值
- np.squeeze()函數,將(5,1,1)轉換成(5,)降維處理,有利於運行,也是可視化操作時,作為輸入時,不可缺少的操作
>>> a=np.random.randn(10000,1,1,1,1)
>>> sys.getsizeof(a)
80160
>>> b=np.random.randn(10000)
>>> sys.getsizeof(b)
80096
- 可視化操作中,參數解釋:loc:選擇把線型說明放在哪個地方,shadow,是否加營養
frame.set_facecolor(‘0.9‘),給說明的地方加了框之後,再選擇填充框的透明度
- 使用‘‘‘作解釋時,也需要遵循Python的縮進格式,否則會報錯
- 空一行 print(‘\n‘)
識別貓的單隱藏層神經網絡(我的第一個模型)