0
点赞
收藏
分享

微信扫一扫

机器学习分类算法之Logistic 回归(逻辑回归)

目录

什么是逻辑回归?

Sigmoid 函数

似然函数

 梯度下降

判定边界

损失函数

逻辑回归优点

逻辑回归缺点

代码实现

Logistic Regression参数详解

正则化选择参数:penalty

优化算法选择参数:solver

其他参数

代码案例

结果显示

每文一语


什么是逻辑回归?

逻辑回归算法是用来解决分类问题的。回归与分类的区别在于:回归所预测的目标量的取值是连续的(例如房屋的价格);而分类所预测的目标变量的取值是离散的(例如判断肿瘤大小是否为恶性)。

如图所示,X为数据点-肿瘤的大小,Y为观测值-是否为恶性肿瘤(0良性肿瘤,1恶性肿瘤)。通过构建线性回归模型,即可根据肿瘤大小,预测是否为恶性肿瘤,hθ(x)≥.05为恶性,hθ(x)<0.5为良性。

 那有的人就会提出疑问,逻辑回归可以做分类,那么线性回归可不可以做分类呢?答案是可以,但是线性回归的鲁棒性(稳定和可靠)很差,如下图所示,因最右边噪点的存在,使回归模型在训练上表现很差,这主要是由于线性回归在整个实数域内敏感度一致,而分类范围,需要在[0,1]。

Sigmoid 函数

Sigmoid 函数在有个很漂亮的“S”形,如下图所示:

 对于线性回归的情况,方程如下:

构造预测函数为:取值在[0,1]

似然函数

 梯度下降

在梯度下降的算法中,还有两个比较重要的点叫做学习率和步数。

学习率是指你在下山的过程中每走的一步大小,你要是厉害能一步跨到山底也算是你厉害,当然你也有可能跨到对面山上,所以学习率我们在设置的时候就要设置的稍微小点,当然也别太小了,这样学习的会很慢。学习率是自己设定的,比如0.01。

迭代次数就是指你在下山过程中你要走多少步,小了的话你可能没有走到山底,多了的话可能你就会在山底来回的走。

学习率和迭代次数都是自定义的,需要通过经验和实际操作去验证和设置。最好在运行代码的时候打印出来,这个就会看到收敛的情况,当很长一段时间内,收敛的效果已经不明显了,基本就到头了。

梯度下降有三种方法:

判定边界

损失函数

逻辑回归优点

逻辑回归缺点

总结一下:回归假设数据服从伯努利分布,通过极大似然函数的方法,运用梯度下降来求解参数,最终达到数据二分类的目的。

代码实现

Logistic Regression参数详解

LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
          penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False)

其中,参数 penalty 表示惩罚项( L1 、 L2 值可选

正则化选择参数:penalty

在调参时如果我们主要的目的只是为了解决过拟合,一般penalty选择L2正则化就够了。但是如果选择L2正则化发现还是过拟合,即预测效果差的时候,就可以考虑L1正则化。另外,如果模型的特征非常多,我们希望一些不重要的特征系数归零,从而让模型系数稀疏化的话,也可以使用L1正则化。
penalty参数的选择会影响我们损失函数优化算法的选择。即参数solver的选择,如果是L2正则化,那么4种可选的算法{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’}都可以选择。

但是如果penalty是L1正则化的话,就只能选择‘liblinear’了。这是因为L1正则化的损失函数不是连续可导的,而{‘newton-cg’, ‘lbfgs’,‘sag’}这三种优化算法时都需要损失函数的一阶或者二阶连续导数。而‘liblinear’并没有这个依赖。

优化算法选择参数:solver

 newton-cg, lbfgs和sag这三种优化算法时都需要损失函数的一阶或者二阶连续导数,因此不能用于没有连续导数的L1正则化,只能用于L2正则化。而liblinear通吃L1正则化和L2正则化。 

其他参数

这里的参数只做介绍,一般也不需要调试

一般来说,我们知道这些参数所使用的的场景,那么就会少走一些坑,比如我们知道L1,L2正则项的意义是什么,L2主要解决过拟合,L1特征选取,也可以解决过拟合,默认是L2

代码案例

具体的代码步骤,我这里就不一一的做详细的解释了,因为我喜欢在jupyter notebook中机器学习,每一步都可以知道如何优化,下面的案例我首先通过逻辑回归进行调参,并使用相关系数进行特征选取,然后得出的效果分数可以达到91%,这比不做特征选取要好很多,随后我又使用逻辑回归自带的特征评估权重做了一次选取,最后效果有所提升。

feature_weight = model.coef_.tolist()[0]
feature_name = X_name
feature_sort = pd.Series(data = feature_weight ,index = feature_name)
feature_sort = feature_sort.sort_values(ascending = False)
print(feature_sort.index)
plt.figure(figsize=(10,8))
sns.barplot(feature_sort.values,feature_sort.index, orient='h')

选取了8个重要的特征

完整代码如下,由于数据集是科研的数据,这里就不做导入说明了

# 导入数据 分割数据
df=**************不做展示***********************

# # 特征筛选(经过一番测试,不需要进行特征筛选)
# X_name=df.corr()[["n23"]].sort_values(by="n23",ascending=False).iloc[1:9].index.values.astype("U")



# X_name=feature_sort.index[:1]

# 测试出来的最佳特征!!!!!!!!
X_name=['n22', 'n8', 'n19f1', 'n18', 'n13', 'n10new','n9','leibie']

print(X_name)
X=df.loc[:,X_name]

# X=df.iloc[:,:-1]
y=df.iloc[:,-1]
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,stratify=y,random_state=1)
# X_train

score = []
C_range = np.linspace(0.01, 30, 50)
for i in C_range:
    clf = LogisticRegression(C=i,penalty="l2").fit(X_train, y_train)
    score.append(clf.score(X_test, y_test))
    
print(max(score), C_range[score.index(max(score))])
best_C=C_range[score.index(max(score))]
#设置标题
plt. title(f' LogisticRegression {max(score)}')
#设置x轴标签
plt. xlabel(' C')
#设置y轴标签
plt. ylabel(' Score')
#添加图例
# plt. legend()
plt.plot(C_range, score)
plt.show()

solvers = ["newton-cg",  "lbfgs", "liblinear","sag"]
for solver in solvers:
    clf = LogisticRegression(solver=solver,
              C=best_C
              ).fit(X_train, y_train)
    print("The accuracy under solver %s is %f" % (solver, clf.score(X_test, y_test)))
best_sover='liblinear'


model=LogisticRegression(C=11.02673469387755,penalty='l2',solver=best_sover)
# 训练模型
model.fit(X_train,y_train)
# 预测值
y_pred = model.predict(X_test)

'''
评估指标
'''
# 求出预测和真实一样的数目
true = np.sum(y_pred == y_test )
print('预测对的结果数目为:', true)
print('预测错的的结果数目为:', y_test.shape[0]-true)
# 评估指标
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score
print('预测数据的准确率为: {:.4}%'.format(accuracy_score(y_test,y_pred)*100))
print('预测数据的精确率为:{:.4}%'.format(
      precision_score(y_test,y_pred)*100))
print('预测数据的召回率为:{:.4}%'.format(
      recall_score(y_test,y_pred)*100))
# print("训练数据的F1值为:", f1score_train)
print('预测数据的F1值为:',
      f1_score(y_test,y_pred))
print('预测数据的Cohen’s Kappa系数为:',
      cohen_kappa_score(y_test,y_pred))
# 打印分类报告
print('预测数据的分类报告为:','\n',
      classification_report(y_test,y_pred))



from sklearn.metrics import precision_recall_curve
from sklearn import metrics
# 预测正例的概率
y_pred_prob=model.predict_proba(X_test)[:,1]
# y_pred_prob ,返回两列,第一列代表类别0,第二列代表类别1的概率
#https://blog.csdn.net/dream6104/article/details/89218239
fpr, tpr, thresholds = metrics.roc_curve(y_test,y_pred_prob, pos_label=2)
#pos_label,代表真阳性标签,就是说是分类里面的好的标签,这个要看你的特征目标标签是0,1,还是1,2
roc_auc = metrics.auc(fpr, tpr)  #auc为Roc曲线下的面积
# print(roc_auc)
plt.figure(figsize=(8,6))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.plot(fpr, tpr, 'r',label='AUC = %0.2f'% roc_auc)
plt.legend(loc='lower right')
# plt.plot([0, 1], [0, 1], 'r--')
plt.xlim([0, 1.1])
plt.ylim([0, 1.1])
plt.xlabel('False Positive Rate') #横坐标是fpr
plt.ylabel('True Positive Rate')  #纵坐标是tpr
plt.title('Receiver operating characteristic example')
plt.show()

结果显示

效果还是有所提升,通过反复的调试,我们的逻辑回归已经大功告成了!

每文一语

举报

相关推荐

0 条评论