
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.pyimport 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)
1.2 创建假设函数(hypothesis),代价函数(cost),梯度下降函数(gradient descent)
sigmoid.pyimport 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.pyimport 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])
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.pyfrom 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
写在最后 - sklearn涵盖了很多机器学习的包,但是自己手写一遍推导并且用代码实现可以加深自己对这个模型的印象,以及可以很好地帮助理解之后在模型调参
- 代码实现过程中,在求点乘的时候,矩阵的行,列要搞清楚。
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)