本篇博客主要是逻辑回归的手撸代码,但是还有我的简单理解,用提问解答的形式描述。并不是逻辑回归的介绍,如有错误还望指出。
逻辑回归和线性回归就是得到一条直线。线性回归的直线是尽可能去拟合输入向量x的分布,使得训练集中所有样本点到直线的距离最短;而逻辑回归的直线是尽可能去拟合决策边界,使得训练集中的样本点尽可能分离开。因此他们的目的是不同的。
平方损失函数是线性回归假设样本误差服从高斯分布,利用极大似然估计推导而得;交叉熵损失函数是逻辑回归假设样本服从二项分布,利用极大似然估计推导而得。这是由于模型优化目标不同而推导得到不同的损失函数。
对于逻辑回归而言,交叉熵损失函数是凸函数,而平方损失函数不是凸函数。凸函数有着良好的优化性质,可以保证局部最优就是全局最优。而非凸函数,存在很多局部极小值,不宜优化。
交叉熵损失函数可以很好的衡量逻辑回归决策函数的好坏。
逻辑回归是对分类可能性建模,不需事先假设数据分布,避免了因假设不准确而带来的后果。
逻辑回归不仅可以预测类别,还可以得到近似的概率预测。
逻辑回归的对率函数是任意阶可导函数,数学性质好,易于优化。
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline
#这里的数据是用的机器学习实战上的数据,其中也参考了上面的代码
data = []
label = []
for line in open('testSet.txt').readlines():
tmpLine = line.strip().split()
data.append([1.0, float(tmpLine[0]), float(tmpLine[1])])
label.append(int(tmpLine[2]))
data = np.matrix(data)
label = np.matrix(label).transpose()
#定义sigmoid函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 随机梯度下降
# data: 特征数据
# label: 标签
# alpha: 学习率
# epoch: 迭代次数
def SGD(data, label, alpha, epoch):
m, n = np.shape(data)
weights = np.ones((n, 1))
for i in range(epoch):
for j in np.random.permutation(m):
h = sigmoid(np.dot(data[j], weights))
error = h - label[j]
weights = weights - (alpha * error * data[j]).transpose()
return weights
# 批梯度下降
# data: 特征数据
# label: 标签
# alpha: 学习率
# epoch: 迭代次数
def BSG(data, label, alpha, epoch):
m, n = np.shape(data)
weights = np.ones((n, 1))
for i in range(epoch):
h = sigmoid(np.dot(data, weights))
error = h - label
weights = weights - np.dot(data.T, error) * alpha / m
return weights
# 小批量梯度下降
# data: 特征数据
# label: 标签
# alpha: 学习率
# epoch: 迭代次数
# miniBatch: 一个小批量的大小
def miniBSG(data, label, alpha, epoch, miniBatch):
m, n = np.shape(data)
weights = np.ones((n, 1))
for i in range(epoch):
arr_reflash = np.random.permutation(m)
miniBatch_arr = np.array_split(arr_reflash, miniBatch)
for mini in miniBatch_arr:
h = sigmoid(np.dot(data[mini], weights))
error = h - label[mini]
weights = weights - np.dot(data[mini].T, error) * alpha / miniBatch
return weights
def plotLine(data, label, weights):
m = np.shape(data)[0]
x1 = []
y1 = []
x2 = []
y2 = []
for i in range(m):
if(label[i] == 1):
x1.append(data[i, 1])
y1.append(data[i, 2])
else:
x2.append(data[i, 1])
y2.append(data[i, 2])
plt.figure(figsize=(10, 5))
plt.scatter(x1, y1, c='r', marker='o')
plt.scatter(x2, y2, c='g', marker='x')
x = np.arange(-4, 4, 0.1)
y = ((- weights[0] - weights[1] * x) / weights[2]).T
plt.plot(x, y)
plt.xlabel('X1')
plt.ylabel('X2')
统计学习方法 -李航
机器学习 -周志华
机器学习实战 -Peter Harrington