logisitic回归
假设现在有一些数据点,我们利用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作为回归。我们希望接收所有的输出,然后预测出类别。在两个类别的情况下,输出0,1来代表,这种函数是单位阶跃函数。
sigmoid函数具有该性质:
sigmoid函数公式是:
sigmoid(z)=11+exp(−z)
s
i
g
m
o
i
d
(
z
)
=
1
1
+
e
x
p
(
−
z
)
sigmoid函数的性质可以作为分类器,输入为z
z=w0∗x0+w1∗x1+...+wn∗xn
z
=
w
0
∗
x
0
+
w
1
∗
x
1
+
.
.
.
+
w
n
∗
x
n
如果使用向量表示, 输入向量均为列向量:输入z:
z=w⃗ T⋅x⃗
z
=
w
→
T
⋅
x
→
n为特征个数。比如下面的例子中,只有两个特征,可以在二维平面上画出并分类。
梯度下降算法
要寻求某个某个函数的最小值,最好的方法是沿着梯度的反方向,即沿着下降速率最快的方向。在Andrew Ng的斯坦佛课堂上,有动态图的演示,方便理解。这种方法,可能会找到局部最优解(local optimum),而不是全局最优解(global optimum)。
假设更新步长是alpha,那么根据梯度下降算法,回归系数可以由下面的式子进行更新:
w:=w−α∗∇f(w)
w
:=
w
−
α
∗
∇
f
(
w
)
在上述更新参数的式子中,是对模型的预测值求梯度,实际上并不需要这样做。可以通过数学推导,可以变化成一种更方便操作的形式。
python实战代码
"""""
Author:
xinming
Modify:
2018/02/21
"""
import numpy as np
import matplotlib.pyplot as plt
def load_data_set():
fo = open('F:\pythonProject\MLIAcode\Ch05/testSet.txt')#注意\t变成了制表符。
data_mat=[] ;label_mat=[]
for line in fo.readlines():
list = line.strip().split()
data_mat.append([1,float(list[0]),float(list[1])])#w0*x0+w1*x1+w2*x2,x0设为1,w0设为常系数
label_mat.append(int(list[2])) #需要强制转换数据类型,否则为字符
return data_mat,label_mat
def sigmoid(x):
return 1.0/(1+np.exp(-x))
def logistic_reg_grad_descent(data_mat,label_mat):
data_matrix = np.mat(data_mat) #100行3列
label_matrix=np.mat(label_mat).transpose() #是行向量故要转置
m,n=np.shape(data_mat) #n为特征个数,共有三个:x0,x1,x2
#print(m,n)
alpha = 0.001 #定义更新的步长
weights = np.ones((n,1))#初始化参数为1 3行1列
max_cycles = 500#书中直接把迭代次数赋值为500
for k in range(max_cycles):
h = sigmoid(data_matrix*weights)#hypothesis,预测值
error=h-label_matrix #m行1列,m组数据
weights=weights-alpha*data_matrix.transpose()*error #梯度下降的参数更新,可以由求导转化为这种乘积形式
return weights
def plot_best_fit():
data_mat,label_mat=load_data_set()
wei = logistic_reg_grad_descent(data_mat,label_mat) #<class 'numpy.matrixlib.defmatrix.matrix'>
print(type(wei))
weights = wei.getA()#<class 'numpy.ndarray'> getA()函数将numpy矩阵转换为数组
print(type(weights))
print(weights)
data_array = np.array(data_mat) #转换为numpy矩阵,方便操作
n ,m= np.shape(data_array) #矩阵的行数
x_cor1=[];y_cor1=[]
x_cor2=[];y_cor2=[]
for i in range(n):
if label_mat[i]==1:
x_cor1.append(data_array[i,1])
y_cor1.append(data_array[i,2])
else:
x_cor2.append(data_array[i,1])
y_cor2.append(data_array[i,2])
fig = plt.figure()
ax=fig.add_subplot(111)#返回Axes类,并实例化为ax对象
ax.scatter(x_cor1,y_cor1,c='red',marker='s')#类别为1的设置为红色方块
ax.scatter(x_cor2,y_cor2,c='green')#类别为0的设置为绿色
x=np.arange(-3,3,0.1)
y=(-weights[0]-weights[1]*x)/weights[2]
ax.plot(x,y)
plt.show()
最后运行的效果如下: