负极大似然函数就是损失函数
计算梯度公式
手写逻辑回归
import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer
bc=load_breast_cancer()
X=bc['data']
Y=bc['target']
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
X=StandardScaler().fit_transform(X)
X=np.hstack(np.ones((X.shape[0],1)),X)
#使用sigmod的函数
def sigmoid(X,w):
z=X*w
return 1/(1+np.exp(-z))
def get_label(Y_pred,threshold=0.5):
return (Y_pred>=threshold).astype(int)
from sklearn.model_selection import train_test_split
Xtrain,Xtest,Ytrain,Ytest=train_test_split(X,Y,test_size=0.3)
def Logistic_regression(X,Y,n_iter=1000,eta=0.01):
X=np.mat(X)
w=np.mat(np.ones((X.shape[1],1)))
Y=np.mat(Y).T
acc_list=[]
for _ in range(n_iter):
sigmoid_result=sigmoid(X,w)
error=sigmoid_result-Y
gd=1/X.shape[0]*error.T*X
w=w-eta*gd.T
Y_pred=sigmoid(X,w)
acc_list.append(accuracy_score(np.array(Y).ravel(),getlabel(np.array(Y_pred).ravel())))
return w,acc_list
w,acc_list=Logistic_regression(Xtrain,Ytrain,n_iter=100000,eta=0.001)
print(acc_list[-1])
Y_pred_test=sigmoid(Xtest,w)
accuracy_score(np.array(Ytest).ravel(),get_label(np.array(Y_pred_test).ravel()))
探索算法参数
#简单使用L1和L2范式
lrl2=LogisticRegression(penalty='l2').fit(Xtrain_,Ytrain)
lrl2.score(Xtrain_,Ytrain),lrl2.score(Xtest_,Ytest)
#对于L2范式,参数值都是非0
lrl2.coef_
#实例化l1范式
lrl1=LogisticRegression(penalty='l1',solver='liblinear').fit(Xtrain_,Ytrain)
lrl1.score(Xtrain_,Ytrain),lrl1.score(Xtest_,Ytest)
#L1范式下,在某一个惩罚力度下,不重要的参数特征值直接压缩成0
lrl1.coef_
Solver优化方法
sag: 随机梯度下降法,通过对损失函数做一阶求导,使用梯度的放方向不断更新,逼近全局最优。数据量小的情况下,结果不收敛,结果不准确,但是数据量大的情况下了,快!并且还能很大可能的绕过局部最优。
newton-cg, lbfgs: 牛顿法,通过对损失函数做二阶求导,从而在小数据集下,更加快的逼近全局最优,如果数据量一旦很大的话,这个方法会非常的慢。得到了嗨森矩阵。
liblinear,效率要低很多,但是万能!不需要损失函数可导,采用一种类似贪心的算法的迭代方法,一直朝着损失函数下降的方向移动,逼近全局最优值。
对于L2范式来说,损失函数可以求导!所以可以使用sag, newton-cg, lbfgs。penalty = 'l2', solver可以是任意的,也可以使用liblinear。
对于L1范式来说,损失函数不可以求导!sag, newton-cg, lbfgs用不了。所以penalty = 'l1',solver必须是liblinear
penalty : 怎么改损失函数,是使用L1范式,还是使用L2范式
solver : 如何最小化损失函数
C惩罚项
#逻辑回归当中的这个C描述1/惩罚,也就是说C越大,惩罚越小,C越小,惩罚越大
使用cv的方法来查看模型的一个在测试集上综合的表现
from sklearn.model_selection import cross_val_score
cross_val_score(lrl1,Xtrain_,Ytrain,cv=5).mean(),cross_val_score(lrl2,Xtrain_,Ytrain,cv=5).mean()
网格搜索
Xtrain,Xtest,Ytrain,Ytest=train_test_split(X,Y,test_size=0.3,random_state=420)
std=StandardScaler().fit(Xtrain)
Xtrain_=std.transform(Xtrain)
Xtest_=std.transform(Xtest)
from sklearn.model_selection import GridSearchCV
params={'penalty':['l1','l2'],'C':np.linspace(0.2,0.7,1000)}
GS=GridSearchCV(model,params,cv=5,scoring='accuracy')
GS.fit(Xtrain_,Ytrain)
#查看最优的参数值
GS.best_params_,GS.best_score_
#GS里面best_estimator_最好分类器,通过coef_查看最好的模型w值
GS.best_estimator_coef_
多分类问题
#鸢尾花数据集做多分类
from sklearn.datasets import load_iris
iris=load_iris()
X=iris['data']
Y=iris['target']
#切分数据集并且来做标准化
Xtrain,Xtest,Ytrain,Ytest=train_test_split(X,Y,test_size=0.3,random_state=420)
std=StandardScaler().fit(Xtrain)
Xtrain_=std.transform(Xtrain)
Xtest_=std.transform(Xtest)
model=LogisticRegression(multi_class='ovr').fit(Xtrain_,Ytrain)
model.score(Xtrain_,Ytrain),model.score(Xtest_,Ytest)
分类方式选择参数
multi_class参数决定了分类方式的选择,有ovr和multinomial两个值可以选择,默认是ovr
ovr即前面提到的one-vs-rest(OvR),而multinomial即前面提到的many-vs-many(MvM),如果是二元逻辑回归,ovr和multinomial并没有任何区别,区别主要是在多元逻辑回归上。
OvR的思想很简单,无论你是多少元逻辑回归,我们都可以看做二元逻辑回归。具体做法是,对于第K
类的分类决策,我们把所有第K类的样本作为正例,除了第K类样本以外的所有样本都作为负例,然后在
上⾯做⼆元逻辑回归,得到第K类的分类模型。其他类的分类模型获得以此类推。
当需要预测新的数据的类别时,使用如下公式:
使用不同的函数去预测输入x,分别计算不同的值,然后取其中的最大值。哪个类别i对应的大,就认为属于哪个类。
而MvM则相对复杂,如果模型有T类,我们每次在所有T类样本里面选择两类样本出来,记作T1类和T2类,把所有的输出为T1和T2的样本放在一起,把T1作为正例,T2作为负例,进行二元逻辑回归,得到模型参数,我们一共需要T(T-1)/2次分类。
从上面的描述可以看出OvR相对简单,但分类效果相对略差。而MvM分类相对精确,但是分类速度没有OvR快。
如果选择了ovr,则4种损失函数的优化方法liblinear,newton-cg,lbfgs和sag都可以选择,但是如果选择了multinomial,则只能选择newton-cg,lbfgs和sag。
#使用网格搜索
model=LogisticRegression(max_iter=10000,solve='lbfgs',penalty='l2')
p={'C':np.linspace(0.1,10,100),
'multi_class':['ovr','multinomial']}
GS=GridSearchCV(model,p,cv=5)
GS.fit(Xtrain_,Ytrain)
print(GS.best_params_,GS.best_score_)
print(GS.score(Xtrain_,Ytrain),GS.score(Xtest_,Ytest))
暂无数据