Deeplearning——Logistics回歸


資料來源:1、博客: http://binweber.top/2017/09/12/deep_learning_1/#more——轉載,修改更新
    

 基本概念

邏輯回歸:
  logistic回歸又稱logistic回歸分析,是一種廣義的線性回歸分析模型,常用於數據挖掘,疾病自動診斷,經濟預測等領域。例如,探討引發疾病的危險因素,並根據危險因素預測疾病發生的概率等。
 
回歸分析:
  回歸分析是確定兩種或兩種以上變量間相互依賴的定量關系的一種統計分析方法。運用十分廣泛,回歸分析按照涉及的變量的多少,分為一元回歸和多元回歸分析;按照因變量的多少,可分為簡單回歸分析和多重回歸分析;按照自變量和因變量之間的關系類型,可分為線性回歸分析和非線性回歸分析。如果在回歸分析中,只包括一個自變量和一個因變量,且二者的關系可用一條直線近似表示,這種回歸分析稱為一元線性回歸分析。如果回歸分析中包括兩個或兩個以上的自變量,且自變量之間存在線性相關,則稱為多重線性回歸分析。
 

 本文例子

為了訓練一個貓識別器,輸入一張圖片表示為 特征向量 x ,並預測圖片 是否為貓,輸出 y 為1(是)或0(不是)
 

 

我們稱圖片為非結構化數據,但在計算機中,一張圖片以RGB方式編碼時,它是以Red、Green、Blue三基色組成一個矩陣的方式進行儲存的,這三個矩陣的大小和圖片的大小相同 ,如圖中每張貓圖大小為64*64(pixeis:像素),那么三個矩陣中每個矩陣的大小即為64*64。
 
單元格中代表的像素值將用來組成一個N維的特征向量(單列 n 維)。在模式識別和機器學習中,一個特征向量用來表示一個對象。這個問題中,這個對象為貓或者非貓。
 
為了組成一個特征向量 x ,將每一種顏色的像素值進行拆分重塑,最終形成的特征向量 x 的維數為:${n_{x}} = 64*64*3 = 12288$(一列有12288個元素)。
 
特征向量x:
   
一個訓練樣本(一張圖片數據)由一對 (x,y) 進行表示,其中 x 為$n_x$維特征向量,y是這個特征向量的標簽,值為0或1。m個訓練樣本對將被表示為:

$$({x^{(1)}},{y^{(1)}}),({x^{(2)}},{y^{(2)}}),......,({x^{(m)}},{y^{(m)}})$$

定義矩陣X、Y,將輸入的訓練集(一組圖片m張)中的x(1)x(1),x(2)x(2)等以及y(1)y(1),y(2)y(2)等分別堆疊在矩陣的列向量中:
$$X = [{{\rm{x}}^{(1)}},{x^{(2)}},......,{x^{(m)}}] $$
$$Y = [{{\rm{y}}^{(1)}},{y^{(2)}},......,{y^{(m)}}] $$
其中X為$n_x$行m列矩陣,Y為1行m列矩陣。
 
Python中即X.shape=($n_x$,m),Y.shape=(1,m)。(shape為numpy庫中的函數,功能為獲取矩陣長度)

 實現方案

Cat vs No-cat: 
給定以一個$n_x$維特征向量x表示的一張圖片,這個算法將估計這張圖中存在一只貓的概率,即 y = 1 的概率:
$$\hat y = P(y = 1|x),0 \le \hat y \le 1$$
我們希望能有一個函數,能夠表示出$\hat y$,如果進行 最簡單的線性擬合的話,規定一個$n_x$維向量w和一個值b作為參數,可得到:
$$\hat y = {w^T}X + b$$
注意:w是一個與輸入X同維度的列向量(轉置后與X相乘得到的是一個實數),b為線性位置調整參數
由於$\hat y$是一個概率值,取值范圍為[0 , 1],簡單的進行線性擬合,得出的$\hat y$可能非常大,還可能為負值,
這時,便需要一個sigmoid函數來對它的值域進行約束,sigmoid函數的表達式為:
$$\sigma \left( z \right) = \frac{1}{{1 + {e^{ - z}}}}$$
函數圖像為:

由函數圖像可知,sigmoid函數有幾個很好的性質:

- 當z趨近於正無窮大時,$\sigma z=1$
- 當z趨近於負無窮大時,$\sigma z=0$
- 當z = 0時,$\sigma z=0.5$
所以可以用sigmoid函數來約束$\hat y$的值域,此時:
$$\hat y = \sigma ({w^T}X + b) = \frac{1}{{1 + {e^{ - ({w^T}X + b)}}}}$$
 

 求參數w和b

參數w和b是通過樣本數據訓練獲得的,給定一張圖片(一個數據),我們會知道圖片中是否有貓,即y = 1 或 y = 0,在算法中即稱之為真實值,再把計算機通過算法計算出來的$\hat y$稱之為預測值。
我們總希望預測值 $\hat y$ 與 y 的差異盡可能的小,甚至相同。也即是說,我們會定義一個衡量預測值 $\hat y$ 與真實值 y 之間差異的函數,通過求其差異最小化的解來得到 w 和 b 兩個參數。
這個衡量預測值 $\hat y$ 與真實值 y 之間差異的函數就是 損失函數(Loss Function):
$${\mathop{\rm L}\nolimits} (\hat y,y) = \frac{1}{2}{(\hat y - y)^2}$$
但在logistic回歸中一般不使用這個損失函數,因為在訓練參數過程中,使用這個損失函數將得到一個 非凸函數,最終將存在很多 局部最優解,這種情況下使用 梯度下降(Gradient Descent)法無法找到最優解。所以在logistic回歸中,一般采用log函數:
$${\mathop{\rm L}\nolimits} (\hat y,y) = - (y\log \hat y + (1 - y)\log (1 - \hat y))$$
log函數有如下性質:
- 當y = 1時,${\mathop{\rm L}\nolimits} (\hat y,y) = - y\log \hat y$
- 當y = 0時,${\mathop{\rm L}\nolimits} (\hat y,y) = - y\log (1 - \hat y)$
附:log函數默認以e為底(在python numpy中,log表示以e為底,log2、log10分別表示以2、10為底)
以上函數只是單個樣本的差值,再定義一個函數來表示整個訓練數據集差異的平均值,即 成本函數(Cost Function)
$${\mathop{\rm J}\nolimits} (w,b) = \frac{1}{m}\sum\limits_{i = 1}^m {L({{\hat y}^i},{y^i})}$$
 
故,函數的最終形式是:
$${\text{J}}(w,b) =  - \frac{1} {m}\sum\limits_{i = 1}^m {(Y\log \frac{1} {{1 + {e^{ - ({w^T}X + b)}}}} + (1 - Y)\log (1 - \frac{1} {{1 + {e^{ - ({w^T}X + b)}}}}))} ,Y = 0,1$$
其中X,Y是從訓練樣本獲得的數據,X是圖像矩陣,Y是1或0。因此,我們可以通過求取J的最小值,來獲得w和b這兩個參數。最后在把這兩個參數應用到$\hat y = \sigma ({w^T}X + b) = \frac{1}{{1 + {e^{ - ({w^T}X + b)}}}}$中作為最終的預測算法!!!

  使用梯度下降法來求得參數w和b,使得成本函數的最小化

參考學習:http://www.cnblogs.com/pinard/p/5970503.html 

  在微積分里面,對多元函數的參數求∂偏導數,把求得的各個參數的偏導數以向量的形式寫出來,就是梯度。比如函數f(x,y), 分別對x,y求偏導數,求得的梯度向量就是${(\frac{{\partial f}}{{\partial x}},\frac{{\partial f}}{{\partial y}})^T}$,簡稱grad f(x,y)或者$\nabla f(x,y)$。對於在點(x0,y0)的具體梯度向量就是${(\frac{{\partial f}}{{\partial x_0}},\frac{{\partial f}}{{\partial y_0}})^T}$,或者$\nabla f(x_0,y_0)$,如果是3個參數的向量梯度,就是${(\frac{{\partial f}}{{\partial x}},\frac{{\partial f}}{{\partial y}},\frac{{\partial f}}{{\partial z}})^T}$,以此類推。

  那么這個梯度向量求出來有什么意義呢?他的意義從幾何意義上講,就是函數變化增加最快的地方。具體來說,對於函數f(x,y),在點(x0,y0),沿着梯度向量的方向就是$\nabla f(x_0,y_0)$的方向是f(x,y)增加最快的地方。或者說,沿着梯度向量的方向,更加容易找到函數的最大值。反過來說,沿着梯度向量相反的方向,也就是 $-\nabla f(x_0,y_0)$的方向,梯度減少最快,也就是更加容易找到函數的最小值。

  在機器學習算法中,在最小化損失函數時,可以通過梯度下降法來一步步的迭代求解,得到最小化的損失函數,和模型參數值(此處即是w和b)。

 

  在空間坐標中以w,b為軸畫出損失函數J(w,b)的三維圖像,可知這個函數為一個凸函數。為了找到合適的參數,先將w和b賦一個初始值,正如圖中的小紅點。在losgistic回歸中,幾乎任何初始化方法都有效,通常將參數初始化為零。隨機初始化也起作用,但通常不會在losgistic回歸中這樣做,因為這個成本函數是凸的,無論初始化的值是多少,總會到達同一個點或大致相同的點(最優解)。梯度下降就是從起始點開始,試圖在最陡峭的下降方向下坡,以便盡可能快地下坡到達最低點,這個下坡的方向便是此點的梯度值。

在二維圖像中來看,順着導數的方向,下降速度最快,用數學公式表達即是:

$$w: = w - a\frac{{\partial J(w,b)}}{{\partial w}}$$

$$b: = b - a\frac{{\partial J(w,b)}}{{\partial b}}$$

上述兩式表示隨時更新w與b的值。

  其中的”:=”意思為賦值,α為學習率,通常為一個小於1的數,用來控制梯度下降過程中每一次移動的規格,相當於邁的步子大小。α的不宜太小也不宜過大:太小會使迭代次數增加,容易陷入局部最優解;太大容易錯過最優解。(a設置的值過小時,需要增加迭代次數,因為如果不增加迭代次數,可能還沒有得到最優解就已經結束了,如同你要走一段固定長度的路,步子小了,就要多走幾步)
 

待解決問題

1、如何把一張圖片轉換成矩陣數據?
2、算法中求$\hat y$只是用了最簡單的線性擬合,是否有更好的擬合算法?
3、sigmoid函數中的 e 是否可以用更小或者更大的數來代替,對算法有什么影響,是更好了還是更差了?——已測試,測試結果見文末附錄
 

Python實現

  總代碼與輸出

#logistic_regression.py

#導入用到的包
import numpy as np
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage

#導入數據
def load_dataset():
    train_dataset = h5py.File("train_cat.h5","r") #讀取訓練數據,共209張圖片
    test_dataset = h5py.File("test_cat.h5", "r") #讀取測試數據,共50張圖片
    
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) #原始訓練集(209*64*64*3)
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) #原始訓練集的標簽集(y=0非貓,y=1是貓)(209*1)
    
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) #原始測試集(50*64*64*3
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) #原始測試集的標簽集(y=0非貓,y=1是貓)(50*1)
    
    train_set_y_orig = train_set_y_orig.reshape((1,train_set_y_orig.shape[0])) #原始訓練集的標簽集設為(1*209)
    test_set_y_orig = test_set_y_orig.reshape((1,test_set_y_orig.shape[0])) #原始測試集的標簽集設為(1*50)
    
    classes = np.array(test_dataset["list_classes"][:])
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes    #classes = [b'non-cat' b'cat']

#顯示圖片
def image_show(index,dataset):
    index = index
    if dataset == "train":
        plt.imshow(train_set_x_orig[index])
        print ("y = " + str(train_set_y[:, index]) + ", 它是一張" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") +  "' 圖片。")
    elif dataset == "load_dataset_test":
        plt.imshow(test_set_x_orig[index])
        print ("y = " + str(test_set_y[:, index]) + ", 它是一張" + classes[np.squeeze(test_set_y[:, index])].decode("utf-8") +  "' 圖片。")

#sigmoid函數
def sigmoid(z):
    s = 1.0/(1+np.exp(-z))
    return s

#初始化參數w,b
def initialize_with_zeros(dim):
    w = np.zeros((dim,1)) #w為一個dim*1矩陣
    b = 0    
    return w, b

#計算Y_hat,成本函數J以及dw,db
def propagate(w, b, X, Y):
    m = X.shape[1] #樣本個數
    Y_hat = sigmoid(np.dot(w.T,X)+b)                                     
    cost = -(np.sum(np.dot(Y,np.log(Y_hat).T)+np.dot((1-Y),np.log(1-Y_hat).T)))/m #成本函數
    
    dw = (np.dot(X,(Y_hat-Y).T))/m
    db = (np.sum(Y_hat-Y))/m

    cost = np.squeeze(cost) #壓縮維度    
    grads = {"dw": dw,
             "db": db} #梯度
    
    return grads, cost

#梯度下降找出最優解
def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):#num_iterations-梯度下降次數 learning_rate-學習率,即參數ɑ
    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: #每100次記錄一次成本值
            costs.append(cost)
        
        if print_cost and i % 100 == 0: #打印成本值
            print ("循環%i次后的成本值: %f" %(i, cost))
    
    params = {"w": w,
              "b": b} #最終參數值
    
    grads = {"dw": dw,
             "db": db}#最終梯度值
    
    return params, grads, costs

#預測出結果
def predict(w, b, X):
    m = X.shape[1] #樣本個數
    Y_prediction = np.zeros((1,m)) #初始化預測輸出
    w = w.reshape(X.shape[0], 1) #轉置參數向量w
    
    Y_hat = sigmoid(np.dot(w.T,X)+b) #最終得到的參數代入方程
    
    for i in range(Y_hat.shape[1]):
        if Y_hat[:,i]>0.5:
            Y_prediction[:,i] = 1
        else:
            Y_prediction[:,i] = 0
    
    return Y_prediction

#建立整個預測模型
def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False): 
                                                                            #num_iterations-梯度下降次數 learning_rate-學習率,即參數ɑ
    w, b = initialize_with_zeros(X_train.shape[0]) #初始化參數w,b

    parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost) #梯度下降找到最優參數
    
    w = parameters["w"]     #獲得最終參數
    b = parameters["b"]     #獲得最終參數
    
    Y_prediction_train = predict(w, b, X_train) #訓練集的預測結果
    Y_prediction_test = predict(w, b, X_test) #測試集的預測結果
    
    train_accuracy = 100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100 #訓練集識別准確度……abs——絕對值……mean——求均值
    test_accuracy = 100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100 #測試集識別准確度
    
    print("訓練集識別准確度: {} %".format(train_accuracy))
    print("測試集識別准確度: {} %".format(test_accuracy))
    
    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

#初始化數據
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

m_train = train_set_x_orig.shape[0] #訓練集中樣本個數
m_test = test_set_x_orig.shape[0] #測試集總樣本個數
num_px = test_set_x_orig.shape[1] #圖片的像素大小

train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T #原始訓練集的設為(12288*209)
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T #原始測試集設為(12288*50)

train_set_x = train_set_x_flatten/255. #將訓練集矩陣標准化
test_set_x = test_set_x_flatten/255. #將測試集矩陣標准化

d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)

# 畫出學習曲線
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()

#學習率不同時的學習曲線
learning_rates = [0.01, 0.001, 0.0001]
models = {}
for i in learning_rates:
    print ("學習率: " + 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' + "-------------------------------------------------------" + '\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()

out:

     

  解釋:

     以上輸出表示的是梯度下降次數為2000次,每次的下降步長分別為0.01,,0.001,0.0001的測試結果。

    由測試結果可知:

      1、循環n次后的成本值最小可以達到為0,而成本值表示的是預測值與真實值之間的差異程度,差異越小越好,所以達到為0 是最理想的結果。

      2、梯度下降的次數與下降步長需要協調改進,如同你要走一段固定的距離到達一個位置(即達到成本值最小,但具體不知道多少),步數多了,步子就要變小,步數少了,步子就要變大,但其實我們總有可能還沒有到達那個位置或者超過了那個位置。以上測試中只減小了步長,很大可能是成本值還沒有達到最小值。

      3、訓練集的准確度是可以達到100%的,因為我們是通過訓練集來確定出算法參數的,也即是說訓練集的數據必然是接近100%擬合算法的,但測試集不是,測試集是我們確定了算法之后,再將經過算法得出的的預測值與真實值進行比較得到的結果。

函數匯總

  • load_dataset():return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes  #導入數據
  • image_show(index,dataset):return null    #顯示圖片
  • sigmoid(z):return s    #sigmoid函數
  • initialize_with_zeros(dim):return w, b    ##初始化參數w,b
  • propagate(w, b, X, Y):return grads, cost    ##計算Y_hat,成本函數J以及dw,db
  • optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):return params, grads, costs    #梯度下降找出最優解
  • predict(w, b, X):return Y_prediction    #預測出結果
  • model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):return d    #建立整個預測模型

    整個算法大概的流程:導入數據load_dataset()——通過訓練數據計算$\hat y$propagate(w, b, X, Y),該函數會返回w和b的梯度值與成本函數cost公式——通過梯度下降法找出w和b的最優解optimize( ),返回最終的w和b參數——再把w和b參數賦給函數predict(),得出最終的預測算法

    以上流程部分嵌套,最后整合在model()中.

  部分代碼分塊解釋

數據導入load_dataset():(加入了測試代碼) 

#logistic_regression.py

#導入用到的包
import numpy as np
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage

#導入數據
def load_dataset():
    train_dataset = h5py.File("train_cat.h5","r") #讀取訓練數據,共209張圖片
    test_dataset = h5py.File("test_cat.h5", "r") #讀取測試數據,共50張圖片
    
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) #原始訓練集(209*64*64*3)
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) #原始訓練集的標簽集(y=0非貓,y=1是貓)(209*1)
    
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) #原始測試集(50*64*64*3
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) #原始測試集的標簽集(y=0非貓,y=1是貓)(50*1)
    
    train_set_y_orig = train_set_y_orig.reshape((1,train_set_y_orig.shape[0])) #原始訓練集的標簽集設為(1*209)
    test_set_y_orig = test_set_y_orig.reshape((1,test_set_y_orig.shape[0])) #原始測試集的標簽集設為(1*50)
    
    classes = np.array(test_dataset["list_classes"][:])
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

#初始化數據
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()    #classes = [b'non-cat' b'cat']

#print("train_set_x_orig = " + str(train_set_x_orig))
#print("train_set_y = " + str(train_set_y))
#print("test_set_x_orig = " + str(test_set_x_orig))
#print("test_set_y = " + str(test_set_y))
print("classes = " + str(classes))
#print("type(train_set_x_orig) = " + str(type(train_set_x_orig)))
#print("type(train_set_y) = "  + str(type(train_set_y)))

  測試:

    print("type(train_set_y) = "  + str(type(train_set_y)))————輸出:type(train_set_y) = <class 'numpy.ndarray'>:輸出的數據是數組形式

    如下(圖片數據的保存形式,即.h5文件內容):

            

        print("classes = " + str(classes))————輸出: classes = [b'non-cat' b'cat']

    將數據還原為圖片:    

#logistic_regression.py

#導入用到的包
import numpy as np
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage

#導入數據
def load_dataset():
    train_dataset = h5py.File("train_cat.h5","r") #讀取訓練數據,共209張圖片
    test_dataset = h5py.File("test_cat.h5", "r") #讀取測試數據,共50張圖片
    
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) #原始訓練集(209*64*64*3)
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) #原始訓練集的標簽集(y=0非貓,y=1是貓)(209*1)
    
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) #原始測試集(50*64*64*3
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) #原始測試集的標簽集(y=0非貓,y=1是貓)(50*1)
    
    train_set_y_orig = train_set_y_orig.reshape((1,train_set_y_orig.shape[0])) #原始訓練集的標簽集設為(1*209)
    test_set_y_orig = test_set_y_orig.reshape((1,test_set_y_orig.shape[0])) #原始測試集的標簽集設為(1*50)
    
    classes = np.array(test_dataset["list_classes"][:])
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

#顯示圖片
def image_show(index,dataset):
    index = index
    if dataset == "train":
        plt.imshow(train_set_x_orig[index])
        print ("y = " + str(train_set_y[:, index]) + ", 它是一張" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") +  "' 圖片。")
    elif dataset == "load_dataset_test":
        plt.imshow(test_set_x_orig[index])
        print ("y = " + str(test_set_y[:, index]) + ", 它是一張" + classes[np.squeeze(test_set_y[:, index])].decode("utf-8") +  "' 圖片。")

#初始化數據
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

for i in range(0,50):
    plt.subplot(5,10,i+1)
    print(i+1)
    image_show(i,"load_dataset_test")
    
plt.show()
'''
for i in range(0,50):
    plt.subplot(5,10,i+1)
    print(i+1)
    image_show(i,"train")
    
plt.show()
'''

       輸出:

            

     


 
附錄:

關於最優解

  來看看梯度下降的一個直觀的解釋。比如我們在一座大山上的某處位置,由於我們不知道怎么下山,於是決定走一步算一步,也就是在每走到一個位置的時候,求解當前位置的梯度,沿着梯度的負方向,也就是當前最陡峭的位置向下走一步,然后繼續求解當前位置梯度,向這一步所在位置沿着最陡峭最易下山的位置走一步。這樣一步步的走下去,一直走到覺得我們已經到了山腳。當然這樣走下去,有可能我們不能走到山腳,而是到了某一個局部的山峰低處。

  從上面的解釋可以看出,梯度下降不一定能夠找到全局的最優解,有可能是一個局部最優解。當然,如果損失函數是凸函數,梯度下降法得到的解就一定是全局最優解。

來源:http://www.cnblogs.com/pinard/p/5970503.html

 關於sigmoid函數中e的參數對算法結果的影響

   此處先把e看做一個變量a:$${\text{y}} = \frac{1} {{1 + {a^{ - x}}}}$$

  不同a值情況下的圖像

          

  在程序中改變a的值進行測試

       

     以上的結果是在梯度下降次數為2000次,學習率為0.005的條件下測試的,可以看出,調整a的值是有助於改變識別准確度的。

   但也可以看到,在相同條件下,只改變a的值也會改變訓練集的識別准確度,這又是為什么?

    我們知道訓練集的識別准確度是可以通過梯度下降次數與學習率的調整最高達到100%的,那么再測試一下不同梯度下降次數條件下識別的准確度會有什么影響:

        

    由以上測試可以看出,訓練集的識別准確度是可以達到100%的,但相應的卻降低了測試集的識別准確度。

  我們知道訓練集的准確度可以達到100%,完全是因為算法的參數就是從中計算出來的,也就是說,訓練集的數據是近乎完全擬合算法的。但測試集不是,我們只是找了另外一些數據來對得到的這個算法進行測試,測試的過程類似於我們拿兩張貓的圖片來進行對比,一張已知是貓,一張未知,看他們的相似程度,相似程度高,就認為未知圖片是貓。只是算法換成了數據,對比的也是數據。先把數據轉換成函數,再通過這個函數來測試另外的數據。但就是這個數據轉換成函數的結果,有很多種,優劣不一,它必然會省略掉一些信息,導致另外拿來測試的數據實際上應該是符合的卻被測試為不符合。也即是再好的一個識別貓的算法,我們必然有可能拿一張不是貓的圖像讓它認為是貓,再拿一張是貓的圖像讓它認為不是貓(也即是對抗樣本模型)。

  所以說,上面測試集識別准確度與訓練集准確度的關系並不會是線性的,跟算法有很大的關系,但即使如此,測試集的識別准確度也在68%-74%之間了(梯度優化足夠的前提下)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM