吴恩达机器学习作业(python版)—— ex2逻辑回归

【1】逻辑回归

在这部分的练习中,你将建立一个逻辑回归模型来预测一个学生是否能进入大学。假设你是一所大学的行政管理人员,你想根据两门考试的结果,来决定每个申请人是否被录取。你有以前申请人的历史数据,可以将其用作逻辑回归训练集。对于每一个训练样本,你有申请人两次测评的分数以及录取的结果。为了完成这个预测任务,我们准备构建一个可以基于两次测试评分来评估录取可能性的分类模型。

1.Visualizing the data

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

path = 'ex2data1.txt'
data = pd.read_csv(path,header=None,names=['Exam 1','Exam 2','Admitted'])
data.head()#查看前5行数据
Exam 1 Exam 2 Admitted
0 34.623660 78.024693 0
1 30.286711 43.894998 0
2 35.847409 72.902198 0
3 60.182599 86.308552 1
4 79.032736 75.344376 1
data.describe()

在这里插入图片描述
创建散点图使数据更加直观地展示出来

positive = data[data['Admitted'].isin([1])]
negative = data[data['Admitted'].isin([0])]

fig,ax = plt.subplots(figsize=(12,8))
ax.scatter(x = positive['Exam 1'],y = positive['Exam 2'],s = 50,color='b',marker = 'o',label = 'Admitted')
ax.scatter(x = negative['Exam 1'],y = negative['Exam 2'],s = 50,color='r',marker = 'x',label = 'Not Admitted')
plt.legend()
ax.set_xlabel('Exam 1 Score')
ax.set_ylabel('Exam 2 Score')
plt.show()

Admitted = 1表示被录取,用positive将Admitted = 1时的exam1、exam2成绩取出;同理用negative将Admitted = 0时的exam1、exam2成绩取出
画出横轴为exam1纵轴为exam2的散点图,查看Admitted的分布情况

在这里插入图片描述

看起来在两类间,有一个清晰的决策边界。现在我们需要实现逻辑回归,那样就可以训练一个模型来预测结果。
获取我们的训练集数据

def get_X(df):
    ones = pd.DataFrame({
    
    'ones':np.ones(len(df))})
    data = pd.concat([ones,df],axis=1)
    return np.array(data.iloc[:,:-1])#返回ndarray

def get_y(df):
    return np.array(data.iloc[:,-1])

def normalize_feature(df):
    return df.apply(lambda column:(column-column.mean())/column.std()) #特征缩放

X = get_X(data)
print(X.shape)

y = get_y(data)
print(y.shape)

2.Sigmoid fuction

在这里插入图片描述

def sigmoid(z):
    return 1 /(1 + np.exp(-z))

让我们做一个快速的检查,来确保它可以工作

fig,ax=plt.subplots(figsize=(8,6))
ax.plot(np.arange(-10,10,step=0.01),sigmoid(np.arange(-10,10,step=0.01)),c='r')
ax.set_ylim((-0.1,1.1))
ax.set_xlabel('z')
ax.set_ylabel('g(z)')
ax.set_title('sigmoid fuction')
plt.plot()

效果如下:(符合S曲线,函数定义正确)
在这里插入图片描述

3.Cost fuction

与线性回归的代价函数不同,因为要使用sigmoid函数控制h(x)在(0,1)之间
在这里插入图片描述
代价函数的推导以及手算过程:
在这里插入图片描述

theta=np.zeros(3)
theta #array([0., 0., 0.])

def cost(theta,X,y):
    return np.mean(-y *np.log(sigmoid(X@theta)) - (1-y)*np.log(1-sigmoid(X@theta)))

cost(theta,X,y)
#0.6931471805599453

相乘两位置为array时(*)号 为对应元素的乘积,@连接的两项表示对应位置相乘后相加 -> 具体请戳这里
其他矩阵相乘的用法及扩展 -> 请戳这里

4.Gradient

在这里插入图片描述

def gradient(theta,X,y):
    return ( X.T @ (sigmoid(X @ theta) - y)) / len(X)

分析: X.T @ (sigmoid(X @ theta) - y)此处我认为是活用了@乘积的操作,X.T为(100×3)维,y为一维数列。为了使达到公式中的效果,需要将X进行转置后才能相乘。

注意,在上这一步中我们实际上没有在这个函数中执行梯度下降,我们仅仅在计算一个梯度步长。(只从[0,0,0]开始进行了一次梯度下降,还没有得到最优的θ)现在可以看看用我们的数据和初始参数为0的梯度下降法的结果

gradient(theta,X,y)
#array([ -0.1       , -12.00921659, -11.26284221])

5.Learning θ parameters

我们可以用SciPy的“optimize”命名空间:SciPy’s truncated newton(TNC)实现寻找最优参数。
只需传入cost函数,已经所求的变量theta,和梯度,func = cost表示传入我们的cost函数,x0=theta,表示传入初始点即theta的初值

import scipy.optimize as opt
res = opt.minimize(fun=cost, x0=theta, args=(X,y), method='Newton-CG',jac=gradient)
res
   fun: 0.20349770249067073
     jac: array([-1.29015205e-05, -7.87933956e-04, -9.06046726e-04])
 message: 'Optimization terminated successfully.'
    nfev: 72
    nhev: 0
     nit: 28
    njev: 243
  status: 0
 success: True
       x: array([-25.15887187,   0.20621202,   0.20145168])

此时的x=[-25.15887187, 0.20621202, 0.20145168]即为theta的最优解

6.Evaluating logistic regression

接下来,我们需要编写一个函数,用我们所学的参数theta来为数据集X输出预测。然后,我们可以使用这个函数来给我们的分类器的训练精度打分。

def predict(theta, X):
    probability = sigmoid( X @ theta)
    return [1 if x >= 0.5 else 0 for x in probability]  # return a list
    
final_theta = res.x
y_pridict = predict(final_theta, X)

用skearn中的方法来检验

from sklearn.metrics import classification_report
print(classification_report( y,y_pridict))
'''
              precision    recall  f1-score   support

           0       0.85      0.87      0.86        39
           1       0.92      0.90      0.91        61

    accuracy                           0.89       100
   macro avg       0.88      0.89      0.88       100
weighted avg       0.89      0.89      0.89       100
'''

我们的逻辑回归分类器预测正确,如果一个学生被录取或没有录取,达到89%的精确度
在这里插入图片描述
f1-score 即 F

7.Decision boundary

更直观地展示出所拟合的参数是否被录取的效果,所以需要根据参数画出决策边界(线性函数)
公式:
在这里插入图片描述
函数推导:
在这里插入图片描述
斜率矩阵:

coef = -(res.x / res.x[2]) 
coef
#array([124.88787185,  -1.02363018,  -1.        ])

函数实现:

x = np.arange(130, step=0.1)
y = coef[0] + coef[1]*x
data.describe()

在这里插入图片描述
根据原始数据画散点图,根据函数画决策边界

fig, ax = plt.subplots(figsize=(8,5))
ax.scatter(positive['Exam 1'], positive['Exam 2'], c='b', label='Admitted')
ax.scatter(negative['Exam 1'], negative['Exam 2'], s=50, c='r', marker='x', label='Not Admitted')
ax.plot(x, y)
ax.set_xlim(0, 130)
ax.set_ylim(0, 130)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('Decision Boundary')
plt.show()

效果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46126258/article/details/107771536