机器学习——逻辑回归分类(机器学习实战)

619 阅读3分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

逻辑回归

数据集的标签大多是离散的,我们需要根据他们的特征去数据集分类。举一个分类的例子,根据肿瘤的体积,判断肿瘤是否是良性的。当然,输入的变量是连续的,也可以是离散的。我们使用逻辑回归来进行回归运算,包括二分类和多分类。

二分类

我们先从用蓝色圆形数据定义为类型1,其余数据为类型2; 只需要分类1次 步骤:1->2。

图片.png

多分类

我们先定义其中一类为类型1(正 类),其余数据为负类(rest); 接下来去掉类型1数据,剩余部分 再次进行二分类,分成类型2和负 类;如果有𝑛类,那就需要分类𝑛-1 次。

图片.png

sigmod函数

使用逻辑回归,我们需要用到一个非常重要的函数,Sigmod函数

我们需要使用这个函数,来将样本分类到标签1或者0,以达到分类的效果。

𝜎(𝑧)代表一个常用的逻辑函数(logistic function)为𝑆形函数(Sigmoid function) 则:𝜎(𝑧) = 𝑔(𝑧) = 1+1/(1+𝑒−𝑧) 合起来,我们得到逻辑回归模型的假设函数:

𝐿 (𝑦^, 𝑦) = −𝑦log(𝑦^) − (1 − 𝑦)log(1 − 𝑦^)(y^表示预测值,y表示实际值)

当𝜎(𝑧)大于等于0.5时,预测 y=1 当𝜎 (𝑧)小于0.5时,预测 y=0。

图片.png

逻辑回归函数求解

损失函数:𝐿 (𝑦^, 𝑦) = −𝑦log(𝑦^) − (1 − 𝑦)log(1 − 𝑦^)(y^表示预测值,y表示实际值)

为了衡量算法在全部训练样本上的表现如何,我们需要定义一个算法的代价函 数,算法的代价函数是对𝑚个样本的损失函数求和然后除以m:

代价函数:

图片.png

更新参数公式:

图片.png

使用的梯度下降,公式较复杂,这里直接给出更新参数的公式,过程读者可自行上网寻找。

代码实现

我们将要构建一个逻辑回归模型来预测,某个学生是否被大学录取。设想你是大学相关部分的管理者,想通过申请学生两次测试的评分,来决定他们是否被录取。现在你拥有之前申请学生的可以用于训练逻辑回归的训练样本集。对于每一个训练样本,你有他们两次测试的评分和最后是被录取的结果。为了完成这个预测任务,我们准备构建一个可以基于两次测试评分来评估录取可能性的分类模型。 数据类型如下: image.png

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
path = 'ex2data1.txt'
data = pd.read_csv(path, header=None, names=['Exam 1', 'Exam 2', 'Admitted'])
positive = data[data['Admitted'].isin([1])]
negative = data[data['Admitted'].isin([0])]

fig, ax = plt.subplots(figsize=(10, 6))
ax.scatter(positive['Exam 1'],
           positive['Exam 2'],
           s=50,
           c='b',
           marker='o',
           label='Admitted')
ax.scatter(negative['Exam 1'],
           negative['Exam 2'],
           s=50,
           c='r',
           marker='x',
           label='Not Admitted')
ax.legend()
ax.set_xlabel('Exam 1 Score')
ax.set_ylabel('Exam 2 Score')
plt.show()
def sigmoid(z):
    return 1 / (1 + np.exp(-z))

def cost(w, X, y):
    w = np.matrix(w)
    X = np.matrix(X)
    y = np.matrix(y)
    first = np.multiply(-y, np.log(sigmoid(X * w.T)))
    second = np.multiply((1 - y), np.log(1 - sigmoid(X * w.T)))
    return np.sum(first - second) / (len(X))
# add a ones column - this makes the matrix multiplication work out easier
data.insert(0, 'Ones', 1)

# set X (training data) and y (target variable)
cols = data.shape[1]
X = data.iloc[:, 0:cols - 1]
y = data.iloc[:, cols - 1:cols]

# convert to numpy arrays and initalize the parameter array w
X = np.array(X.values)
y = np.array(y.values)
w = np.zeros(3)
cost(w,X,y)
def gradient(w, X, y):
    w = np.matrix(w)
    X = np.matrix(X)
    y = np.matrix(y)

    parameters = int(w.ravel().shape[1])
    grad = np.zeros(parameters)

    error = sigmoid(X * w.T) - y

    for i in range(parameters):
        term = np.multiply(error, X[:, i])
        grad[i] = np.sum(term) / len(X)

    return grad
import scipy.optimize as opt
result = opt.fmin_tnc(func=cost, x0=w, fprime=gradient, args=(X, y))
def predict(w, X):
    probability = sigmoid(X * w.T)
    return [1 if x >= 0.5 else 0 for x in probability]
w_min = np.matrix(result[0])
predictions = predict(w_min, X)
correct = [
    1 if ((a == 1 and b == 1) or (a == 0 and b == 0)) else 0
    for (a, b) in zip(predictions, y)
]
accuracy = (sum(map(int, correct)) % len(correct))
print('accuracy = {0}%'.format(accuracy))

最终得出正确率为89%