逻辑回归

实验内容及步骤

本实验主要利用逻辑回归(logistics regression)对kaggle数据集进行分析预测。

  • 数据处理
#NULL项舍弃
df=df.dropna()
  • ENcode,将非数字型的属性值编码为0~1的数字
df.Gender=df.Gender.map({'Male':1,'Female':0})
df.Married=df.Married.map({'Yes':1,'No':0})
df.Dependents=df.Dependents.map({'1':0,'0':0.3,'2':0.6,'3+':1})
df.Education=df.Education.map({'Graduate':1,'Not Graduate':0})
df.Self_Employed=df.Self_Employed.map({'Yes':1,'No':0})
df.Property_Area=df.Property_Area.map({'Rural':0,'Urban':0.5,'Semiurban':1})
df.Loan_Status=df.Loan_Status.map({'Y':1,'N':0})
  • 数据归一化,采用$X_{norm}=(X-\mu)/\sigma$,其中$\mu$为平均值,$\sigma$为标准差
import numpy as np
from sklearn.model_selection import train_test_split
X = df.drop(["Loan_Status"], axis=1)
y = df["Loan_Status"]
X_norm=np.array(X)
mu = np.mean(X_norm,0)         
sigma = np.std(X_norm,0)      
for i in range(X.shape[1]):
    X_norm[:,i]=(X_norm[:,i]-mu[i])/sigma[i]
  • 划分训练集和测试集,此处采用训练集:测试机=8:2的方式进行划分,利用permutation()函数进行处理
num=np.random.permutation(len(y))
X_norm=X_norm[num]
y=y[num]
a=int(0.2*len(y))
X_test=X_norm[0:a-1,:]
X_train=X_norm[a:,:]
y_test=y[0:a-1]
y_train=y[a:]
  • 训练部分预处理
col=X.shape[1]+1 
m=len(y)
X=np.array(X)
X = np.hstack((np.ones((m,1)),X))  
y=np.array(y).reshape(-1,1)
theta=np.zeros((col,1))
n=len(theta)
temp=np.matrix(np.zeros((n,int(max_iter))))
  • 损失函数:利用交叉熵损失函数计算
loss=-np.dot(np.transpose(np.log(self.sigmoid(X,theta))),y)/m-np.dot(np.transpose(np.log(1-self.sigmoid(X,theta))),1-y)/m
  • 梯度下降
grad=np.dot(np.transpose(X),self.sigmoid(X,theta)-y)
  • 正则化,其中L1相当于添加1-范数项,L2相当于在损失函数中添加2-范数项
if self.penalty=="l1":
   loss+=self.gamma*np.sum(np.abs(theta))/m
   grad+=self.gamma*np.sign(theta)
else:
   loss+=self.gamma*np.sum(np.square(theta))/m
   grad+=self.gamma*theta
  • 训练部分函数主体
for i in range(int(max_iter)):
     #计算loss和gard
     temp[:,i]=theta-(lr/m)*grad
     theta=temp[:,i]
     m = len(y)
     j_history=np.append(j_history,np.sum(np.square(loss))
     if np.sum(np.square(loss))<tol:
          break
  • sigmoid函数
return 1.0/(1+np.exp(-np.dot(w,x)))
  • 预测函数
def predict(self, X,y,theta):
    m=len(y)
    X=np.array(X)
    X=np.hstack((np.ones((m,1)),X))  
    p=np.dot(X,theta)
    p=p.reshape(-1,1)
    y=np.array(y).reshape(-1,1)
    sum=0
    for i in range(m):
        if y[i]==1 and p[i]>0:
        	sum+=1
        elif y[i]==0 and p[i]<0:
        	sum+=1
    return sum/m

实验结果及分析

采用实验默认参数进行训练:lr=0.01, tol=1e-7, max_iter=3e3,penalty=”l2”,gamma=0,fit_intercept=True

Acc=83.2%

  • 参数比较

首先对不同的学习率进行比较,如下为不同的学习率下的损失函数

lr=0.001,此时到达max_iter时损失函数仍在快速递减、

相比之下lr=0.01的学习率避免了图像的抖动,也避免了训练过慢导致训练时间长。

不同的正则化参数:

观察图像的纵坐标,可以看出选择l2正则化的收敛效果最好,因此采取l2正则化。

  • 最佳准确率的情况:

(此时的参数:lr=0.01, tol=1e-7, max_iter=3e3,penalty=”l2”,gamma=1,fit_intercept=True)

准确率达到了87.37%,其中测试集和训练集的比例为2:8