逻辑回归的概念
逻辑:逻辑,源自古典希腊语 (logos),最初的意思是“词语”或“言语”,引申意思是“思维”或“推理”。 1902年,教育家严复将其意译为“名学”,音译为“逻辑”。
回归:回归是统计学的一个重要概念,其本意是根据之前的数据预测一个准确的输出值。
逻辑回归是目前使用最为广泛的一种学习算法,用于解决分类问题。与线性回归算法一样,也是监督学习算法。
分类问题为什么不用线性回归
对于分类问题分类,y 取值为0 或者1。如果使用线性回归,那么线性回归模型的输出值可能远大于1,或者远小于0。导致代价函数很大。
逻辑函数
逻辑函数(logical function)是一种描述数字电路特点的工具。输出量是高、低电平,可以用二元常量(0,1)来表示。
逻辑回归模型
hθ(x) =
1
1
+
e
−
X
θ
\frac{1}{1+e^{-Xθ}}
1+e−Xθ1
关于这个模型为了方便后面sigmoid函数的计算我们需要对其求导,求导过程如下:
代价函数
这里用到的代价函数与我们之前用到的不同,需要用交叉熵代价函数
J(θ) =
−
1
m
∑
i
=
1
m
[
y
(
i
)
l
n
(
h
θ
(
x
(
i
)
)
)
+
(
1
−
y
(
i
)
)
l
n
(
1
−
h
θ
(
x
(
i
)
)
)
]
-\frac{1}{m}\sum_{i=1}^m[y^{(i)}ln(h_θ(x^{(i)})) + (1-y^{(i)})ln(1-h_θ(x^{(i)}))]
−m1∑i=1m[y(i)ln(hθ(x(i)))+(1−y(i))ln(1−hθ(x(i)))]
因为y的取值不是0就是1,所以这样写可以直接在一方为0是另一个可以计算
该代价函数J(θ)是一个凸函数,并且没有局部最优值;
因为代价函数是凸函数,无论在哪里初始化,最终达到这个凸函数的最小值点。
逻辑回归的梯度下降
在得到代价函数以后,便可以用梯度下降算法来求得能使代价函数最小的参数了。
代码实现
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 读取数据
data_train = np.loadtxt(r'C:\Users\shy\PycharmProjects\untitled\week4\mushroomTrain.txt',delimiter=',')
data_test = np.loadtxt(r'C:\Users\shy\PycharmProjects\untitled\week4\mushroomTest.txt',delimiter=',')
# 提取数据
train_x,train_y = data_train[:,:-1],data_train[:,-1]
test_x,test_y = data_test[:,:-1],data_test[:,-1]
# 数据预处理
def proPeross(x,y):
# 特征缩放
x -= np.mean(x,axis=0)
x /= np.std(x,axis=0,ddof=1)
# 数据初始化
x = np.c_[np.ones(len(x)),x]
y = np.c_[y]
return x,y
train_x,train_y = proPeross(train_x,train_y)
test_x,test_y = proPeross(test_x,test_y)
# 激活函数
def g(z):
h = 1.0/(1+np.exp(-z))
return h
def model(x,theta):
z = np.dot(x,theta)
h = g(z)
return h
# 代价
def costFunc(h,y,R):
m = len(h)
J = -1.0/m*np.sum(y*np.log(h)+(1-y)*np.log(1-h)) + R
return J
# 梯度下降
def draeDesc(x, y, alpha=0.01, iter_num=100, lamba=60):
m,n = x.shape
theta = np.zeros((n,1))
J_history = np.zeros(iter_num)
for i in range(iter_num):
h = model(x,theta)
theta_r = theta.copy()
theta_r[0] = 0
R = lamba/(2 * m)*np.sum(np.square(theta_r))
J_history[i] = costFunc(h,y,R)
deltaTheta = 1.0/m * (np.dot(x.T,h-y)+lamba*theta_r)
theta -= alpha*deltaTheta
return J_history,theta
J_history,theta = draeDesc(train_x,train_y)
# 准确率
def score(h, y):
count = 0
for i in range(len(h)):
if np.where(h[i] >= 0.5,1,0) == y[i]:
count += 1
return count/len(h)
# 获得预测值
train_h =model(train_x,theta)
test_h = model(test_x,theta)
print('训练集准测率为',score(train_h,train_y))
print('测试集准测率为',score(test_h,test_y))
# 画图
def draw(x,y,title):
plt.title(title)
plt.scatter(x[y[:,0]==0,2],x[y[:,0]==0,3],label='负相关')
plt.scatter(x[y[:,0]==1,2],x[y[:,0]==1,3],label='正相关')
plt.legend()
plt.show()
draw(train_x,train_y,'训练集')
效果展示