sklearn 逻辑回归

Alex一晚上都没睡好觉,被IEEE-CIS Fraud Detection折磨的死去活来,不管怎么调参,用什么样的策略,评分就是上不去,这可不行,什么时候认过输,生死看淡,不服就干!结果:

第二天,Alex打算去工作室问问Bachelor,这家伙肯定还藏了不少东西没说,结果Bachelor不知道是因为心虚还是咋的,竟然没来,工作室只有一个肤白貌美大长腿的实习生MM在,听Bachelor说这个是实习生是个高手,也是MIT过来的,而且人家主修的就是人工智能这方面,Alex决定厚着脸皮去问问。

Alex:“Hi Coco, Do you know the credit card fraud detection we received recently?”

Coco:“你说啥?”

Alex:“我靠,你会说中文。”

Coco:“相较于你的英文,我还是听懂了你的中文。”

ALex:“。。。。。。”

ALex:“我说你知道咱们工作室最近接的那个信用卡欺诈检测的项目么?”

Coco:“知道啊,那个项目就是我接的,只不过现在是Bachelor负责,我跟进。”

Alex:“那太好了,Bachelor昨天给我讲了讲,但是我回去自己做的时候准确率出奇的低。”

Coco:“你跟我说说Bachelor讲了啥,我帮你看看吧。”

于是Alex就把昨天的逻辑回归又说了一遍…

Coco:“整体看来没问题,只不过Bachelor只讲了逻辑回归的原理,应用在这个项目上还需要一些处理。”

于是,Alex一边听着Coco的讲解,一边擦口水…

Coco倒是没多想,专心的给Alex讲解:

这样吧,我就给你捋一下工作室目前是怎么做的。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plttrain_identity = pd.read_csv('/kaggle/input/ieee-fraud-detection/train_identity.csv')
train_transaction = pd.read_csv('/kaggle/input/ieee-fraud-detection/train_transaction.csv')
data = pd.merge(train_transaction, train_identity, on="TransactionID", how="left")
data.drop("TransactionID", axis=1, inplace=True)    # TransactionID说实话没啥用
data.drop("TransactionDT", axis=1, inplace=True)    # TransactionDT类似于时间戳,也没啥用
del train_identity, train_transaction

上来还是先把两张表的数据读进内存里,然后通过TransactionID连接起来制作一个train表,之后既可以把原来的两张表删了,不然会占用内存。

pd.set_option('display.max_columns',None)    # 设置pandas显示列不限制数量
pd.set_option('display.max_rows',None)       # 设置pandas显示行不限制数量
data.head()

数据预处理

首先还是去掉缺失值超过50%的特征:

na_count = data.isnull().sum().sort_values(ascending=False)
na_rate = na_count / len(data)
na_data = pd.concat([na_count,na_rate],axis=1,keys=['count','ratio'])
data.drop(na_data[na_data['ratio'] > 0.3].index, axis=1, inplace=True)

将所有的离散型数据对应为数值型数据,缺失值用均值填充:

for col in data.columns:if data[col].dtypes == "object":data[col], uniques = pd.factorize(data[col])data[col].fillna(data[col].mean(), inplace=True)
data.head()

其实在这个项目里,重要的是数据预处理而不是逻辑回归的算法。

拿到数据之后,先简单看一下,isFraud表示有没有没诈骗,也就是我们的y值,0表示没有被诈骗,1表示被诈骗了,但是在日常生活中,虽然诈骗比较多,但还是正常样本占大多数,所以我们先看一下正负样本的统计。

count_isFraud = pd.value_counts(data["isFraud"], sort=True)
count_isFraud.plot(kind="bar")    # 条形图
plt.title("Fraud statistics")
plt.xlabel("isFraud")
plt.ylabel("Frequency")

X = data.iloc[:, data.columns != "isFraud"]
Y = data.iloc[:, data.columns == "isFraud"]

通过条形图我们可以发现,正负样本量是非常不均衡的,这会对我们的模型计算产生很大的影响,我估计你昨天测试集的结果应该全都是0吧。

对于这种样本不均衡的数据最常使用的有两种解决方案:

1.过采样:通过1样本数据制造一些数据,让两种样本数据保持平衡;

2.下采样:在0样本数据中随机抽取跟1样本数据一样多的数据,让两种样本数据保持均衡。

# 过采样——通过第三方库可以很方便的实现
from imblearn.over_sampling import SMOTE
over_sample = SMOTE()
X_over_sample_data, Y_over_sample_data = over_sample.fit_sample(X.values, Y.values)
X_over_sample_data = pd.DataFrame(X_over_sample_data)
Y_over_sample_data = pd.DataFrame(Y_over_sample_data)
# 看一下过采样数据集的长度
print("Total number of normal =", len(Y_over_sample_data[Y_over_sample_data == 0]))
print("Total number of fraud =", len(Y_over_sample_data[Y_over_sample_data == 1]))
# 下采样
number_of_fraud = len(data[data.isFraud == 1])    # 统计被诈骗数据量
fraud_indices = np.array(data[data.isFraud == 1].index)    # 被诈骗数据索引
normal_indices = np.array(data[data.isFraud == 0].index)   # 正常数据索引# 在正常数据中随机选择与被诈骗数据量相等的正常数据的索引
random_normal_indices = np.array(np.random.choice(normal_indices, number_of_fraud, replace=False))# 将所有被诈骗的数据索引和随机选择的等量正常数据索引合并
under_sample_indices = np.concatenate([fraud_indices, random_normal_indices])
# 从原始数据中取出下采样数据集
under_sample_data = data.iloc[under_sample_indices, :]X_under_sample = under_sample_data.iloc[:, under_sample_data.columns != "isFraud"]
Y_under_sample = under_sample_data.iloc[:, under_sample_data.columns == "isFraud"]
# 看一下下采样数据集的长度
print("Total number of under_sample_data =", len(under_sample_data))
print("Total number of normal =", len(under_sample_data[data.isFraud == 0]))
print("Total number of fraud =", len(under_sample_data[data.isFraud == 1]))

标准化

在我们做机器学习模型的时候,要保证特征之间的分布数据是差不多,也就是保证初始情况下每一列特征的重要程度是相似的,比如说card1这一列,它的数据相比如其它的数据都非常大,在训练模型的时候机器可能认为card1这行数据非常重要,但实际上并不能确定。

因此,我们需要对data进行标准化的处理,通过sklearn的preprocessing模块可以快速的帮助我们队数据做标准化:

from sklearn.preprocessing import StandardScalercols = X_under_sample.columnsfor col in cols:X[col] = StandardScaler().fit_transform(X[col].values.reshape(-1, 1))for col in cols:X_under_sample[col] = StandardScaler().fit_transform(X_under_sample[col].values.reshape(-1, 1))for col in cols:X_over_sample_data[col] = StandardScaler().fit_transform(X_over_sample_data[col].values.reshape(-1, 1))

交叉验证

为了在不使用测试集的情况下验证模型的效果,通常在训练一个机器学习的模型之前,会对train数据集进行切分:

我们把训练集分成5份,然后进行五轮训练:

第一轮:第1份数据留作验证,2、3、4、5份数据用作训练模型;第二轮:第2份数据留作验证,1、3、4、5份数据用作训练模型;第三轮:第3份数据留作验证,1、2、4、5份数据用作训练模型;第四轮:第4份数据留作验证,1、2、3、5份数据用作训练模型;第五轮:第5份数据留作验证,1、2、3、4份数据用作训练模型;

最后针对每一轮训练的结果取一个平均的效果,会让我们的模型变得更加优秀,当然这个效果不用我们来实现,sklearn已经帮我们实现好了:

from sklearn.model_selection import train_test_split

简单来说,train_test_split就是输入训练集的X和Y,返回切分后的训练集X、Y,验证集X、Y。

# 对原始的全部数据进行切分
X_train, X_test, Y_train, y_test = train_test_split(X, Y, test_size=0.2)# 对下采样数据集进行切分
X_under_sample_train, X_under_sample_test, Y_under_sample_train, Y_under_sample_test = train_test_split(X_under_sample, Y_under_sample, test_size=0.2)# 对上采样数据集进行切分
X_over_sample_train, X_over_sample_test, Y_over_sample_train, Y_over_sample_test = train_test_split(X_over_sample_data, Y_over_sample_data, test_size=0.2)

模型评估

一个模型的好坏不能只看它的准确率,举一个简单的例子:

假设1000个人中,有900个人是正常的,有100个人被诈骗。从这1000个人中抽出100人来测试某个模型,这100个人中有90个人是正常的,有10个人是被诈骗的。有一个非常粗暴的模型,将输入的样本都判断为正常,那么这个模型在处理这100个数据的时候,会预测准那90个正常的,但剩下10个预测错误。模型的准确率为90%,但是这显然不是一个好模型。

所以,在样本不均衡的情况下不能够使用准确率作为模型评估的标准,而要使用recall,也就是召回率。

计算recall需要先看一个表格:

正类 负类
检索到 True Positive(TP),正类判断为正类 False Positive(FP),负类判断为正类
未检索到 False Negative(FN),正类判断为负类 True Negative(TN),负类判断为负类

recall=TPTP+FNrecall = \frac{TP}{TP+FN}recall=TP+FNTP​

这看起来不是很好理解,我们再来举一个例子:

还是1000个人中,有900个人是正常的,有100个人被诈骗。又有一个不靠谱的模型,将输入的样本50%判断为正常,50%判断为异常,我们的目的是找出所有被诈骗的。经过这个模型的计算,得到500个模型认为的被诈骗人,但是500个人中只有50个人是被诈骗的,剩下450个都是正常的。检索到的500个人中:50个异常数据被判断为异常,TP=50;450个正常数据被判断为异常,FP=450。未被检索到的500个人中:50个异常数据被判断为正常,FN=50;450个正常数据被判断为正常,TN=450。recall = 50 / (50 + 50) = 0.5

正则化惩罚项

我们训练模型的目标其实就是求出参数θ,假设通过计算得到θ1和θ2两个模型,尽管参数值截然不同,但在预测中有可能会得到相同的结果。

那么对于这两个模型,我们到底要选择哪一个呢?

在回答这个问题之前,我们要了解一个知识点,过拟合

过拟合问题是机器学习中很让人头疼的一件事情,举个例子:

暂时不用管这是什么算法,我们的目标是对红绿色的点进行分类,可以看到对于大部分数据区分的还是比较完美的,但是绿色范围在左下方突出了一个角,为了去拟合在红色堆里那个按照正常的逻辑应该判定为红色点的绿色点,但是,有可能那个离群的绿色点是个错误数据。

这就是过拟合,只能说我们的模型对于训练集来说太过完美,这可并不是一件好事,我们的目的是想让模型能够匹配所有的数据,不仅仅局限于训练集。

过拟合通常发生在训练数据不够多或者训练过度(overtrainging)的情况下,而正则化方法就是为了解决过拟合的问题而诞生的,通过在损失函数中引入额外的计算项,可以有效的防止过拟合,提高模型的泛化能力。

目标函数=损失函数+正则化惩罚项目标函数 = 损失函数 + 正则化惩罚项目标函数=损失函数+正则化惩罚项

目前有两种正则化惩罚项:

L1参数正则化:ω(θ)=∣∣w∣∣=∑i∣wi∣\omega(\theta)=||w||=\sum_i|w_i|ω(θ)=∣∣w∣∣=i∑​∣wi​∣

L2参数正则化:ω(θ)=12∣w∣2\omega(\theta)=\frac{1}{2}|w|^2ω(θ)=21​∣w∣2

逻辑回归模型

我们已经学习过逻辑回归算法的推导过程,能够将计算过程由代码实现,带如果每次使用逻辑回归都要再写一遍代码显然是非常繁琐的,sklearn包帮我们实现好了一个很优秀的逻辑回归训练器,只需要输入相应的参数,就可以造出一个训练器。

import time
from sklearn.metrics import recall_score
from sklearn.model_selection import KFold
from sklearn.linear_model import LogisticRegression
def kfold_scores(x_train_data, y_train_data):start_time = time.time()fold = KFold(3, shuffle=True)       # 3折交叉验证c_param_range = [10, 100, 1000]      # 惩罚力度,正则化惩罚项的系数  # 做可视化展示results_table = pd.DataFrame(index=range(len(c_param_range), 2), columns=["C_parameter", "Mean recall scores"])results_table["C_parameter"] = c_param_range# 不确定哪一个正则化惩罚项的系数更好,因此采用循环确认index = 0for c_param in c_param_range:print('--------------------------------------------------------------------------------')print("If C parameter =", c_param, end="\n\n")# 做交叉验证recall_accs = []lr = LogisticRegression(C=c_param, penalty='l1', solver='liblinear', max_iter=10000)for iteration, indices in enumerate(fold.split(x_train_data)):# 拟合训练数据lr.fit(x_train_data.iloc[indices[0], :], y_train_data.iloc[indices[0], :].values.ravel())# 使用验证集得出预测数据y_predicted_undersample = lr.predict(x_train_data.iloc[indices[1], :])# 计算recallrecall_acc = recall_score(y_train_data.iloc[indices[1], :], y_predicted_undersample)recall_accs.append(recall_acc)print('\tIteration ', iteration, ': recall score = ', recall_acc)index += 1# 计算recall的平均值results_table.loc[index, "Mean recall scores"] = np.mean(recall_accs)print('Mean recall score = ', results_table.loc[index, "Mean recall scores"], end="\n\n")print('--------------------------------------------------------------------------------')best_c_param = results_table.loc[results_table['Mean recall scores'].astype(float).idxmax()]['C_parameter']print('Best C parameter = ', best_c_param, "\t duration: ", time.time() - start_time)return lr, best_c_param
# 对原始全部数据进行测试
# lr1, param1 = kfold_scores(X_train, Y_train)
del X_train
del Y_train
# 对下采样数据进行测试
lr2, param2 = kfold_scores(X_under_sample_train, Y_under_sample_train)
del X_under_sample_train
del Y_under_sample_train
# 对上采样数据进行测试
# lr3, param3 = kfold_scores(X_over_sample_train, Y_over_sample_train)
del X_over_sample_train
del Y_over_sample_train
test_identity = pd.read_csv('/kaggle/input/ieee-fraud-detection/test_identity.csv')
test_transaction = pd.read_csv('/kaggle/input/ieee-fraud-detection/test_transaction.csv')
data = pd.merge(test_transaction, test_identity, on="TransactionID", how="left")
test_ID = data[["TransactionID"]]
data.drop("TransactionID", axis=1, inplace=True)    # TransactionID说实话没啥用
data.drop("TransactionDT", axis=1, inplace=True)    # TransactionDT类似于时间戳,也没啥用for col in data.columns:if col.startswith("id"):newcol = col.replace("-", "_")data.rename(columns={col: newcol},inplace=True)del test_identity, test_transactiondata.drop(na_data[na_data['ratio'] > 0.3].index, axis=1, inplace=True)
for col in data.columns:if data[col].dtypes == "object":data[col], uniques = pd.factorize(data[col])data[col].fillna(data[col].mean(), inplace=True)
for col in cols:data[col] = StandardScaler().fit_transform(data[col].values.reshape(-1, 1))test_predict = lr2.predict(data.values)
submission = pd.concat([test_ID, pd.Series(test_predict)], axis=1, keys=["TransactionID", "isFraud"])
submission.to_csv("submission1.csv", index=False)

好了,这就是通过sklearn来做这个逻辑回归的项目,咱们可以吧结果提交评测网站IEEE-CIS Fraud Detection看看效果怎么样:


Coco:“你看,这么做是不是效果比你之前那个好一点了。”

Alex:“我靠,真大。。。。”

Coco:“什么真大?”

Alex:“额,分数啊。”

Coco:“行,大概就是这个套路,剩下的是就是细节的问题了,你回去也可以试试过采样和正常数据能达到什么效果。”

Alex:“不用回去了,我就在这试。”

小姐姐教我的 sklearn 逻辑回归相关推荐

  1. logisticregression参数_通俗地说逻辑回归【Logistic regression】算法(二)sklearn逻辑回归实战...

    前情提要: 通俗地说逻辑回归[Logistic regression]算法(一) 逻辑回归模型原理介绍 上一篇主要介绍了逻辑回归中,相对理论化的知识,这次主要是对上篇做一点点补充,以及介绍sklear ...

  2. 一步步教你轻松学逻辑回归模型算法

    一步步教你轻松学逻辑回归模型算法 ( 白宁超2018年9月6日15: 01:20) 导读:逻辑回归(Logistic regression)即逻辑模型,属于常见的一种分类算法.本文将从理论介绍开始,搞 ...

  3. sklearn 逻辑回归Increase the number of iterations (max_iter) or scale the data as shown in解决方案

      大家好,我是爱编程的喵喵.双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中.从事机器学习以及相关的前后端开发工作.曾在阿里云.科大讯飞.CCF等比赛获得多次Top名次.现 ...

  4. sklearn逻辑回归参数设置_【机器学习笔记】:逻辑回归实战练习(二)

    作者:xiaoyu 微信公众号:Python数据科学 知乎:python数据分析师 前言 前几篇介绍了逻辑回归在机器学习中的重要性:5个原因告诉你:为什么在成为数据科学家之前,"逻辑回归&q ...

  5. python机器学习库sklearn——逻辑回归

    全栈工程师开发手册 (作者:栾鹏) python数据挖掘系列教程 逻辑分类的相关的知识内容可以参考 http://blog.csdn.net/luanpeng825485697/article/det ...

  6. sklearn 逻辑回归中的参数的详解'newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'

    penalty : str, 'l1' or 'l2', default: 'l2' 这个是l1 or l2正则化,一般选l2正则化对于逻辑回归分类算法 dual:选择默认的就好,针对的就是l2正则和 ...

  7. sklearn逻辑回归为什么要归一化

    原创文章,转载请说明本文来自:<老饼讲解-机器学习> ml.bbbdata.com 目录 一.归一化对梯度下降的影响 01.下降路径的影响 02.对步长设置的影响 二.逻辑回归何时需要归一 ...

  8. sklearn逻辑回归案例分析 《良/恶性乳腺癌肿瘤预测》

    由于对逻辑回归等算法做到深刻理解有点难,目前还在学习中,尽管有现成的模型库,我们还是需要对模型的底层实现有一个了解.这里先记录一下如何利用sklearn的LogisticRegression来做一个简 ...

  9. 【机器学习】:sklearn逻辑回归案例分析 《良/恶性乳腺癌肿瘤预测》

    由于对逻辑回归等算法做到深刻理解有点难,目前还在学习中,尽管有现成的模型库,我们还是需要对模型的底层实现有一个了解.这里先记录一下如何利用sklearn的LogisticRegression来做一个简 ...

最新文章

  1. git用法从入门到精通
  2. python导入mongo数据库文件
  3. 双指针算法(四):力扣 88.合并两个有序数组 | 经典例题
  4. linux python3 pip3_linux环境下安装python3以及pip3
  5. [Flashback]开启数据库闪回数据库功能
  6. http请求在asp.net中的应用
  7. 题目1179:阶乘-------------阶乘不用long long int 就不能AC
  8. Keras-5 基于 ImageDataGenerator 的 Data Augmentation实现
  9. OC中字符串的提取与替换-四种不同方法实现
  10. golang debug 配置_新鲜出炉的golang日志库
  11. epson r1900 清零软件_Epson爱普生me1100清零软件 me1100打印机废墨清零软件
  12. 数字藏品APP源码,无加密
  13. TB6612与电机编码器
  14. vue 移动端弹窗后禁止页面滚动 @touchmove.prevent
  15. 《LeGO-LOAM: Lightweight and Ground-OptimizedLidar Odometry and Mapping on Variable Terrain》论文精读
  16. java国际化转换_java 实现国际化 中英文语言切换
  17. 微信中提示浏览器打开网址链接如何解决
  18. /usr/bin/ld: cannot find -lxxx的错误
  19. 中国移动规范学习——4A技术要求(账号管理)
  20. elastic-job 有没有java 接口去触发定时任务执行

热门文章

  1. 今天写的上传类,纯练手之作,供新人学习
  2. 网络编程练习 -- NSURLConnection -- get/post请求
  3. sqlserver结果集转为字符串
  4. 逻辑地址、线性地址、物理地址和虚拟地址
  5. concat合并的数组会有顺序么_JS数组 Array
  6. python自动控制_程序员用Python实现自动化控制键盘和鼠标
  7. 可以改动的option组件_uni-app WebView 组件通信
  8. 计算机专业期末考试是编程序,武汉大学计算机学院C语言期末考试
  9. vue 返回上一页传参_H5页面与微信小程序相互跳转并传参(web-view)
  10. 河南城建学院linux期末试题,河南城建学院Linux期末考试复习题