逻辑回归
说明
之前的代价函数写成了这样
J
(
θ
)
=
−
∑
i
=
1
n
y
i
l
n
h
θ
(
x
i
)
+
(
1
−
y
i
)
l
n
(
1
−
h
θ
(
x
i
)
)
J(\theta)=-\sum_{i=1}^ny_ilnh_\theta(x_i)+(1-y_i)ln(1-h_\theta(x_i))
J(θ)=−i=1∑nyilnhθ(xi)+(1−yi)ln(1−hθ(xi))
梯度下降的迭代函数写成了这样
θ
j
:
=
θ
j
−
α
∑
i
=
1
n
x
i
(
h
θ
(
x
i
)
−
y
i
)
\theta_j := \theta_j - \alpha\sum_{i=1}^{n}x_i(h_\theta(x_i)-y_i)
θj:=θj−αi=1∑nxi(hθ(xi)−yi)
-
这里的 x i x_i xi代表的是向量,也就是一条数据,所以写成了 ∑ \sum ∑的形式,也可以写成矩阵的形式
J ( θ ) = − y T l n h θ ( x ) + ( 1 − y T ) l n ( 1 − h θ ( x ) ) J(\theta)=-y^Tlnh_\theta(x)+(1-y^T)ln(1-h_\theta(x)) J(θ)=−yTlnhθ(x)+(1−yT)ln(1−hθ(x))θ j : = θ j − α X ( h θ ( x ) − y ) \theta_j := \theta_j - \alpha X(h_\theta(x)-y) θj:=θj−αX(hθ(x)−y)
下面的代码中直接使用矩阵做的计算
-
关于代价函数和梯度下降的迭代函数里面要不要加 1 m \frac1m m1的问题,我觉得加不加都行,反正我们求得是使J最小时 θ \theta θ的取值,加不加都一样。
以下的代码中加了。
代码
# encoding:utf-8
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import classification_report# 用于计算一些指标
# 这个函数用来画出类别不同的点
def showDots():
x0=[]
x1=[]
y0=[]
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=['class:0','class:1'])
# 读文件
data = np.genfromtxt('../data/LR-testSet.csv',delimiter=',')
x_data = data[:,:-1]
y_data = data[:,-1,np.newaxis]
# 加偏置项
X_data = np.concatenate((np.ones((100,1)),x_data),axis=1)
# sigmoid函数
def sigmoid(x):
return 1.0/(1+np.exp(-x))
# 代价函数
def cost(xMat,yMat,ws):
part1 = np.multiply(yMat,np.log(sigmoid(xMat*ws)))
part2 = np.multiply(1-yMat,np.log(1-sigmoid(xMat*ws)))
return np.sum(part1+part2) / -len(xMat)
# 梯度下降法
def gradAscent(xArray,yArray):
xMat = np.mat(xArray)
yMat = np.mat(yArray)
lr = 0.001
epochs = 10000
costList = []
# 获得数据条数和特征数目
m,n = np.shape(xMat)
# 初始化权值全为1
ws = np.mat(np.ones((n,1)))
# 开始迭代
for i in range(epochs+1):
h = sigmoid(xMat*ws)
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
# 训练模型
ws,costList = gradAscent(X_data, y_data)
# 画图
showDots()
x_test = [[-4],[3]]
y_test = (-ws[0]-x_test*ws[1])/ws[2]
plt.plot(x_test,y_test,c='brown')
plt.show()
# 画代价函数的变化情况
x = np.linspace(0,10000,201)
plt.plot(x,costList,c='r')
plt.title('train')
plt.xlabel('epochs')
plt.ylabel('cost')
plt.show()
# 分类的函数
def predict(ws):
xMat = np.mat(X_data)
ws = np.mat(ws)
return [1 if x >= 0.5 else 0 for x in sigmoid(xMat*ws)]
prediction = predict(ws)
print(classification_report(y_data,prediction))
调用sklearn库实现
# encoding:utf-8
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import classification_report# 用于计算一些指标
from sklearn import linear_model
# 这个函数用来画出类别不同的点
def showDots():
x0=[]
x1=[]
y0=[]
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=['class:0','class:1'])
# 读文件
data = np.genfromtxt('../data/LR-testSet.csv',delimiter=',')
x_data = data[:,:-1]
y_data = data[:,-1,np.newaxis]
# 创建模型
logistic = linear_model.LogisticRegression()
logistic.fit(x_data,y_data)
# 画图
showDots()
x_test = np.array([[-4],[3]])
y_test = (-logistic.intercept_-x_test*logistic.coef_[0][0])/logistic.coef_[0][1]
plt.plot(x_test,y_test,c='brown')
plt.show()
# 分类
prediction = logistic.predict(x_data)
print(classification_report(y_data,prediction))
结果
- 分类边界
- 代价函数的值随
θ
\theta
θ的迭代而减小
- 正确率、召回率和
F
1
F_1
F1值