第三章.逻辑回归
3.1 逻辑回归(Logistic Regression)
线性回归以及非线性回归是用来处理回归问题的,而逻辑回归是用来处理分类问题的。
1.应用场景:
1).分类:
- 垃圾邮件分类
 - 预测肿瘤是良性还是恶行
 - 预测某人的信用是好是坏
 
2.Sigmoid / Logistic Function
1).Sigmoid/Logistic函数:

2).预测函数:

- 将g(x)代到h0(x)中:
 

3).图像:

- 图像描述:
①.0.5可以作为分类的边界
②.当z≥0时,g(z)≥0.5;当θTX≥0时,g(θTX)≥0.5
③.当z≤0时,g(z)≤0.5;当θTX≤0时,g(θTX)≤0.5 
3.决策边界
1).

- 图像描述:
①.线下面的点都是小于0的,属于标签为0的类别
②.线上面的点都是大于0的,属于标签为1的类别 
2).

- 图像描述:
①.圈内点都是小于0的,属于标签为0的类别
②.圈外的点都是大于0的,属于标签为1的类别 
3).

- 图像描述:
①.决策边界内的点都是小于0的,属于标签为0的类别
②.决策边界外的点都是大于0的,属于标签为1的类别 
4.逻辑回归的代价函数
1).图像:

- 说明:非凸函数在使用线性回归的代价函数的梯度下降法的时候,会存在多个局部极小值,不利于参数的求解,因此引入了逻辑回归的代价函数。
 
2).代价函数

- 参数说明:
①.h0(x):预测值
②.y:样本标签 
3).转换:
 ①.两个公式合并成一个公式: (深度学习中交叉熵也是这个公式)
 
  ②.梯度下降法求解逻辑回归:

  ③.求导的过程:
 
- 涉及到的公式:
 
| 公式 | 
|---|
| ( logax)'=1/xlna | 
| (θT x) ’ = x | 
| lne=1 | 
| log是以e为底 | 
 ④.最终的公式:
 
5.多分类

- 图像描述:
①.多分类可以做多个决策边界 
6.逻辑回归正则化
1).普通逻辑回归代价函数:

2).正则化逻辑回归代价函数:

3).求导:

7.实战1:梯度下降法—逻辑回归:
数据标准化有利于优化梯度下降法。
1).CSV中的数据:
- LR-testSet.csv
 
2).代码
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import classification_report
from sklearn import preprocessing
# 数据是否需要标准化
scale = False
# 载入数据
data = np.genfromtxt('D:\\Data\\LR-testSet.csv', delimiter=',')
# 数据切片
x_data = data[:, :-1]
y_data = data[:, -1]
# 画图
def plot():
    x0 = []
    x1 = []
    y0 = []
    y1 = []
    # 切分不同类别的数据:区分标签0和标签1
    for i in range(len(x_data)):
        if y_data[i] == 0:
            x0.append(x_data[i, 0])
            y0.append(x_data[i, 1])
        else:
            x1.append(x_data[i, 0])
            y1.append(x_data[i, 1])
    # 画散点图
    scatter0 = plt.scatter(x0, y0, c='b', marker='o')
    scatter1 = plt.scatter(x1, y1, c='r', marker='x')
    # 图例
    plt.legend(handles=[scatter0, scatter1], labels=['label0', 'label1'], loc='best')
plot()
plt.show()
# 数据处理
# 增加维度
y_data = data[:, -1, np.newaxis]
# 给样本增加偏置项
X_data = np.concatenate((np.ones((100, 1)), x_data), axis=1)
lr = 0.001
epochs = 10000
costList = []
# sigmoid函数
def sigmoid(x):
    return 1.0 / (1 + np.exp(-x))
# 代价函数
def cost(xMat, yMat, ws):
    value1 = np.multiply(yMat, np.log(sigmoid(xMat * ws)))
    value2 = np.multiply(1 - yMat, np.log(1 - sigmoid(xMat * ws)))
    return np.sum(value1 + value2) / - (len(xMat))
# 梯度下降函数
def gradAscent(xArr, yArr):
    # 判断数据是否需要标准化
    if scale == True:
        xArr = preprocessing.scale(xArr)
    xMat = np.mat(xArr)
    yMat = np.mat(yArr)
    # 返回数据的行列数
    m, n = np.shape(xMat)
    # 初始化权值
    ws = np.mat(np.ones((n, 1)))
    for i in range(epochs + 1):#+1是为了记录最后一次的代价函数的值
        h = sigmoid(xMat * ws)
        # 计算误差
        # xMat使用转置的原因:xMat是[100,3],转置后[3,100],h是[100,1],ws_grad是[3,1],回归参数正好是[3,1]的
        ws_grad = xMat.T * (h - yMat) / m
        ws = ws - lr * ws_grad
        if i % 50 == 0:
            costList.append(cost(xMat, yMat, ws))
    return ws, costList
# 训练模型,得到权重和cost值得变化
ws, costList = gradAscent(X_data, y_data)
if scale == False:
    # 绘制决策边界
    plot()
    x_test = [[-4], [3]]
    #y_test公式的由来:直线方程:w0+w1*x+w2*y=0 -> y=(-w0-w1*x)/w2
    y_test = (-ws[0] - x_test * ws[1]) / ws[2]
    plt.plot(x_test, y_test, 'k')
    plt.show()
# 绘制loss值得变化
x = np.linspace(0, 10000, 201)#每50次记录一下,一共记录了201次
plt.plot(x, costList, c='r')
plt.title('Train')
plt.xlabel('Epochs')
plt.ylabel('Cost')
plt.show()
# 预测
def predict(x_data, ws):
    if scale == True:
        x_data = preprocessing.scale(x_data)
    xMat = np.mat(x_data)
    ws = np.mat(ws)
    return [1 if x >= 0.5 else 0 for x in sigmoid(xMat * ws)]
precisions = predict(X_data, ws)
print(classification_report(y_data, precisions))
 
3).结果展示:
①.数据

②.图像

8.实战2: sklearn—逻辑回归:
数据标准化有利于优化梯度下降法。
1).CSV中的数据:
- LR-testSet.csv
 
2).代码
import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
from sklearn.metrics import classification_report
# 数据是否需要标准化
scale = False
# 载入数据
data = np.genfromtxt('D:\\Data\\LR-testSet.csv', delimiter=',')
x_data = data[:, :-1]
y_data = data[:, -1]
# 画图
def plot():
    x0 = []
    y0 = []
    x1 = []
    y1 = []
    # 切分不同类别的数据
    for i in range(len(x_data)):
        if (y_data[i] == 0):
            x0.append(x_data[i, 0])
            y0.append(x_data[i, 1])
        else:
            x1.append(x_data[i, 0])
            y1.append(x_data[i, 1])
    # 绘制散斑点
    scatter0 = plt.scatter(x0, y0, c='b', marker='o')
    scatter1 = plt.scatter(x1, y1, c='r', marker='x')
    # 绘制图例
    plt.legend(handles=[scatter0, scatter1], labels=['label0', 'label1'])
plot()
plt.show()
# 创建并拟合模型
logistic = linear_model.LogisticRegression()
logistic.fit(x_data, y_data)
# 截距
intercept = logistic.intercept_
# 回归系数
coef = logistic.coef_
if scale == False:
    # 绘制决策边界
    plot()
    x_test = np.array([[-4], [3]])
    y_test = (-intercept - x_test * coef[0][0]) / coef[0][1]
    plt.plot(x_test, y_test, 'k')
    plt.show()
# 预测值
predictions = logistic.predict(x_data)
print(classification_report(y_data, predictions))
 
3).结果展示:
①.数据

②.图像



















