逻辑回归的Python实现

163 阅读3分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

代码:

iris=pd.read_csv(r'Desktop\iris.csv',sep=',',delimiter=',')

dummy=pd.get_dummies(iris['Species'])#通过哑变量类别数据化

iris = pd.concat([iris, dummy], axis =1 )

del iris['Unnamed: 0']

iris = iris.loc[0:99, :]

#定义回归函数,即sigmoid函数

def logit(x):

return 1./(1+np.exp(-x))                                                              

temp = pd.DataFrame(iris['Sepal.Length'])

#添加“1”列到temp

temp['x0'] = 1.#加一列创建计算矩阵

##整理出X矩阵 和 Y矩阵

X=temp.reindex(columns=['x0','Sepal.Length'])

Y = iris['setosa'].values

#两种算法的实现

#批量梯度下降法

def logitic_fuc(X,Y,alpha=0.0065,iteration_1=3000):

    m,n = X.shape #矩阵大小

    #alpha = 0.0065 #设定学习速率

    theta_g = np.zeros(n) #初始化参数

    #iteration_1=3000

    J = pd.Series(np.zeros(iteration_1, dtype = float)) #构造损失函数承载器

    for i in range(iteration_1):

        h = logit(np.dot(X, theta_g)) #回归函数

        J[i] = -(1/100.)np.sum(Ynp.log(h)+(1-Y)*np.log(1-h)) #计算损失函数值     

        diff = h - Y #概率差

        grad = np.dot(X.T, diff) #梯度,

        theta_g -= alpha * grad#调节学习速率,会得到不同曲线

    J.plot()

plt.show()

return logit(np.dot(X, theta_g))

 

logitic_fuc(X,Y,alpha=0.0000000000005,iteration_1=5000)

 

C:\Users\dongfeng\Anaconda3\lib\site-packages\ipykernel_launcher.py:9: RuntimeWarning: divide by zero encountered in log

  if name == 'main':

[ 107.09155916  -17.47261277]

 

减小学习速率,损失函数会有很有更小的值,这就意味着回归函数有更优的拟合。是这样吗,当然不是,我们目的当然是寻找使J(θ)有最小值的θ,然而那是对某一固定速率来讲的。但不同固定速率会导致不同的J(θ)收敛形式。如果收敛过缓,反而会导致低的精度。

 

n [55]: logitic_fuc(X,Y,alpha=0.0000000065,iteration_1=5000)

上面是预测Y=1时的概率。

比较以上数据,我们发现预测根本就不准。

怎么办呢? 通过编写精确度函数来解决这个问题。

精确度定义=正确预测分类次数/目标集总数

def pricise_func(ary_theo,ar_known):

    score=0

    bool_1=ary_theo>0.5

    bool_2=ar_known==1

    bool_2_list=list(bool_2)

    nr=bool_2_list.count(True)

    for j in range(bool_1.shape[0]):

        if bool_1[j] and bool_2[j]:

           score+=1

return score/nr

改进精度函数:

def pricise_func(ary_theo,ar_known):

    score=0

    bool_1=ary_theo>0.5

    bool_2=ar_known==1

    bool_2_list=list(bool_2)

    #nr=bool_2_list.count(True)

    for j in range(bool_1.shape[0]):

        if (bool_1[j] and bool_2[j])or(not(bool_1[j]) and not(bool_2[j])):

            score+=1

    return score/len(ar_known)

下面通过它展开我们的训练:训练正确的速率。

trager=0.0001

alpha_opt=0

for i in range(120,220):

    alpha_1=i*0.00005

    ary_theo=logitic_fuc(X,Y,alpha=alpha_1,iteration_1=3600)

    score=pricise_func(ary_theo,Y)

    if score>trager:

        trager=score

        alpha_opt=alpha_1

print(trager,alpha_opt)

0.89 0.006

运行起来太慢,因此分段运行,上面是最佳结果。谁有牛逼计算机,可在家自行操练。

比如运行下面代码,可以得到整个的得分,以及与其对应的alpha值。

 #trager=0.0001

#list_score=[]

list_alpha_score=[]

for i in range(120,220):

    alpha_1=i*0.0005

    ary_theo=logitic_fuc(X,Y,alpha=alpha_1,iteration_1=3600)

list_alpha_score.append((alpha_1,pricise_func(ary_theo,Y)))

list_alpha_score

自己在家运行

下面我们应用牛顿迭代法对其求解,牛顿迭代法的优点

1.     收敛速度极快,往往几步即可搞定,大大提高了运算速率

2.     无需额外设定下降速率

注意:牛顿迭代法是通过产生奇异矩阵来判断训练是否结束,也就是说通过奇异矩阵的产生间接得到最优的回归系数。奇异矩阵一旦产生,将连续持续产生。

def logitic_fuc_newton(X,Y,iteration_1=300):

    from scipy import linalg

    m,n = X.shape #矩阵大小

    #alpha = 0.0065 #设定学习速率

    theta_nw = np.zeros(n) #初始化参数

    #iteration_1=3000

    J = pd.Series(np.zeros(iteration_1, dtype = float)) #构造损失函数承载器

    for i in range(iteration_1):

        h = logit(np.dot(X, theta_nw)) #回归函数,h是矢量

        J[i] = -(1/100.)np.sum(Ynp.log(h)+(1-Y)*np.log(1-h)) #计算损失函数值 

        #print(J[i])   

        diff = h - Y #概率差

        grad = (1/m)*np.dot(X.T, diff) #梯度,

        M=((1/m)h(1-h))*np.identity(m)#中间矩阵

        Hesse_matrix=np.dot(X.T,np.dot(M,X))

        If linalg.det(Hesse_matrix)==0:

           continue

        theta_nw -= np.dot(linalg.inv(Hesse_matrix),grad)#牛顿迭代

    #J.plot()

    #plt.show()

return logit(np.dot(X, theta_nw))

pricise_func(logitic_fuc_newton(X,Y,iteration_1=3000),Y)

Out[18]: 0.9