天天看點

python邏輯回歸_吳恩達Coursera機器學習Week3邏輯回歸python實作(一)

python邏輯回歸_吳恩達Coursera機器學習Week3邏輯回歸python實作(一)

Coursera上Andrew Ng的課程堪稱經典,課程主要使用的是Octave/MATLAB。平時學習使用python多些,是以嘗試着用python來做個課後作業。

第三周的課程主要學習了邏輯回歸以及邏輯回歸的正則化。

作業目标:通過兩次考試成績來判斷是否可以錄取通過?

下載下傳課後作業檔案,解壓縮後可以得到如下檔案,自行過濾出第一部分相關檔案:

  • ex2.m 分步驟實作邏輯回歸代碼,之後對應ex2.py
  • ex2data1.txt 第一部分資料集
  • plotDecisionBoundary.m 實作繪畫決策邊界的代碼,對應plotDecisionBoundary.py

下面這些檔案是這次作業要做的

[⋆] plotData.m 繪畫二維資料,之後對應plotData.py

[⋆] sigmoid.m 之後對應sigmoid.py

[⋆] costFunction.m 邏輯回歸損失函數 之後costFunction.py

[⋆] predict.m 邏輯回歸預測 之後對應predict.py

下面就按照作業給出的步驟來實戰下

1.1 用散點圖來展示我們的資料,了解我們需要的解決的問題

plotData.py
import matplotlib.pyplot as plt

def plotData(X,y):
    fig, ax = plt.subplots(figsize=(14,7))
    #篩選出通過的樣本
    X_sub = X[y==1]
    ax.scatter(X_sub.loc[:,0],X_sub.loc[:,1],marker ='x',color='green',label ='Admitted')
    #篩選出未通過的樣本
    X_sub = X[y==0]
    ax.scatter(X_sub.loc[:,0],X_sub.loc[:,1],marker='s',color='red',label ='Not admitted')
    #設定橫縱坐标
    ax.set(xlabel='Exam 1 score',ylabel = 'Exam 2 score')
    plt.legend()
    plt.show()
           
ex2.py
from plotData import plotData
from pandas as pd

df = pd.read_csv("ex2/ex2data1.txt",header=None)
X = df.loc[:,:1]
y = df.loc[:,2]
plotData(X,y)
           
python邏輯回歸_吳恩達Coursera機器學習Week3邏輯回歸python實作(一)

1.2 建立假設函數(hypothesis),代價函數(cost),梯度下降函數(gradient descent)

sigmoid.py
import numpy as np
def sigmoid(x):
    return 1/(1+np.exp(-x))
           
costFunction.py
from sigmoid import sigmoid
from numpy as np

def y_hat(w,X):
    # 計算假設函數輸出的y結果
    return sigmoid(np.dot(X, w))

def cost(w, X, y):
    # 代價函數
    return np.mean(-y * np.log(y_hat(w,X)) - (1-y) * np.log(1-y_hat(w,X)))

def gradient(w, X, y):
    m = len(X)
    return np.dot(X.T, y_hat(w,X)-y)/m
           
ex2.py更新
from costFunction import *

#在X資料中加一列常數列為1
X[2] = 1
y = np.array(y).reshape(-1,1)

w = np.zeros((len(X.columns),1))
print(cost(w,X,y))
           

用初始化的w計算可以驗證,得到最初的代價(cost)為0.693,

正确
Once you are done, ex2.m will call your costFunction using the initial parameters of θ. You should see that the cost is about 0.693.
尋找使得代價函數最小的最優解w,在Octave/MATLAB可以使用自帶函數fminunc來求最優解,在python中可以使用scipy 方法一 使用fmin_tnc ex2.py更新
import scipy.optimize as opt

w = np.zeros(len(X.columns))

#print(cost(w,X,y))

result = opt.fmin_tnc(func=cost, x0=w, fprime=gradient, args=(X, y))
print(result)
print(cost(result[0],X,y)
           
方法二:循環疊代(耗時長,learningRate設定要很小,不然容易過頭) 大家是不是也有這個問題?有大佬可以解答下不
epochs = 100000
learningRate = 0.0015
for i in range(0, epochs):
    cost_res = cost(w,X,y_1)
    dw = gradient(w,X,y_1)
    w -= learningRate*dw
    if i % 100 == 0:
        print("第%i次循環,損失函數為%s" % (i, cost_res))
print(w)
           

用最小求解反推出代價為0.2034977,

正确
Once fminunc completes, ex2.m will call your costFunction function using the optimal parameters of θ. You should see that the cost is about 0.203.

1.3 繪畫決策邊界 Decision Boundary

plotDecisionBoundary.py
import numpy as np
import matplotlib.pyplot as plt


def plot_decision_boundary(theta):
    """為 ex2.py 畫出 decision boundary"""
    boud_x = np.array([10,120])
    boud_y = (-theta[0]*boud_x-theta[2])/theta[1]
    plt.plot(boud_x,boud_y,'b-')
           
ex2.py更新
from plotDecisionBoundary import plot_decision_boundary
plotData(X,y)
plot_decision_boundary(result[0])
           
python邏輯回歸_吳恩達Coursera機器學習Week3邏輯回歸python實作(一)
For a student with an Exam 1 score of 45 and an Exam 2 score of 85, you should expect to see an admission probability of 0.776.

作業中提高一個學生考試1分數45,考試二分數85,最後y值為0.776,是以可以用這個列子來檢測自己的模型是否正确。

ex2.py更新
X_test = np.array([[45,85,1]])
y_test = sigmoid(result[0],X_test)
print(y_test) #0.77629062
           

1.4 預測函數predict

predict.py
from sigmoid import sigmoid
import numpy as np

def predict(w,X):
    y_hat = sigmoid(np.dot(X, w))
    return np.where(y_hat>=0.5,1,0)
           
ex2.py更新
from predict import predict
X_predict = [[50,68,1],[70,90,1]] #自己編了測試資料
y_predict = predict(result[0],X_predict) 
print(y_predict) #列印看下輸出結果是不是0,1
           
寫在最後
  1. sklearn涵蓋了很多機器學習的包,但是自己手寫一遍推導并且用代碼實作可以加深自己對這個模型的印象,以及可以很好地幫助了解之後在模型調參
  2. 代碼實作過程中,在求點乘的時候,矩陣的行,列要搞清楚。
a = np.arange(4) 
#np.array([1,2,3,4])
a.shape
#(4,)
b = np.arange(4).reshape(1,4)
#np.array([[1,2,3,4]])
b.shape
#(1,4)