天天看点

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)