逻辑回归

一、导入使用模块

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns#画图工具,在matplot上进行API精装
plt.style.use('fivethirtyeight') #样式美化
import matplotlib.pyplot as plt
# import tensorflow as tf
from sklearn.metrics import classification_report#这个包是评价报告

二、导入数据

data = pd.read_csv('F:\\MachineLearning\data\ex2data1.txt', names=['exam1', 'exam2', 'admitted'])
data.head()#看前五行

read_csv中的参数names以列表形式给每一列命名。

如图所示为数据形式:
在这里插入图片描述
下面为数据展示:

sns.set(context='notebook',style='darkgrid')                  #context:设置绘图元素大小(坐标轴标记大小),style:主题风格
sns.set_palette(palette=sns.color_palette("RdBu", 2)) #设置分类色板
sns.lmplot('exam1','exam2',hue='admitted',data=data,height=6,fit_reg=False,scatter_kws={"s": 50})#exam1,exam2:分别在制定的行列上分类
#hua:用于分类的属性,size:设置图的大小,fig_reg:是否显示分类直线,scatter_kws:点的样式大小
plt.show()

得到点图为:
在这里插入图片描述
color_palette() 中的第一个参数为颜色风格,第二个参数为色块数。fit_reg表示是否要画出回归曲线。

三、数据处理

def get_X(df):#读取特征

    ones = pd.DataFrame({'ones': np.ones(len(df))})#ones所对应的列长度为m全为1
    data = pd.concat([ones, df], axis=1)  # 合并数据,根据列合并
    return data.iloc[:, :-1].as_matrix()  # 这个操作返回 ndarray,不是矩阵


def get_y(df):#读取标签
    return np.array(df.iloc[:, -1])        #df.iloc[:, -1]是指df的最后一列


def normalize_feature(df):

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

由于要处理逻辑回归中常数项所对应的参数,所以要在X中的第一列添加全为1的列。concact将ones与df合并,axis=1表示按照行的方向合并。最会X除去倒数第一列。y则要取最后一列。normalize_feature为对数据进行归一化,防止在梯度下降过程中迭代过慢。
检查处理后数据的行数和列数:

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

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

得到:

(100, 3)
(100,)

四、sigmoid 函数
sigmoid函数形如:
在这里插入图片描述
所以可以编写sigmoid函数的代码:

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

然后展示sigmoid函数的曲线图:

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

得到图:
在这里插入图片描述

五、代价函数
逻辑回归的代价函数为:
在这里插入图片描述
所以代价函数的代码如下:

def cost(theta, X, y):
    m=X.shape[0]
    sigVector=sigmoid(X@theta)
    totalCost=-(y@np.log(sigVector)+(1-y)@np.log(1-sigVector))
    return totalCost/m

下面检验其正确性:在这里插入代码片

theta = theta=np.zeros(3)
print(cost(theta, X, y))

得到代价函数的值为0.6931471805599452,发现正确。

六、计算梯度
梯度形式为:
在这里插入图片描述
向量形式为:
在这里插入图片描述
所以可以计算梯度:

def gradient(theta, X, y):
    m=X.shape[0]
    deltaVector=sigmoid(X@theta)-y
    grad=X.T@deltaVector/m
    return grad

七、拟合参数
这里我们不必编写梯度下降算法以得到最优值,只需调用scipy.optimize就可拟合最优值。代码如下:

import scipy.optimize as opt#拟合参数

res = opt.minimize(fun=cost, x0=theta, args=(X, y), method='Newton-CG', jac=gradient)#fun:需要最小化的函数。x0:最初的猜想,
#ndarray, shape (n,)。arg:需要传递给目标函数与及其倒数的参数,fun, jac and hess functions。method:所使用的方法。jac:梯度向量计算方法。

print(res)#res为一个字典,拥有以下属性。x : ndarra,问题的优化求解。success : bool,是否成功。status : int,优化器终止状态。
#message : str,终止状态的说明。fun, jac, hess: ndarray,目标函数的值。hess_inv : object,目标函数Hessian矩阵的逆。
#nfev, njev, nhev : int,目标函数及其雅可比矩阵和黑森矩阵的计算次数。nit : int,优化器执行的迭代次数。maxcv : float,最大约束冲突。

得到最终拟合状态:

fun: 0.2034977015894895
     jac: array([-4.33738420e-07, -2.47262193e-05, -2.84907400e-05])
 message: 'Optimization terminated successfully.'
    nfev: 72
    nhev: 0
     nit: 29
    njev: 256
  status: 0
 success: True
       x: array([-25.16135181,   0.20623186,   0.20147175])

于是最优化theta值为:

 array([-25.16135181,   0.20623186,   0.20147175])

八、用训练集预测和验证
用我们拟合得到参数带入逻辑回归,预测样本集中样本的类。首先编写prdict函数的到预测结果。

def predict(x, theta):
    fx=sigmoid(X@theta)
    pred_list=[]
    for a in fx:
        if a>=0.5:
            pred_list.append(1)
        else:
            pred_list.append(0)
    y_pred=np.array(pred_list)
    return y_pred

进行判断:

final_theta = res.x
y_pred=predict(X, final_theta)
print(type(y_pred))
print(classification_report(y, y_pred))

得到预测结果:

<class 'numpy.ndarray'>
              precision    recall  f1-score   support

           0       0.87      0.85      0.86        40
           1       0.90      0.92      0.91        60

   micro avg       0.89      0.89      0.89       100
   macro avg       0.89      0.88      0.88       100
weighted avg       0.89      0.89      0.89       100

得到判断0的精度为0.87,1的精度为0.9。

九、寻找决策边界
我们把我们拟合的参数作为决策边界的参数,查看拟合参数的拟合情况。

print(res.x)
[-25.16135181   0.20623186   0.20147175]

得到前面的拟合参数。

coef = -(res.x / res.x[2])  # find the equation
print(coef)

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

这一步主要是得到exam2属性关于exam1属性的函数。然后就可以通过曲线图得到拟合情况:

sns.set(context="notebook", style="ticks", font_scale=1.5)

sns.lmplot('exam1', 'exam2', hue='admitted', data=data, 
           size=6, 
           fit_reg=False, 
           scatter_kws={"s": 25}
          )

plt.plot(x, y, 'grey')
plt.xlim(0, 130)
plt.ylim(0, 130)
plt.title('Decision Boundary')
plt.show()

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值