洞察力无处不在。
你的数据包含洞察力。是的,你的!
数据科学不是为那些受过正规 it 培训的人保留的。任何有动机的人都可以跳上他们的笔记本电脑,开始挖掘、调查和想象。
他们可以从手头的数据着手。天哪,我们到处都有——通常数量非常大。在我们的工作和生活中,我们不断地抛出数据——尽管这些数据的质量因来源而异,但如果你告诉我,从你可以访问的数据中提取不出任何有价值的东西,我是不会相信你的。我想证明,即使是从最初可能会忽略的简单数据源中,也完全有可能获得洞察力。
照片由S O C I A L C U T在 Unsplash 上拍摄
那交易是什么?
在某些行业,比如金融业,通常不缺乏可供分析的数字数据——但我意识到,其他行业可能不存在这种情况。因此,为了表明这些原则更普遍地适用于其他类型的组织,我们将放弃这些数字,研究一个相当通用的数据文件。
对于那些渴望了解数据是如何被处理的人,你可以跟随我上传到 GitHub 的 Jupyter 笔记本。 Python 用于此分析。 Numpy 和 Pandas 用于数据操作和计算。所有的图都是使用 Matplotlib 生成的。
数据文件的前几行。
我们正在使用工作进展(WIP)文档,该文档用于记录自 2019 年以来已完成的许多精算工作项目的详细信息。我们有:
- 成员名称:任务已完成的成员的名称
- 计算类型:所需的计算类型
- 请求日期:请求工作的日期
- 截止日期:要求完成工作的日期
- 完成者:谁完成了这项工作
- 检查者:谁检查了工作
- 审核人:谁审核并批准了该工作
- 发送日期:作品完成并发送出去的日期
- 期限到了吗?:工作是否在截止日期前及时完成,即发送日期是在截止日期之前还是同一天
一旦我们检查了数据的完整性,并处理了任何错误或缺失的值,我们就可以开始了。
谁在做什么?
假设我们想跟踪 Alice 和 Bob 在工作流程中接触每个角色的程度,我们想确保他们都获得了经验并取得了进步。经过一些处理后,我们可以计算出自 2019 年初以来,爱丽丝和鲍勃每个月完成、检查和审查了多少个案例:
爱丽丝和鲍勃参与这些工作任务。
表格固然很好,但是我们的大脑不能像一个好的可视化一样真正掌握表格数据。让我们来绘制这些发现:
现在我们可以更清楚地了解这些趋势。
我们可以看到,Alice 最初做了许多案例,但现在已经转变为更多的检查角色。同样,Bob 在 2019 年初主要是检查案例,而现在他正在审查他看到的大多数案例。这两个指标都很好地表明了我们的员工正在学习和接受挑战!
我们是否按时完成了任务?
我们可能会签订某种服务水平协议,以确保我们的工作速度足够快。提供低于约定水平的服务会损害我们与客户的关系。如果他们最终去找我们的竞争对手寻求更好的服务,我们可能会失去业务。记住这一点,让我们看看最近我们是否按时完成了任务。
看起来…好吗?这有点难以判断
同样,让我们用图表来表示数据:
看起来我们有点不稳定
看起来我们通常保持 80%到 100%的案例按时交付的服务水平。然而,从 2019 年 7 月到 10 月,服务水平有相当大的下降。如果我们还没有意识到,我们会深入了解为什么我们的团队表现不佳,并解决这个问题。我们人手不足吗?那是一个特别繁忙的时期吗?我们是否需要雇用更多的长期或临时工作人员来应付?
有时候,数据分析产生的问题比它回答的问题还多,但是如果它们是正确的问题,那么我们就在朝着正确的方向前进,并增加价值。
我们错过了什么案子的最后期限?
按时完成对我们的团队和我们与客户的关系都很重要。让我们来看看在错过最后期限时最容易出问题的案例。
等着吧…
像往常一样,让我们看看是否可以用一种更清楚地揭示正在发生什么的方式来绘制这些数据:
啊哈!
有意思!有一些类型的计算相对来说很少收到,但是它们在我们错过最后期限的所有案例中占了很大比例。换句话说,不管出于什么原因,我们在这方面都差得不成比例。
潜在的行动可能是对团队如何处理这些情况进行更多的在职指导,或者可能是向全公司的培训和发展团队反馈,在新员工入职时需要更彻底地涵盖这些类型的计算。
洞察力无处不在
希望这在某种程度上证明了,当涉及到您的数据时,几乎总是有一些有趣的东西需要研究。我们仅仅触及了这个相当基础的数据集所能提供的皮毛。限制因素不是技术。它不是在现实世界中应用数据科学的机会的可用性。它甚至不是知识——有无穷无尽的资源可供我们学习。
限制因素是动机。学习曲线一开始可能很难管理,我们在学习过程中都会遇到问题。其中一些问题可能看起来无法克服,并可能导致我们在愤怒和沮丧中放弃。但是,寻求这些棘手问题的解决方案是我们发展最快的领域。只要你坚持努力,这些问题就能够也一定会被克服。
您可能不认为自己是数据科学家,但事实上,任何人都可以学习在工作中应用这些工具。所以我鼓励你——挑选一份你认为可能包含有用见解的数据。一旦你开始探索和使用它,你将很快证明自己的能力。
更多信息和积分
Andrew Hetherington 是英国伦敦的一名见习精算师和数据爱好者。
图片:由S O C I A L C U T在 Unsplash 上拍摄的望远镜照片。
洞察力是王道——如何获得洞察力并避免陷阱
很难找到对数据集如何运行的直观理解!然而,连贯地解释你的系统是如何工作的,对于找到一种建模或分析任何特征的方法是至关重要的。坚持到最后,找出为什么最初的洞察力是良好分析的关键,你必须做什么来形成你的理解,以及如何轻松避免和克服问题。
我在一个 5 人团队中一直在做一个项目,利用澳大利亚的天气数据来预测能源需求。它历时半年,模仿了一个经典的数据科学项目。从数据收集开始,转移到清理、建模,然后撰写报告。进行到一半的时候,我发现了一件事——我还在清理数据,尽管有另外四个人在做这件事,但还是花了很长时间!看起来我们有一百万个功能需要处理,其中大部分都离很远,很难使用。我认为这是一个学习更多不同的(奇特的)技术的机会,这些技术可以用来插入(填充)缺失的数据。但是… 我完全误解了我的项目。
我们不明白我们的数据是如何工作的,所以必须考虑 100 个特征,而不是 3 个…
约翰·巴克利普在 Unsplash 上的照片
这是一个幼稚的错误,但却给了我几个宝贵的教训:
- 低质量/不相关的数据弊大于利
- 我的团队的工作只能在被理解的情况下完成
现在不要担心,我们确实按时完成了,有一个模型和完整的报告!但是…只有在我考虑了这些缺陷之后,我的团队才能像一台运转良好的机器一样运转。因此,在这里,我们将探讨如何找到洞察力并从中受益,以及如何避免一直存在的缺陷和潜在的陷阱(每个人在某个时候都会遇到)。
强调理解数据如何运作的重要性很容易,但要发现它却很难。有了教程、kaggle 竞赛和简单的初学者练习,就很容易了……理解和翻译部分已经轻而易举地交给你了。只要拿出你的金叉(代号)和刀(合奏模型),开始切割(测试)和你能吃的 whala(高性能模型)!
然后你取得进展,开始一些真正的项目…哦,不。也许没有一个放之四海而皆准的策略,但是我们可以通过适当地设置自己,让这个过程变得更顺利,更少痛苦。
杨静在 Unsplash 上的照片
从哪里开始
只是酷……不,请等等!
代码很重要,但是我要告诉你一个小秘密——当你知道过程时,花费的时间会更少。Bbubbbut…如何在第一次开始之前了解流程?简单,解释任务目标。缺失的目标是你想从项目中得到的。任务目标包括模型和报告本身,但也包括您需要学习的内容、您将经历的阶段以及需要考虑的挑战。
我以为我的目标是尽我所能创造最好的模型来预测能源需求,哈哈哈。我完全错了!
我的目标不是预测能源需求…因为那几乎是不可能的。我真正想要的是识别和模拟短期内发生的能源需求趋势和季节模式,以及温度如何适应这个等式。它包括导入数据,研究哪些变量是有用的,创建图表以直观地显示数据的外观/工作方式,然后最终创建一个模型来具体测量温度和能源需求之间的关系。主要的困难在于了解能源时间序列是如何工作的,以及如何指导我的团队完成这个过程的每个阶段。还很啰嗦吗?最终目标可能是一个报告,展示了在我们得到一个模型之前一切是如何工作的,但是实际上,模型只是工作的 10%!
虽然很容易把它放在一边…说它是软的,不必要的计划,现在不太可能直接影响项目。事实上……是的,这是额外的工作,也很公平,如果你不是被迫像这样计划每件事的话。如果你有更好的选择,请告诉我。如果没有,试一试。它可能不会马上影响到你,但是它将有助于缓解大问题,并阐明所有事情是如何联系在一起的!
凯尔·格伦在 Unsplash 上的照片
找出下一步去哪里
但是我不知道如何做这些… 不要担心,随着时间的推移,你会明白的。请记住:
一旦开始,道路似乎就不那么崎岖不平了!
如果你不知道从哪里开始,找出你需要学习的内容,并找到学习的方法。简单的教程和视频是开始的好方法。然后,一旦你对事情应该是什么样子和该做什么有了一个模糊的想法,就开始吧。简单地跟着这条路走,看看它通向哪里!
对于数据科学项目,要知道实用的步骤和流程。我在我的机器学习领域指南文章中解释了这些,该文章详细介绍了该过程的每一步!如果你想了解更多,像动手机器学习和百页机器学习书这样的书是非常有用的。
为了在团队中更好地工作,确保你了解协作编码工具(所有解释在这里)和如何领导。《极端所有权》这本书是一个关于团队合作和领导力的惊人指南(不是专门针对数据科学的,但 Jocko Willink 的建议仍然适用)。
Josh Calabrese 在 Unsplash 上拍摄的照片
避免崩溃
一切都进行得如此顺利…直到我意识到我们仍然在项目中途清理数据。一切似乎都很好,进展似乎还不错,不完美…但很好。
即使你已经为自己的成功做好了准备,而且一切都进展顺利,事情也可能会变糟!但是……我很幸运,因为一位老师告诉我要定期做一件事:
做一个简单的进度日志,特别是评论你做了什么,结果如何,以及可以做些什么来改进。
Toa Heftiba 在 Unsplash 上拍摄的照片
它创造了奇迹!在了解我需要完成多少任务后,我没有感到压力,而是能够区分优先次序并执行,因为我知道哪里可能出错,并且我可以解释。我知道我的团队可能会分心,失去注意力,所以我确保抓住要点,强调我们试图完成的事情,而不是写下狭窄的任务。我知道很难调整自己的节奏,所以我数了数还剩多少周,确保每个人都明白。我知道编码对大多数人来说是特别具有挑战性和威胁性的,所以我做了一个简短的概述,关于它将涉及什么/它应该看起来像样本代码。简而言之,我说明了自己的弱点,并设法扭转了糟糕的局面。
这个过程每周只需要大约 5 分钟,极大地提高了进度。
你所要做的就是反思你的行为,考虑什么能进一步帮助你。
这个导致简单可行的步骤。
感谢阅读!
我希望你喜欢这本书,并且发现它很有帮助!请随时与任何人分享这可能会有所帮助。
我其他关于实用编码技巧、机器学习、起步项目和网页抓取的文章可能会比较有意思。
在推特上关注我的更新。
深刻的贷款违约分析
深入分析
可视化洞察并发现贷款违约的贷款信用风险模型中的驱动特征
(图片由作者提供)
L ending Club 是最大的在线贷款市场,为个人贷款、商业贷款和医疗程序融资提供便利。借款人可以通过快速的在线界面轻松获得低利率贷款。
与大多数其他贷款公司一样,向“高风险”申请人发放贷款是财务损失(称为信用损失)的最大来源。信用损失是指当借款人拒绝付款或带着所欠的钱逃跑时,贷款人所损失的金额。换句话说,违约的借款人给贷款人造成的损失最大。
因此,使用数据科学、探索性数据分析和来自 Lending Club 的公开数据,我们将探索和计算出贷款违约背后存在的驱动因素,即作为违约强指标的变量。此外,公司可以利用这些知识进行投资组合和风险评估。
关于 Lending Club 贷款数据集
该数据集包含通过2007–2011发放的所有贷款的完整贷款数据,包括当前贷款状态(当前、已核销、已完全支付)和最新支付信息。其他功能包括信用评分、财务查询次数和收款等。该文件是一个大约 39,000 个观察值和 111 个变量的矩阵。数据集中的一个单独文件中提供了一个数据字典。数据集可以在 Kaggle 上下载。
问题
- 我们正在处理哪组贷款数据?
- 我们有哪些类型的功能?
- 我们需要治疗缺失值吗?
- 贷款状态分布如何?
- 具有其他特征的贷款违约分布是怎样的?
- 我们可以为画出什么样的图来推断与贷款违约的关系?
- 主要描述贷款违约的驱动特征有哪些?
特征分布
- 贷款特征,如贷款金额、期限、目的,显示有关贷款的信息,帮助我们发现贷款违约。
- 人口统计变量,如年龄、就业状况、关系状况,这些信息显示了对我们无用的借款人概况。
- 行为变量,如下一个付款日期、EMI、拖欠显示提供贷款后更新的信息,在我们的情况下,这些信息并不有用,因为我们需要通过违约分析来决定是否批准贷款。
下面是我们将在本文中看到的内容的快速概述:
- 数据集概述(贷款分布)
- 数据清理(缺失值、标准化数据、异常值处理)
- 指标推导(宁滨)
- 单变量分析(分类/连续特征)
- 双变量分析(箱线图、散点图、小提琴图)
- 多变量分析(相关热图)
数据/库导入
*# import required libraries*
import numpy as np
print('numpy version:',np.__version__)
import pandas as pd
print('pandas version:',pd.__version__)
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
sns.set(style="whitegrid")
plt.style.use('ggplot')
plt.rcParams['figure.figsize'] = (12, 8)
pd.options.mode.chained_assignment = None
pd.options.display.float_format = '**{:.2f}**'.format
pd.set_option('display.max_columns', 200)
pd.set_option('display.width', 400)*# file path variable*
case_data = "/kaggle/input/lending-club-loan-dataset-2007-2011/loan.csv"
loan = pd.read_csv(case_data, low_memory=False)
数据集有 111 列和 39717 行
数据集概述
# plotting pie chart for different types of loan_status
chargedOffLoans = loan.loc[(loan["loan_status"] == "Charged Off")]
currentLoans = loan.loc[(loan["loan_status"] == "Current")]
fullyPaidLoans = loan.loc[(loan["loan_status"]== "Fully Paid")]data = [{"Charged Off": chargedOffLoans["funded_amnt_inv"].sum(), "Fully Paid":fullyPaidLoans["funded_amnt_inv"].sum(), "Current":currentLoans["funded_amnt_inv"].sum()}]investment_sum = pd.DataFrame(data)
chargedOffTotalSum = float(investment_sum["Charged Off"])
fullyPaidTotalSum = float(investment_sum["Fully Paid"])
currentTotalSum = float(investment_sum["Current"])
loan_status = [chargedOffTotalSum,fullyPaidTotalSum,currentTotalSum]
loan_status_labels = 'Charged Off','Fully Paid','Current'
plt.pie(loan_status,labels=loan_status_labels,autopct='**%1.1f%%**')
plt.title('Loan Status Aggregate Information')
plt.axis('equal')
plt.legend(loan_status,title="Loan Amount",loc="center left",bbox_to_anchor=(1, 0, 0.5, 1))
plt.show()
(图片由作者提供)
*# plotting pie chart for different types of purpose*
loans_purpose = loan.groupby(['purpose'])['funded_amnt_inv'].sum().reset_index()plt.figure(figsize=(14, 10))
plt.pie(loans_purpose["funded_amnt_inv"],labels=loans_purpose["purpose"],autopct='%1.1f%%')plt.title('Loan purpose Aggregate Information')
plt.axis('equal')
plt.legend(loan_status,title="Loan purpose",loc="center left",bbox_to_anchor=(1, 0, 0.5, 1))
plt.show()
(图片由作者提供)
数据清理
*# in dataset, we can see around half of the columns are null*
*# completely, hence remove all columns having no values*
loan = loan.dropna(axis=1, how="all")
print("Looking into remaining columns info:")
print(loan.info(max_cols=200))
我们剩下以下几列:
Looking into remaining columns info:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 39717 entries, 0 to 39716
Data columns (total 57 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 39717 non-null int64
1 member_id 39717 non-null int64
2 loan_amnt 39717 non-null int64
3 funded_amnt 39717 non-null int64
4 funded_amnt_inv 39717 non-null float64
5 term 39717 non-null object
6 int_rate 39717 non-null object
7 installment 39717 non-null float64
8 grade 39717 non-null object
9 sub_grade 39717 non-null object
10 emp_title 37258 non-null object
11 emp_length 38642 non-null object
12 home_ownership 39717 non-null object
13 annual_inc 39717 non-null float64
14 verification_status 39717 non-null object
15 issue_d 39717 non-null object
16 loan_status 39717 non-null object
17 pymnt_plan 39717 non-null object
18 url 39717 non-null object
19 desc 26777 non-null object
20 purpose 39717 non-null object
21 title 39706 non-null object
22 zip_code 39717 non-null object
23 addr_state 39717 non-null object
24 dti 39717 non-null float64
25 delinq_2yrs 39717 non-null int64
26 earliest_cr_line 39717 non-null object
27 inq_last_6mths 39717 non-null int64
28 mths_since_last_delinq 14035 non-null float64
29 mths_since_last_record 2786 non-null float64
30 open_acc 39717 non-null int64
31 pub_rec 39717 non-null int64
32 revol_bal 39717 non-null int64
33 revol_util 39667 non-null object
34 total_acc 39717 non-null int64
35 initial_list_status 39717 non-null object
36 out_prncp 39717 non-null float64
37 out_prncp_inv 39717 non-null float64
38 total_pymnt 39717 non-null float64
39 total_pymnt_inv 39717 non-null float64
40 total_rec_prncp 39717 non-null float64
41 total_rec_int 39717 non-null float64
42 total_rec_late_fee 39717 non-null float64
43 recoveries 39717 non-null float64
44 collection_recovery_fee 39717 non-null float64
45 last_pymnt_d 39646 non-null object
46 last_pymnt_amnt 39717 non-null float64
47 next_pymnt_d 1140 non-null object
48 last_credit_pull_d 39715 non-null object
49 collections_12_mths_ex_med 39661 non-null float64
50 policy_code 39717 non-null int64
51 application_type 39717 non-null object
52 acc_now_delinq 39717 non-null int64
53 chargeoff_within_12_mths 39661 non-null float64
54 delinq_amnt 39717 non-null int64
55 pub_rec_bankruptcies 39020 non-null float64
56 tax_liens 39678 non-null float64
dtypes: float64(20), int64(13), object(24)
memory usage: 17.3+ MB
现在,我们将删除所有人口统计和客户行为特征,这些特征对于信贷审批的违约分析毫无用处。
*# remove non-required columns*
*# id - not required*
*# member_id - not required*
*# acc_now_delinq - empty*
*# funded_amnt - not useful, funded_amnt_inv is useful which is funded to person*
*# emp_title - brand names not useful*
*# pymnt_plan - fixed value as n for all*
*# url - not useful*
*# desc - can be applied some NLP but not for EDA*
*# title - too many distinct values not useful*
*# zip_code - complete zip is not available*
*# delinq_2yrs - post approval feature*
*# mths_since_last_delinq - only half values are there, not much information*
*# mths_since_last_record - only 10% values are there*
*# revol_bal - post/behavioural feature*
*# initial_list_status - fixed value as f for all*
*# out_prncp - post approval feature*
*# out_prncp_inv - not useful as its for investors*
*# total_pymnt - post approval feature*
*# total_pymnt_inv - not useful as it is for investors*
*# total_rec_prncp - post approval feature*
*# total_rec_int - post approval feature*
*# total_rec_late_fee - post approval feature*
*# recoveries - post approval feature*
*# collection_recovery_fee - post approval feature*
*# last_pymnt_d - post approval feature*
*# last_credit_pull_d - irrelevant for approval*
*# last_pymnt_amnt - post feature*
*# next_pymnt_d - post feature*
*# collections_12_mths_ex_med - only 1 value*
*# policy_code - only 1 value*
*# acc_now_delinq - single valued*
*# chargeoff_within_12_mths - post feature*
*# delinq_amnt - single valued*
*# tax_liens - single valued*
*# application_type - single*
*# pub_rec_bankruptcies - single valued for more than 99%*
*# addr_state - may not depend on location as its in financial domain*
colsToDrop = ["id", "member_id", "funded_amnt", "emp_title", "pymnt_plan", "url", "desc", "title", "zip_code", "delinq_2yrs", "mths_since_last_delinq", "mths_since_last_record", "revol_bal", "initial_list_status", "out_prncp", "out_prncp_inv", "total_pymnt", "total_pymnt_inv", "total_rec_prncp", "total_rec_int", "total_rec_late_fee", "recoveries", "collection_recovery_fee", "last_pymnt_d", "last_pymnt_amnt", "next_pymnt_d", "last_credit_pull_d", "collections_12_mths_ex_med", "policy_code", "acc_now_delinq", "chargeoff_within_12_mths", "delinq_amnt", "tax_liens", "application_type", "pub_rec_bankruptcies", "addr_state"]
loan.drop(colsToDrop, axis=1, inplace=True)
print("Features we are left with",list(loan.columns))
我们只剩下 [‘loan_amnt ‘,’ funded_amnt_inv ‘,’ term ‘,’ int_rate ‘,’ partition ‘,’ grade ‘,’ sub_grade ‘,’ emp_length ‘,’ home_ownership ‘,’ annual_inc ‘,’ verification_status ‘,’ issue_d ‘,’ loan_status ‘,’ purpose ‘,’ earliest_cr_line ‘,’ inq_last_6mths ‘,’ open_acc ‘,’ pub_rec ‘,’ revol_util ‘,’ total_acc’]
现在,通过移除/输入来处理缺失值:
*# in 12 unique values we have 10+ years the most for emp_length,*
*# but it is highly dependent variable so we will not impute*
*# but remove the rows with null values which is around 2.5%*loan.dropna(axis=0, subset=["emp_length"], inplace=True)*# remove NA rows for revol_util as its dependent and is around 0.1%*loan.dropna(axis=0, subset=["revol_util"], inplace=True)
现在,我们将一些特征列标准化,以使数据兼容用于分析:
*# update int_rate, revol_util without % sign and as numeric type*loan["int_rate"] = pd.to_numeric(loan["int_rate"].apply(lambda x:x.split('%')[0]))loan["revol_util"] = pd.to_numeric(loan["revol_util"].apply(lambda x:x.split('%')[0]))*# remove text data from term feature and store as numerical*loan["term"] = pd.to_numeric(loan["term"].apply(lambda x:x.split()[0]))
删除贷款状态为“当前”的记录,因为贷款当前正在运行,我们无法从这些贷款中推断出任何有关违约的信息。
*# remove the rows with loan_status as "Current"*
loan = loan[loan["loan_status"].apply(lambda x:False if x == "Current" else True)] *# update loan_status as Fully Paid to 0 and Charged Off to 1*
loan["loan_status"] = loan["loan_status"].apply(lambda x: 0 if x == "Fully Paid" else 1)*# update emp_length feature with continuous values as int*
*# where (< 1 year) is assumed as 0 and 10+ years is assumed as 10 and rest are stored as their magnitude*loan["emp_length"] = pd.to_numeric(loan["emp_length"].apply(lambda x:0 if "<" in x else (x.split('+')[0] if "+" in x else x.split()[0])))*# look through the purpose value counts*
loan_purpose_values = loan["purpose"].value_counts()*100/loan.shape[0]
*# remove rows with less than 1% of value counts in paricular purpose*
loan_purpose_delete = loan_purpose_values[loan_purpose_values<1].index.values
loan = loan[[False if p in loan_purpose_delete else True for p in loan["purpose"]]]
异常值处理
查看每个特征的分位数值,我们将处理某些特征的异常值。
*# for annual_inc, the highest value is 6000000 where 75% quantile value is 83000, and is 100 times the mean
# we need to remomve outliers from annual_inc i.e. 99 to 100%*
annual_inc_q = loan["annual_inc"].quantile(0.99)
loan = loan[loan["annual_inc"] < annual_inc_q]*# for open_acc, the highest value is 44 where 75% quantile value is 12, and is 5 times the mean
# we need to remomve outliers from open_acc i.e. 99.9 to 100%*
open_acc_q = loan["open_acc"].quantile(0.999)
loan = loan[loan["open_acc"] < open_acc_q]*# for total_acc, the highest value is 90 where 75% quantile value is 29, and is 4 times the mean
# we need to remomve outliers from total_acc i.e. 98 to 100%*
total_acc_q = loan["total_acc"].quantile(0.98)
loan = loan[loan["total_acc"] < total_acc_q]*# for pub_rec, the highest value is 4 where 75% quantile value is 0, and is 4 times the mean
# we need to remomve outliers from pub_rec i.e. 99.5 to 100%*
pub_rec_q = loan["pub_rec"].quantile(0.995)
loan = loan[loan["pub_rec"] <= pub_rec_q]
这是我们的数据在清理和标准化功能后的样子:
(图片由作者提供)
度量派生
- 发行日期不是标准格式,我们也可以将日期分为月和年两栏,这样便于分析
- 日期时间中的 Year 要求 year 介于 00 到 99 之间,在某些情况下 year 是一位数,即 9 编写一个将转换此类日期的函数,以避免日期转换中出现异常。
def standerdisedate(date):
year = date.split("-")[0]
if(len(year) == 1):
date = "0"+date
return datefrom datetime import datetime
loan['issue_d'] = loan['issue_d'].apply(lambda x:standerdisedate(x))
loan['issue_d'] = loan['issue_d'].apply(lambda x: datetime.strptime(x, '%b-%y'))*# extracting month and year from issue_date*
loan['month'] = loan['issue_d'].apply(lambda x: x.month)
loan['year'] = loan['issue_d'].apply(lambda x: x.year)*# get year from issue_d and replace the same*
loan["earliest_cr_line"] = pd.to_numeric(loan["earliest_cr_line"].apply(lambda x:x.split('-')[1]))
宁滨连续特征:
*# create bins for loan_amnt range*
bins = [0, 5000, 10000, 15000, 20000, 25000, 36000]
bucket_l = ['0-5000', '5000-10000', '10000-15000', '15000-20000', '20000-25000','25000+']
loan['loan_amnt_range'] = pd.cut(loan['loan_amnt'], bins, labels=bucket_l)*# create bins for int_rate range*
bins = [0, 7.5, 10, 12.5, 15, 100]
bucket_l = ['0-7.5', '7.5-10', '10-12.5', '12.5-15', '15+']
loan['int_rate_range'] = pd.cut(loan['int_rate'], bins, labels=bucket_l)*# create bins for annual_inc range*
bins = [0, 25000, 50000, 75000, 100000, 1000000]
bucket_l = ['0-25000', '25000-50000', '50000-75000', '75000-100000', '100000+']
loan['annual_inc_range'] = pd.cut(loan['annual_inc'], bins, labels=bucket_l)*# create bins for installment range*
def installment(n):
if n <= 200:
return 'low'
elif n > 200 and n <=500:
return 'medium'
elif n > 500 and n <=800:
return 'high'
else:
return 'very high'
loan['installment'] = loan['installment'].apply(lambda x: installment(x))*# create bins for dti range*
bins = [-1, 5.00, 10.00, 15.00, 20.00, 25.00, 50.00]
bucket_l = ['0-5%', '5-10%', '10-15%', '15-20%', '20-25%', '25%+']
loan['dti_range'] = pd.cut(loan['dti'], bins, labels=bucket_l)
将创建以下箱:
(图片由作者提供)
可视化数据洞察力
*# check for amount of defaults in the data using countplot*
plt.figure(figsize=(14,5))
sns.countplot(y="loan_status", data=loan)
plt.show()
(图片由作者提供)
从上图我们可以看出,在总共 35152 条记录中,约有 16%即 5062 人是违约者。
单变量分析
*# function for plotting the count plot features wrt default ratio*
def plotUnivariateRatioBar(feature, data=loan, figsize=(10,5), rsorted=True):
plt.figure(figsize=figsize)
if rsorted:
feature_dimension = sorted(data[feature].unique())
else:
feature_dimension = data[feature].unique()
feature_values = []
for fd in feature_dimension:
feature_filter = data[data[feature]==fd]
feature_count = len(feature_filter[feature_filter["loan_status"]==1])
feature_values.append(feature_count*100/feature_filter["loan_status"].count())
plt.bar(feature_dimension, feature_values, color='orange', edgecolor='white')
plt.title("Loan Defaults wrt "+str(feature)+" feature - countplot")
plt.xlabel(feature, fontsize=16)
plt.ylabel("defaulter %", fontsize=16)
plt.show()# function to plot univariate with default status scale 0 - 1
def plotUnivariateBar(x, figsize=(10,5)):
plt.figure(figsize=figsize)
sns.barplot(x=x, y='loan_status', data=loan)
plt.title("Loan Defaults wrt "+str(x)+" feature - countplot")
plt.xlabel(x, fontsize=16)
plt.ylabel("defaulter ratio", fontsize=16)
plt.show()
a .分类特征
*# check for defaulters wrt term in the data using countplot*
plotUnivariateBar("term", figsize=(8,5))
(图片由作者提供)
从上面的“期限”图中,我们可以推断,违约率在期限内不断增加,因此,3600 万英镑贷款违约的可能性小于 6000 万英镑。
**is term benificial -> Yes**
*# check for defaulters wrt grade in the data using countplot*
plotUnivariateRatioBar("grade")
(图片由作者提供)
从上面的“等级”图中,我们可以推断出违约率随着等级的增加而增加,因此贷款违约的几率随着等级从 A 向 g 的增加而增加。
**is grade benificial -> Yes**
*# check for defaulters wrt sub_grade in the data using countplot*
plotUnivariateBar("sub_grade", figsize=(16,5))
(图片由作者提供)
从上面的“路基”图中,我们可以推断出违约率在路基中增加,因此贷款违约的机会随着路基从 A1 向 G5 移动而增加。
**is sub_grade benificial -> Yes**
*# check for defaulters wrt home_ownership in the data*
plotUnivariateRatioBar("home_ownership")
(图片由作者提供)
从上面的“房屋所有权”图中,我们可以推断这里的违约率是恒定的(其他人的违约率相当高,但我们不知道那里有什么,所以我们不会考虑它进行分析),因此违约率不取决于房屋所有权
**is home_ownership benificial -> No**
*# check for defaulters wrt verification_status in the data*
plotUnivariateRatioBar("verification_status")
(图片由作者提供)
从上面的“验证 _ 状态”图中,我们可以推断出违约率正在增加,并且未验证用户的违约率小于已验证用户的违约率,但是对分析没有用处。
**is verification_status benificial -> No**
*# check for defaulters wrt purpose in the data using countplot*
plotUnivariateBar("purpose", figsize=(16,6))
(图片由作者提供)
从上述“目的”图中,我们可以推断,除“小企业”外,所有目的类型的违约率几乎是恒定的,因此违约率将取决于贷款的目的
**is purpose benificial -> Yes**
*# check for defaulters wrt open_acc in the data using countplot*
plotUnivariateRatioBar("open_acc", figsize=(16,6))
(图片由作者提供)
从上面的“open_acc”图中,我们可以推断,对于功能 open_acc,违约率几乎是恒定的,因此违约率不依赖于 open_acc 功能
**is open_acc benificial -> No**
*# check for defaulters wrt pub_rec in the data using countplot*
plotUnivariateRatioBar("pub_rec")
(图片由作者提供)
从上面的“pub_rec”图中,我们可以推断出违约率几乎在增加,因为 0 的违约率较小,而值为 1 的 pub_rec 的违约率较大,但由于其他值与 0 相比非常小,因此我们不会考虑这一点
**is pub_rec benificial -> No**
b .连续特征
*# check for defaulters wrt emp_length in the data using countplot*
plotUnivariateBar("emp_length", figsize=(14,6))
(图片由作者提供)
从上面的“雇员长度”图中,我们可以推断出违约率在这里是常数,因此违约率不依赖于雇员长度
**is emp_length benificial -> No**
*# check for defaulters wrt month in the data using countplot*
plotUnivariateBar("month", figsize=(14,6))
(图片由作者提供)
从上面的“月”图中,我们可以推断出违约率在这里几乎是常数,没有用
**is month benificial -> No**
*# check for defaulters wrt year in the data using countplot*
plotUnivariateBar("year")
(图片由作者提供)
从上面的“年”图中,我们可以推断出违约率在这里几乎是常数,没有用
**is year benificial -> No**
*# check for defaulters wrt earliest_cr_line in the data*
plotUnivariateBar("earliest_cr_line", figsize=(16,10))
(图片由作者提供)
从上面的“earliest_cr_line”图中,我们可以推断,除了 65 岁左右的年份,所有目的类型的违约率几乎都是恒定的,因此违约率不依赖于人的 earliest_cr_line
**is earliest_cr_line benificial -> No**
*# check for defaulters wrt inq_last_6mths in the data*
plotUnivariateBar("inq_last_6mths")
(图片由作者提供)
从上面的“inq_last_6mths”图中,我们可以推断,违约率不会随着 inq_last_6mths 类型的增加而持续增加,因此没有用
**is inq_last_6mths benificial -> No**
*# check for defaulters wrt revol_util in the data using countplot*
plotUnivariateRatioBar("revol_util", figsize=(16,6))
(图片由作者提供)
从上述“革命”图中,我们可以推断,违约率是波动的,有些违约率为 100%,并且随着规模的增加而增加,因此违约率将取决于革命的特点
**is revol_util benificial -> Yes**
*# check for defaulters wrt total_acc in the data using countplot*
plotUnivariateRatioBar("total_acc", figsize=(14,6))
(图片由作者提供)
从上面的‘total_acc’图中,我们可以推断出,对于所有的 total_acc 值,违约率几乎是恒定的,因此违约率不依赖于 total _ ACC 特性
**is total_acc benificial -> No**
*# check for defaulters wrt loan_amnt_range in the data using countplot*
plotUnivariateBar("loan_amnt_range")
(图片由作者提供)
从上面的“贷款 _amnt_range”图中,我们可以推断出违约率正在增加贷款 _amnt_range 值,因此利率将取决于贷款 _amnt_range 特征
**is loan_amnt_range benificial -> Yes**
*# check for defaulters wrt int_rate_range in the data*
plotUnivariateBar("int_rate_range")
(图片由作者提供)
从上面的“int_rate_range”图中,我们可以推断出违约率随着 int_rate_range 值的增加而降低,因此违约率将取决于 int_rate_range 特性
**is int_rate_range benificial -> Yes**
*# check for defaulters wrt annual_inc_range in the data*
plotUnivariateBar("annual_inc_range")
(图片由作者提供)
从上述“年度收入范围”图中,我们可以推断违约率随着年度收入范围值的增加而降低,因此违约率将取决于年度收入范围特征
**is annual_inc_range benificial -> Yes**
*# check for defaulters wrt dti_range in the data using countplot*
plotUnivariateBar("dti_range", figsize=(16,5))
(图片由作者提供)
从上面的“dti_range”图中,我们可以推断违约率随着 dti_range 值的增加而增加,因此违约率将取决于 dti_range 特性
**is dti_range benificial -> Yes**
*# check for defaulters wrt installment range in the data*
plotUnivariateBar("installment", figsize=(8,5))
(图片由作者提供)
从上述“分期付款”图中,我们可以推断违约率随着分期付款值的增加而增加,因此违约率将取决于 dti_range 特征
**is installment benificial -> Yes**
因此,以下是我们从上述单变量分析中推导出的重要特征:
**term, grade, purpose, pub_rec, revol_util, funded_amnt_inv, int_rate, annual_inc, dti, installment**
双变量分析
*# function to plot scatter plot for two features*
def plotScatter(x, y):
plt.figure(figsize=(16,6))
sns.scatterplot(x=x, y=y, hue="loan_status", data=loan)
plt.title("Scatter plot between "+x+" and "+y)
plt.xlabel(x, fontsize=16)
plt.ylabel(y, fontsize=16)
plt.show()
def plotBivariateBar(x, hue, figsize=(16,6)):
plt.figure(figsize=figsize)
sns.barplot(x=x, y='loan_status', hue=hue, data=loan)
plt.title("Loan Default ratio wrt "+x+" feature for hue "+hue+" in the data using countplot")
plt.xlabel(x, fontsize=16)
plt.ylabel("defaulter ratio", fontsize=16)
plt.show()
用条形图和散点图在 y 轴上绘制关于贷款违约率的两种不同特征。
*# check for defaulters wrt annual_inc and purpose in the data using countplot*
plotBivariateBar("annual_inc_range", "purpose")
(图片由作者提供)
从上面的图中,我们可以推断出它没有显示任何相关性
**related - N**
*# check for defaulters wrt term and purpose in the data*
plotBivariateBar("term", "purpose")
(图片由作者提供)
正如我们在图上看到的直线,违约率随着每一个目的贷款期限的增加而增加
**related - Y**
*# check for defaulters wrt grade and purpose in the data*
plotBivariateBar("grade", "purpose")
(图片由作者提供)
正如我们在图上看到的直线,违约率随着各种用途的 wrt 等级而增加
**related - Y**
*# check for defaulters wrt loan_amnt_range and purpose in the data*
plotBivariateBar("loan_amnt_range", "purpose")
(图片由作者提供)
正如我们在图上看到的直线,违约率在每种用途下都增加
**related - Y**
*# check for defaulters wrt loan_amnt_range and term in the data*
plotBivariateBar("loan_amnt_range", "term")
(图片由作者提供)
正如我们在图上看到的直线一样,每一个期限的违约率都在增加
**related - Y**
*# check for defaulters wrt annual_inc_range and purpose in the data*
plotBivariateBar("annual_inc_range", "purpose")
(图片由作者提供)
正如我们在图上看到的直线,违约率在 wrt annual_inc_range 的各种用途下都会增加
**related - Y**
*# check for defaulters wrt annual_inc_range and purpose in the data*
plotBivariateBar("installment", "purpose")
(图片由作者提供)
正如我们在图上看到的直线一样,除了小企业之外,每个目的的 wrt 分期付款的违约率都在增加
**related - Y**
*# check for defaulters wrt loan_amnt_range in the data*
plotScatter("int_rate", "annual_inc")
(图片由作者提供)
正如我们在图上看到的直线,上述特征之间没有关系
**related - N**
*# plot scatter for funded_amnt_inv with dti*
plotScatter("funded_amnt_inv", "dti")
(图片由作者提供)
正如我们在图上看到的直线,上述特征之间没有关系
**related - N**
*# plot scatter for funded_amnt_inv with annual_inc*
plotScatter("annual_inc", "funded_amnt_inv")
(图片由作者提供)
正如我们在图上看到的斜率模式,上述特征之间存在正相关关系
**related - Y**
*# plot scatter for loan_amnt with int_rate*
plotScatter("loan_amnt", "int_rate")
(图片由作者提供)
正如我们在图上看到的直线模式,上述特征之间没有关系
**related - N**
*# plot scatter for int_rate with annual_inc*
plotScatter("int_rate", "annual_inc")
(图片由作者提供)
正如我们在图上看到的密度降低的负相关模式,上述特征之间存在某种关系
**related - Y**
*# plot scatter for earliest_cr_line with int_rate*
plotScatter("earliest_cr_line", "int_rate")
(图片由作者提供)
正如我们在图上看到的密度增加的正相关模式,上述特征之间存在相互关系
**related - Y**
*# plot scatter for annual_inc with emp_length*
plotScatter("annual_inc", "emp_length")
(图片由作者提供)
正如我们在图上看到的直线模式,上述特征之间没有关系
**related - N**
*# plot scatter for earliest_cr_line with dti*
plotScatter("earliest_cr_line", "dti")
(图片由作者提供)
用箱线图和小提琴图在 y 轴上绘制关于贷款违约率的两种不同特征。
*# function to plot boxplot for comparing two features*
def plotBox(x, y, hue="loan_status"):
plt.figure(figsize=(16,6))
sns.boxplot(x=x, y=y, data=loan, hue=hue, order=sorted(loan[x].unique()))
plt.title("Box plot between "+x+" and "+y+" for each "+hue)
plt.xlabel(x, fontsize=16)
plt.ylabel(y, fontsize=16)
plt.show()
plt.figure(figsize=(16,8))
sns.violinplot(x=x, y=y, data=loan, hue=hue, order=sorted(loan[x].unique()))
plt.title("Violin plot between "+x+" and "+y+" for each "+hue)
plt.xlabel(x, fontsize=16)
plt.ylabel(y, fontsize=16)
plt.show()*# plot box for term vs int_rate for each loan_status*
plotBox("term", "int_rate")
(图片由作者提供)
(图片由作者提供)
贷款期限越长,利率越高,违约几率也越大
*# plot box for loan_status vs int_rate for each purpose*
plotBox("loan_status", "int_rate", hue="purpose")
(图片由作者提供)
(图片由作者提供)
int_rate 相当高,其中贷款对于每个目的值都是默认的
*# plot box for purpose vs revo_util for each status*
plotBox("purpose", "revol_util")
(图片由作者提供)
(图片由作者提供)
在贷款违约的情况下,revol_util 更适用于各种用途价值,对于信用卡来说,revol _ util 相当高
*# plot box for grade vs int_rate for each loan_status*
plotBox("grade", "int_rate", "loan_status")
(图片由作者提供)
(图片由作者提供)
int_rate 随着每个年级而增加,并且每个年级的违约者的中位数接近 int_rate 的非违约者的 75%分位数
*# plot box for issue_d vs int_rate for each loan_status*
plotBox("month", "int_rate", "loan_status")
(图片由作者提供)
(图片由作者提供)
违约者的 int_rate 随着每个月而增加,其中每个月的违约者的中位数接近非违约者的 int_rate 的 75%分位数,但是每个月几乎是恒定的,没有用
因此,以下是我们从上述双变量分析中推导出的重要特征:
**term, grade, purpose, pub_rec, revol_util, funded_amnt_inv, int_rate, annual_inc, installment**
多元分析(相关性)
*# plot heat map to see correlation between features*
continuous_f = ["funded_amnt_inv", "annual_inc", "term", "int_rate", "loan_status", "revol_util", "pub_rec", "earliest_cr_line"]
loan_corr = loan[continuous_f].corr()
sns.heatmap(loan_corr,vmin=-1.0,vmax=1.0,annot=True, cmap="YlGnBu")
plt.title("Correlation Heatmap")
plt.show()
(图片由作者提供)
因此,来自上述多变量分析的重要相关特征是:
**term, grade, purpose, revol_util, int_rate, installment, annual_inc, funded_amnt_inv**
最终调查结果
在分析了数据集中所有可用的相关特征后,我们已经结束,为 Lending Club 贷款违约分析推导出主要的驱动特征:
贷款违约分析的最佳驱动特征是: 期限、等级、用途、周转、利率、分期、年度公司、基金 _ 资产 _ 投资
关于分类器组合的见解
随着分类算法库的急剧增加,使用几个分类器,然后组合它们的决策以获得准确性并避免选择正确的一个的负担变得越来越有吸引力。注意,分类器的组合本身仍然是一个分类器,没有免费的午餐定理也适用于它。普遍最优的分类器是没有希望的,但是我们可以实现其他形式的鲁棒性,我们将在后面讨论。最简单的融合方法之一是对每个分类器提供的预测类别集执行多数投票。
在这篇文章中,我提出了一些在组合量词时要记住的一般性原则。具体来说,我研究了关于组合信息的性质、组合规则、单个分类器的类型和组合结构的融合方案的分类。然后,我们讨论了多样性在多分类器系统中的重要性。
https://pix abay . com/插图/交通信号灯-交通信号灯-相位-2147790/
1)分类器组合的说明
四个问题有助于确定我们解决组合问题的角度:
Q1:输出什么性质的信息要组合?
Q2:什么类型的分类器要组合起来
Q3:用什么组合规则来组合决策?
Q4:这个组合的结构是怎样的?
- 分类器输出性质的相关分类( Q1 )在文献中给出:基本输出(分类器的输出是单个标签)、分级输出(分类器的输出是从最可能到最不可能分级的标签列表)和评分输出(分类器给每个类别标签分配置信度)。
- 基于来自相同分类算法的分类器的融合方法被称为同质组合方法(例如,随机森林使用决策树)或集成方法。这一类别中的标准方法是由 Breiman 首次引入并随后开发的 bagging(引导聚合)。另一种非常流行的集成方法是 boosting,其最广泛使用的实现是 AdaBoost。在过去的二十年里,机器学习社区对打包和提升进行了很好的探索和研究。最近,一种新的升压设计利用了线性规划支持向量机(LPSVM)。如果融合面板包含不同的分类器,那么我们讨论异构组合方法,即组合神经网络和决策树。这两种类型的面板(同质和异质)是源于( Q2 )的多分类器系统的主要类别。
- 更不用说组合分类器的类型,组合方法也根据允许决策融合的规则来分类。两个主要类别是确定性方法和概率性方法,这是对( Q3 )的两种可能的回答。通过概率方法,我们意味着分类函数依赖于类别概率分布的最大化。分类器组合也可以在其他不确定性框架内执行,这些框架可以是诸如模糊逻辑之类的概率论的替代方案,或者与诸如信任函数框架之类的概率论相关。在 Dempster 的原始论文中,通过用多值映射插入概率测度来获得信任函数。其他作者主张该理论是独立的,不需要建立在概率对象上。
- 关于组合架构( Q4 ),我们指的是分类器如何组织成一个网络并连接到融合过程。有三种主要的拓扑类型:并行、顺序或混合组合。在并行融合中,基本分类器独立工作,它们可以用不同特征空间中的输入进行训练,并且特征向量可以或可以不从相同的原始训练样本中导出。然而,给定分类器的输出不能作为另一个分类器的输入。在顺序(串行)融合中,基本分类器以顺序方式堆叠,一个分类器的决策取决于先前的决策。一些类别标签在每个分类步骤中被去除,直到剩下一个类别。混合分层融合是并行和顺序架构的混合。
该图与( Q4 )相关,展示了三种不同的分类器组合方案。这个数字摘自我自己的博士报告。
作者图片
2)多样性问题
设计多分类器系统(MCS)需要在选择单个分类器时特别小心,以便实现更高的分类精度或获得更鲁棒的算法。例如,在同一数据集上训练的一组线性分类器肯定会收敛到非常接近的分离超平面,并且组合非常相似的决策规则注定会获得平均结果。因此,多样性是设计有效的多分类器系统的指导原则。
应对措施需要多样化
多样性和独立性的概念是密切相关的,但两者之间的分界线仍然不清楚。然而,我们可能不期望高度依赖的分类器池输出非常不同的响应,因为依赖的分类器肯定会产生相关的响应。在这一节中,我们讨论测量多样性的方法以及在分类器响应中诱导多样性的方法。
Brow 等人主张可以通过两种方式在分类器集成中引入多样性。第一种方式是显式的,它基于对分类器池的多样性度量的优化。第二种是隐式的,它包括使用不同的机制生成分类器,并希望在它们的响应中具有显著的独立性。这通常通过在不同的学习数据样本或特征空间的不同区域上训练它们来完成。
隐式分集诱导方案
第二类多样性归纳涉及基于输入数据、输出决策或分类器类型的操纵的一些隐含方法。
在他们的调查中,沃兹尼亚克等人为数据操作制定了以下分类法:
分割数据点:这允许在不同的训练集上训练单个分类器。尽管学习样本在某种程度上是相关的,但我们使用不同的训练数据在分类器响应中保持一定程度的多样性,这些数据可能是通过对学习样本进行拆分或随机采样(如 Bagging)而获得的。
选择特征子集:同样,基本分类器因此在不同的数据集上被训练,在某种意义上,它们可以访问每个训练示例的不同信息。因此,决策函数有不同的领域,如果特征是弱相关的,那么我们实现多样性。在这种情况下,一种流行的策略是随机选择那些被选择来训练每个基本分类器的特征的子集。这种策略被称为随机子空间方法。另一种策略包括为特征空间中的每个分区选择具有最佳性能的分类器。
- 修改分类器输出 : MCS 可以通过要求每个分类器只区分类的子集来享受另一种形式的多样性。为了恢复整个类别集的决策粒度,需要设计特定的信息融合策略。这一类别中一个著名的方法是一对一分类器,在这种情况下,多类分类问题被分解为二类分类问题。分类器将在给定标签和剩余标签之间进行选择。纠错输出码方法也属于这一类方法。在这种设置中,每个标签都有一个码字(二进制值序列),然后构建二进制分类器,为每个测试样本产生一个码字。所选择的标签是与测试样本码字具有最接近汉明距离的标签。
结论
在这个故事中,我谈了一些关于分类器组合的见解,以及应该如何看待这个问题。
在我未来的故事中,我将讲述经典的分类器组合方法,如投票、Borda 计数。我还将讨论在不确定性框架内组合分类器决策,如概率和可能性理论。
使用新标签对新冠肺炎疫情建模的见解
爵士和 SEIR 模型中缺少了什么?
流行病学中的建模是使用给所有人分配标签的分室模型来执行的。这些标签可以被认为是状态机中的状态,并且整个群体被分配不同的类别。用于模拟新冠肺炎的一个普遍的房室模型是 SIR 模型(易感-感染-康复)。SIR 模型使用一组方程(ODEs)来计算在给定时间易感、感染和康复的人。SIR 模型是有界的,因为它认为所有感染的人都会立即被感染(或出现症状)。这与冠状病毒疾病的情况不同,在冠状病毒疾病中,不同的个体在不同的时间开始出现症状。SEIR(易感-暴露-感染-康复)模型是 SIR 的变体,也不能用于准确模拟新冠肺炎,因为它是基于每个感染个体都被报告的假设。有多种原因可以解释为什么会有感染者没有被报告,比如缺乏检测设备,不知道等等。
本文将解释 SIRU(易感-感染-报告-未报告)模型,该模型通过在新冠肺炎疫情中的应用,克服了 SIR 和 SEIR 模型的缺点。此外,本文重点分析了公共卫生组织的干预措施,如隔离和封锁,以及在不同国家的积极测试的效果。我的文章是受[1]和[2]中的工作的启发,其中 SIRU 模型已经被提出用于流行病建模以及逼近其参数的方法。
SIRU(易感-感染-报告-未报告)
它是流行病学中使用的分室模型,专门用于将未报告的感染个体病例纳入建模,从而捕捉公共测试的影响。社会距离的影响也可以被这个模型所容纳。
图 1: SIRU 流程图
该模型由以下常微分方程系统组成:
参数
- t ≥ t₀ 为天数, t₀ 为疫情开始, t=0 对应 2019 年 12 月 31 日
- τ :传染率
- S(t) = S :在时间 t 易受感染的个体数量
- I(t) = I :时间 t 无症状感染个体数
- R(t) = R :在 t 时间报告的有症状的感染个体数
- U(t) = U :在时间 t 未报告的有症状的感染个体数
- 无症状个体变成有症状个体的速度
- ƞ: 已报告/未报告症状的个体恢复的速度
假设
- 与个体的一生相比,感染的过程是短暂的,并且疾病不是致命的,因此出生和死亡可以被忽略。
- 人口保持不变,没有移民。
- 所报告的有症状的个体被立即报告和隔离,并且不会引起进一步的感染。
- 所有感染都是从传染性无症状个体( I )或未报告的传染性个体( U )获得的。
- 从感染中康复的个体获得了对病原体的完全免疫力。
- 无症状感染个体( I )在平均 1/ ѵ 天的时间内(潜伏期)具有传染性。
- 已报告的症状( R )和未报告的症状( U )个体在平均 1/ ƞ 天的时间内(恢复期)具有传染性。
- f :无症状感染个体( I )成为报告症状个体( R )的比例。
- (1 — f) :无症状感染个体( I )变成未报告的有症状个体( U )的比例。
- ν₁ = ѵ * f :无症状传染个体( I )成为报告症状个体( R )的比率。
- ν₂ = ѵ * (1 — f) :无症状传染个体( I )变成未报告症状个体( U )的比率。
初始条件
估计参数
我们利用确诊病例数据来确定参数 τ,ν,ν₁,ν₂,η 的值,以及初始条件s(t₀】**i(t₀】**u(t₀)。
我们假设在时间 t 、 CR(t) 累计报告的有症状的感染病例,由到时间 t 为止的有症状的感染病例总数的恒定部分组成。由于 ν₁ 是报告的有症状的感染个体的去除率, CR(t) 表示为:
假设在疫情初期,累计报告的有症状传染病病例呈指数增长
通过将该曲线与报道的病例数据进行拟合,我们得到了χ₁*、χ₂* 和χ₃的值。
实验
*我们使用 Kaggle 上提供的数据集(小说电晕病毒 2019 数据集)。以西班牙为例,我们设定 S₀ 的数值为西班牙总人口,s₀= 4690 万。然后我们根据最初的发现确定 ν,η,f , ѵ=1/7 , η=1/7 和 *f = 0.8。图 2 显示了前 45 天冠状病毒病例的拟合曲线。
图 2:显示西班牙冠状病毒病例前 45 天拟合曲线的图
拟合曲线为我们提供了χ1、χ2 和-χ3,分别为 0.01920、0.29338 和-36.47589。这条曲线帮助我们:
- 获得疫情开始的时间,t₀
- 获得 I₀无症状感染者的初始人数
- 获得 U₀未报告症状个体的初始数量
- 获得传输速率τ
详细推导请参考最后的附录。
使用上述计算值,从方程(3)中绘制 CR(t) ,从方程(1c)中绘制 R(t) ,从方程(1d)中绘制 U(t) ,如图 3 所示(左图)。
由于传播率( τ 因封锁而降低,社会距离和报告的感染个体比例( f 随着攻击性检测而增加,将参数 τ 和 f 视为时间变量系数 τ(t) 和 f(t) 在解释公共卫生措施的效果时非常有用。
假设 τ 在 t=N₁ 被国家严格封锁时变为 0。
此外,假设在 t= N₂ 的状态下采用积极测试后,f 增加到 0.9。
在西班牙的情况下,我们采用 N₁=N₂= 76 天(封锁从 3 月 14 日开始,因此假设传输速率从 3 月 16 日开始变为 0)。在图-3(右)中绘制来自(3)的 CR(t) 、来自(1c)的 R(t) 和来自(1d)的 U(t) 。
图 3:西班牙实验
西班牙的公共卫生措施从 3 月 14 日开始在全国范围内实行封锁,但对控制疫情没有太大效果。转折点,即 R(t)达到最大值的时间,还没有从 66 天下来。该国报告了世界上第二高的病例数。[3]
现在,我们来考虑对比一下各个国家的场景。
以下实验的假设:在宣布封锁两天后,传播率变为 0。随着测试增加的 f 的值也假定在锁定两天后从 0.8 变为 0.9。在南韩,政府宣布了“红色级别”警报,但没有封锁,假设在“红色级别”警报宣布两天后,传输率和 f 发生类似变化。
图 4:韩国实验
韩国遏制病毒传播的措施包括积极的检测策略和严重依赖移动应用程序,这些应用程序通过帮助人们避免接触阳性病例来帮助减少感染的传播。在 2015 年面临类似危机(中东呼吸综合征)后,在政府于 2 月 23 日宣布“红色级别”警报后,人们在采取预防措施方面保持警惕。这帮助韩国将转折点提前了 14 天。
图 5:德国实验
德国从 3 月 22 日开始的大规模测试和全国宵禁虽然降低了疫情的规模,但并没有带来其转折点的改变。
图 6:意大利实验
意大利政府采取的公共卫生措施将转折点提前了 20 天,并降低了疫情规模。
图 7:湖北实验
由于有效的公共卫生措施,如从 1 月 23 日起严格封锁和增加检测,转折点已从 138 天下降到 28 天,新冠肺炎疫情在中国湖北省的规模大幅缩小。
结论
通过 SIRU 模型,我试图比较公共卫生措施在世界不同地区遏制冠状病毒传播的效果。此外,我还通过当局积极的病毒检测纳入了报告病例的增加,从而发现了未报告的病例。这种措施的效果并没有反映在其他车厢模型中,如 SIR 及其不同的变体。
参考文献
[1] Z. Liu,P. Magal,O. Seydi,G. Webb,了解中国武汉新冠肺炎疫情暴发中未报告的病例,以及重大公共卫生干预的重要性。生物 2020, 9 ,50。
*[2] R.M. Cotta,C.P. Naveira-Cotta,P. Magal,**模拟巴西的新冠肺炎流行病:参数识别和公共卫生措施的影响,*medRxiv 2020 . 03 . 31 . 30303030331
[3]世界计量仪,https://www.worldometers.info/coronavirus/
附录
在我的 Github 上可以找到本分析中使用的代码。
充分解释了统计显著性——为什么不应高估 p 值
传统统计学中最著名也最令人困惑的概念指南:零假设显著性检验(NHST)。
马克斯·麦金农在 Unsplash 上的照片
你有没有听过有人说一项研究揭示了*【重大成果】*?这到底是什么意思?让我给你介绍一个科学界的实践,这是一个被深入争论并且仍然被用来回答研究问题的实践。简单地说,大致是这样的:如果你运行一个模型,而你的计算机给出的 p 值小于 0.05,那么你的结果已经达到了具有统计学意义的圣杯,因此更有可能被发表。另一方面,如果 p 大于 0.05,你的观察结果似乎不会偏离已知的结果。然而,这可能是一种从数据中得出结论的危险方式,并且会引起几乎机械地使用这一工具的诱惑。这种做法受到了热烈的讨论,美国统计协会(ASA)发表了一份关于 p 值的声明,以阐明这一问题(瓦瑟斯坦&耶戈,2016)。一些专家甚至认为 p 值是大多数研究结果错误的原因(Ioannidis,2018),并认为其滥用导致了研究中的可重复性危机(彭,2015)。围绕这一概念有一个完整的误解指南,因为 p 值远非直观、简单明了(Greenland 等人,2016 年)-对于业余爱好者和研究人员来说都是如此。因此,掌握基本概念是值得的。因此,我想给你一个温和而基本的介绍,介绍统计学中最著名但也最令人困惑的概念:零假设显著性检验。
为什么这很重要?
如今,我们身边有大量随时可用的数据。《福布斯》杂志在 2018 年的一篇文章中提出,仅互联网就创造了 2.5 万亿(!!!)仅链接一项,过去两年领先的每日字节数就占了世界数据的 90%。这句话绝对值得再读一遍。你可能也已经意识到,数据科学家的数量正在增长,尽管他们分析这些数据的努力无法弥补这些巨大的数量。此外,科学界有一个悠久的传统,即使用一种叫做零假设显著性检验(NHST)的方法来回答他们的研究问题。因此,鉴于我们有机会分析数据来满足我们的好奇心并为我们的决策提供信息,我们应该知道使用关键的统计概念来得出不太不可靠的结论。看下面的问题:
- 特朗普总统任期如何改变了国际关系?
- 间歇性禁食有长期的健康益处吗?
- 这种新药 X 如何改善疾病 Y 的症状?
- 社交媒体是增强了还是降低了青少年对连通性的感知?
- 人工智能如何帮助残障人士?
- 学生在同性教室里学得更好吗?
- 随着年龄的增长,我们能控制记忆力的衰退吗?
这些只是我们问自己的问题的一小部分,因为一个答案可能会影响我们塑造生活、教育孩子或开发新技术的方式——正如我所说的,这只是其中的几个例子。所有这些都只能用数据做出超出你自己的鼻子的推论来可靠地回答。作为一名心理学毕业生,我了解到,大多数人讨厌一切与统计数字接近的东西,一提到数学公式,就会让人产生相当大的焦虑感。为了让你放心,我不想在这里包括任何数学。我保证,最终一切都是值得的。
因此,我试图解释统计推断是什么,以及为什么它不那么简单——为此,我想邀请你来一次太空之旅。你想加入吗?
一个假想的案例研究——研究太空中的外星生命
想象一下,你是一个研究小组的成员,在植物 X 上发现了非人类的智慧,似乎对人类没有危险。你渴望更多地了解这一物种,于是指示你的同事收集关于它们的一些主要特征的数据。除了细胞样本和行为观察,你还会派一群太空机器人去收集他们的身高数据,因为他们的身高和人类差不多。它们光滑的皮肤纹理让你在实验室里给它们取名为glibglobs——就像你最喜欢的卡通系列里的一些生物叫瑞克和莫蒂一样。现在你的同事已经注意到 glibglobs 有不同的性别——其中一个比另一个高一点。由于地球上女性的身高通常比男性低,你开始想知道:这种性别差异可能是我们宇宙中的一种普遍模式吗?好吧——这是一个大问题,所以让我们把它变得更具体些:油腔滑调的人比他们的小吗?或者这只是你的一个同事的随机观察?
当你收集了每种性别的 100 个身高样本后,你开始直观地研究这一现象,并问自己,油嘴滑舌和珠珠之间是否真的有根本的区别。看着这些图,你可以看到 globs 平均比 glibs 高,但是也有很多变化。在某些情况下,glibglob 甚至比 glob 还高,所以如果你有资源来测量整个 x 星球上的每一个 glibglob,性别之间甚至可能没有差异。你如何判断你的数据假设甚至根本没有身高差异的可能性有多大?
glibglob 身高数据的密度图(用 R 模拟),每种性别都有颜色(红色= glibs,蓝色= globs)
在你检查了数据是否适合你想要用来回答这个问题的测试之后,你运行一个计算机程序来比较两性的平均值。有两种可能的情况:
1.真正的身高差异在人群中等于 0。
2.真正的身高差异在人群中不等于 0。
你可以把第一个假设(称为“零假设”)想象成一种在显著性检验中的默认假设——这可能是乍一看最令人困惑的事情,因为你实际上对第二个假设感兴趣。现在想象你的计算机程序的一部分是一个重要的陪练,这表明没有区别。尽管这很合理,但它表明机会是独自运作的。尽管如此,你仍然假设可能有一些不同的事情正在发生,用一些真实的 glibglob 数据来支持,并提出你对此观点的替代方案。来辩论吧!为了更接近答案,计算机为你进行了一些计算。它现在“假装”一遍又一遍地运行同一个实验,从而产生了许许多多虚构的油嘴滑舌的数据的模拟样本。这些假样本代表了如果 glibs 和 globs 实际上具有相同的高度,允许一些随机变化,那么高度差异会是什么样子。现在,计算机为 a)您的观察样本数据以及 b)每个模拟样本(假数据)生成一个汇总统计数据(例如,t-统计数据)。
经验表明,只要我们有很多观测值,自然界中的很多现象都近似成一个钟形分布,叫做正态分布。这也适用于理论上可能的 glibglob 身高差异的假数据:如果你从假数据中随机抽取一个样本,你将更有可能观察到零附近的身高差异,允许一点随机变化。另一方面,它不太可能观察到偶然发生的极端差异。仍然不确定是否存在身高差异的假设,您的计算机最终会将观察到的汇总统计数据与之前生成的假样本汇总统计数据进行比较,并告诉您您的数据在完全随机的假样本分布中的位置。给你一个 p 值< 0.01,计算机必须承认你的样本使他的默认状态(“glibglob 身高没有差别!)看起来有点不寻常。为什么?因为在假设机会独自运行时,似乎不可能观察到这种甚至更极端的数据。
p 值估计观察到这种或更极端数据的概率,假设实际上在自然界中没有任何影响——假设您的模型符合数据,并且您坚持自己的初衷。
那么,这个 p 值能告诉我什么呢?什么不是?
恭喜你走到这一步。看看那个冗长的定义。p 值现在能回答你原来的问题吗?
- 鉴于你观察到的这些数据,你能否告诉你的同事,glibglobs 之间很可能存在真正的身高差异?
没有。很困惑,对吧?虽然这实际上是我们感兴趣的问题,但这个问题只能使用贝叶斯统计来回答,贝叶斯统计包含了一种完全不同的思维方式和数学方法(Dienes & Mclatchie,2018;Kruschke & Liddell,2018a,2018bVandekerckhove、Rouder 和 Kruschke,2018 年)。如果使用传统显著性检验的人声称他们的假设是真的,因为零假设被拒绝,这应该给你一些危险信号。就其本身而言,一个小的 p 值确实表明,就目前而言,这些数据似乎与实际上没有任何影响的情景不相容。但是它不能告诉你你提出的替代方案(如*)是否存在性别相关的 glibglob 身高差异大于零。")很可能是真的,因为它没有结合任何先前的知识(例如,首先这种替代的可能性有多大?)—这可能是由我们最新的 glibglob 数据更新的备选方案的后验概率*,但这超出了当前文章的范围。
2.你能告诉你的同事,考虑到 glibglobs 中没有真正的身高差异的说法,这些数据似乎有点有趣吗?
是的,你可以。如果您已经检查了模型所需的前提条件,并且在实验过程中严格保持您的采样意图不变(例如,不管实验结果如何,在收集到预定义的样本量后停止测量),这种高度现象可能值得进一步研究。鉴于之前没有人测量过这些生物,因此你的实验具有探索性,这一结果为正在进行的该主题的研究提供了初步的起点。
3.你能告诉你的同事这些结果有实际意义吗?
没有。你不知道 glibglobs 之间的身高差异是否对他们在 X 行星上的生活有任何作用,甚至不能仅仅根据 p 值来判断这种差异是否和在人类中观察到的一样大。同样,你也不知道你是否问对了问题。也许 glibglobs 有一些你目前还没有考虑到的更有趣的特性?
现在你可能会感到有点失望。你已经走了这么长的路来到行星 X,测量了一群 glibglobs,但对它们仍然知之甚少——这似乎只是各种研究团队近距离观察这种外来物种的更漫长旅程的开始。知道你是研究 glibglobs 的第一个研究团队的一部分,你仍然在黑暗中敲击,即使你有一个指向特定方向的微小信号。
好吧——这个故事可能看起来有点牵强,过于简单。尽管如此,它还是以简明易懂的方式阐明了对待统计重要性的传统方法。如果你还在挣扎,不要担心:即使是科学家或健康专家通常也很难解释 p 值(Gigerenzer,2004;吉杰伦泽、盖斯迈尔、库尔茨-米尔克、施瓦茨和沃洛欣,2007 年;Gigerenzer 和 Marewski,2015 年)。所以,如果你还停留在你的头脑中,这并不奇怪。
乔尔·菲利普在 Unsplash 上的照片
那又怎样?
基本上,我们可以告别快速、轻松、精确地回答自然问题的想法。因此,要做到以下几点可能需要很大的毅力和忍耐力:a)接受这个事实;b)能够忍受自己的好奇心;c)忘记拥有一个适用于所有问题的神奇通用统计工具的梦想。为了对复杂现象做出有意义的结论,每次我们解决一个新问题时,我们需要有目的地从整个统计工具箱中挑选。分析师需要接受大量的培训,不仅要能够进行分析,还要在第一时间提出正确的问题,选择合适的方法进行测试,并最终解释研究结果。当涉及到人类行为时,应该变得更加明显的是,要对其进行可靠的测量,并对多种个体的总和做出一般性的推断,需要花费大量的时间。这就是为什么专家建议总是明确传达伴随研究发现的不确定性,提供关于导致结果的每一个步骤的详细文件,并与研究界共享数据。这使得科学推理更具可追溯性,证明了一种效应是否适用于不同的实验室,并为未来的研究人员共同回答关键问题铺平了道路。通过整合与感兴趣的现象有关的证据,我们能够描绘出一幅更大的图景,可能更精确地代表其本质(Hunter & Schmidt,2004;温伯格,2001)。
p 值被批评为将研究结果分为重要和不重要,因此可悲且错误地被认为不值得在许多研究期刊上发表。因为对于被认为具有统计显著性的结果,p 值有明确的临界值(通常为 p < .05 or p < .01), it supports a black-or-white style of thinking. Moreover, significance testing is only the end result of a long chain of other decisions the researcher makes beforehand (e.g. the research design, sampling method, model selection etc.) which determine the quality of the research but this simply cannot get expressed into a single value. However, the p-value taken by itself is a useful tool to indicate non-random patterns in the data and — if used thoughtfully — allows statistical inference to become fast and scalable.
I would never claim that science is nonsense because of this practice — the p-value just needs to be used and interpreted as one of many tools and not put as a mindless decision-making cut-off. This is exactly what the inventor of p-value, Sir Ronald Fisher, aimed for — it should be taken as a hint that indicates whether your observations are worth a closer look. Nevertheless, the p-value is not a fool-proof concept, seems to be quite a bit counterintuitive and therefore does require in-depth training of the analyst to interpret the results with the right amount of scepticism. Fisher (1956) even writes: ),没有一个科学工作者每年都有固定的显著性水平,在任何情况下,他都拒绝假设;他更愿意根据他的证据和想法来考虑每一个具体的案例。'【T1]因此,这不是 p 值故障,因为它只是做了它应该做的事情。我们只是不应该对它期望过高,也不应该屈服于关闭我们思维的诱惑。
参考文献
[1] R. L. Wasserstein & N. A .耶戈,美国儿科学会关于 p 值的声明:背景、过程和目的 (2016),美国统计学家, 70 (2),129–133。
[2] J. P. A .约安尼迪斯(J. P. A. Ioannidis),为什么大多数发表的研究结果是假的 (2018),变好:生物医学科学中的研究诚信, 2 (8),2–8。
[3] R .彭,科学中的再现性危机:一次统计学反击 (2015),显著性, 12 (3),30–32。
[4] S. Greenland,S. J. Senn,K. J. Rothman,J. B. Carlin,C. Poole,S. N. Goodman & D. G. Altman,统计检验,P 值,置信区间和功效:误解指南 (2016),《欧洲流行病学杂志》, 31 (4),337–350。
[5] Z. Dienes & N. Mclatchie,比显著性检验更喜欢贝叶斯分析的四个理由 (2018),心理经济学通报和评论, 25 (1),207–218。
[6] J. K. Kruschke & T. M. Liddell,新人贝叶斯数据分析 (2018a),心理计量学通报与评论, 25 (1),155–177。
[7] J. K. Kruschke & T. M. Liddell,贝叶斯新统计:从贝叶斯角度进行假设检验、估计、元分析和功效分析 (2018b),心理经济学通报和评论, 25 (1),178–206。
[8] J. Vandekerckhove,J. N. Rouder & J. K. Kruschke,社论:推进心理科学的贝叶斯方法 (2018),心理计量学通报与评论, 25 (1),1–4。
[9] G .吉杰伦泽,无脑统计学 (2004),社会经济学杂志, 33 (5),587–606。
[10] G .吉杰伦泽、w .盖斯迈尔、e .库尔茨-米尔克、L. M .施瓦茨和 s .沃洛申,帮助医生和病人理解健康统计 (2007),公众利益中的心理科学,补编, 8 (2),53–96。
[11] G. Gigerenzer,代理科学:科学推理的普遍方法的偶像 (2015),管理杂志, 41 (2),421–440。
[12] J. E. Hunter & F. L. Schmidt,荟萃分析方法:纠正研究结果中的错误和偏差 (2004),Sage。
[13] C. R. Weinberg,是时候恢复 P 值了 (2001),流行病学,12(3),288–290。
[14] R. A .费希尔,《统计方法与科学推断》 (1956),爱丁堡:奥利弗和博伊德。
鼓励女性参与数据科学或技术领域。
数据驱动的职位是另一个技术领域,所以我不认为我们需要为它强制实施更高的女性“配额”或“斗争”。或许,“获得一技之长,技能提升,在赛场上贡献出技术**,而感到荣幸”。**
技术领域的世界为男人和女人提供了各种各样的可能性。数据科学和分析领域在过去十年中经历了巨大的发展。研究表明,尽管数据科学在今天和不久的将来都是一个令人兴奋的职业方向,但女性在该领域的代表性仍然严重不足。数据驱动领域的男女差距仍然惊人。各种因素,如组织文化、信任程度、缺乏兴趣和隐含的偏见都促成了这一点。在过去二十年中,技术和数据科学领域的性别差距急剧扩大,引起了全球对信息和技术行业开放程度的关注。然而,《O ’ Reilly ’ s Women in Data》(https://www . oreilly . com/library/view/Women-in-Data/9781492048237/)这本书采访了当今计算和技术科学领域最具影响力的女性,该书表示,随着意识的提高,越来越多的女性被带入该领域。
数据驱动的工作领域继续呈指数级增长,各种规模的公司都需要能够解释和处理数据、了解相关技术能力并有创新和研究能力的人。2017 年(https://www . kdnugges . com/2017/01/glass door-data-scientist-best-job-America . html),数据科学家成为美国顶尖的工作,然而,招聘有价值的申请人对组织来说仍然很困难。数据科学的职位包括计算机专业知识、算法、统计以及更多需要花费大量时间才能获得的技能。数据科学家中,70%是男性。尽管如此,随着该行业合格申请人的短缺,这对女性来说是一个探索、提高技能和变得有竞争力的绝佳机会。正如在“编码的女孩们将如何改变世界”(https://www . Inc . com/James-Kerr/How-the-Girls-Who-Code-movement-can-Change-the-World . html)活动中提到的那样,美国劳工部估计,到 2020 年将有 140 万个计算机专家职位可供选择。
现有的研究将有助于解释媒体报道的假设和文化态度是如何影响女性对自己的数学能力失去信心,以及她们追求的低愿望阻碍就业的。数据研究还描述了女性是如何被教育环境排除在数学、科学和技术相关领域之外的。我并不否认这样一个事实,即事情正在发生变化,女性对技术领域的看法正在蓬勃发展。
除此之外,多样化的劳动力在社会所有部门都变得极其重要,这一点尤其重要,因为在许多行业,特别是在技术和研究领域仍然存在差距。性别包容来自不同的背景,你获得了创造不同世界观的技能、才能和经验。人口普查显示,47.4%的美国劳动力是女性,但只有 27%的工作由女性担任(https://www.builtbyme.com/statistics-facts-women-in-stem/)。
数据科学和分析行业已经出现能力不足,估计申请人短缺。但很明显,需要填补的职位比工人多得多,这导致市场和单个公司陷入困境,未来可能会进一步失败。从真正务实的角度来看,通过在各个大学班级招募更多的人,更有意识地努力实现更大的性别平等,将会有更好的劳动力数据可以雇佣。在更多的工作竞争中,申请人的效率必然会提高,从而为大多数数据驱动型公司带来新的发展和创造力。在一个仍在争夺合适候选人的就业领域,让 50%的劳动力退出几乎没有意义,因为美国劳工统计局估计,未来八年,拥有数据处理能力的专家市场将增长 24%(https://www.bls.gov/news.release/pdf/ecopro.pdf)。
数据科学及其相关领域仍处于形成阶段,仅在过去 10 年才在组织中成功实施。这表明,现有的男性/女性差异不应该隐含在职业中,就像在零售、政治和技术行业中一样。首先,在脸书的所有员工中,只有 36%是女性(https://www . statista . com/statistics/311827/Facebook-employee-gender-global/),而加拿大最大的资产银行加拿大皇家银行的女性董事比例高达 42.9%。其次是加拿大丰业银行,该行 13 名高管中有 5 名女性,比例为 38.5%(https://thepayers . com/payments-general/canadas-top-banks-lead-the world-in-executive-gender-diversity-global data-study-finds-1240754)。通过确保数据驱动的部门和组织在就业增长的早期阶段可以获得公平的资源,该部门应该能够围绕健康和多样化的劳动力而不是给许多更传统的企业带来重大问题的传统男性主导文化繁荣和扩张。
Craigslist 的创始人 Craig Newmark(https://www . vox . com/2016/6/2/11834380/Craig-Newmark-Women-Tech-funding-gender-gap-diversity)在他的帖子《让我们认真对待支持科技领域的女性》中报道说,女性领导的科技公司比男性领导的公司平均高出 35%的资本回报率。他还引用了一项研究,该研究显示,拥有女性创始人的科技公司比那些创始团队全部由男性组成的公司表现好 63%。
在建设性、包容性的氛围中,我们应该通过促进从事数据科学、机器学习、人工智能、行业技术使用案例讨论论坛的性别少数群体个人的谈话,以及组织技术会议和网络活动,为参与者提供参与科学和教育讨论的论坛。我们尊重所有加入我们事业的人,无论其社会取向或职业背景如何。任务是纠正数据科学和技术的性别差距。创新改变了我们的生活方式,女性在设计软件、塑造科学目标以及创建数据技术和基于人工智能的应用程序方面必须是公平的合作者。我们应该鼓励刊登广告的文章,宣传真正的活动、大数据文化中女性的工作机会,以及免费或打折获取各种学习资源以提高技能。
但是,解决技术领域的性别差距不应该仅仅是满足行业内一定的男女比例。虽然招聘仍然是一个令人关切的问题,但重点应放在支持已经在该领域工作的妇女,庆祝她们的成就,以及提醒对该领域感兴趣或加入该领域的女孩和妇女,技能不分性别。在技术和数据科学领域,女性仍然处于劣势,获得更多的参与并不是一件容易的事情。提高对当前形势认识的运动应突出现有的发展前景,并揭示性别多样性的优势。女性一如既往地为科技行业增添了很多东西。但是,获得鼓励和对他们所带来的东西的欣赏将会以缓慢而稳定的速度缩小性别差距。
女性劳动力证明了她们富有创造力、适应性强、工作精明,并有能力承担责任。他们有能力在数据科学或技术领域出类拔萃。到 2020 年,超过 100 万个数据科学职位空缺(https://www . Inc . com/James-Kerr/how-the-girls-who-code-movement-can-change-the-world . html),公司转变员工队伍、接纳女性的机会可能终于到来了。在努力消除性别差异和填补空缺职位的同时,让女性展示她们的才华。多元化创造了一个理想的环境,员工可以在其中相互学习和了解。
让我们为彼此加油,看着彼此成长!
训练文本中的不稳定性——甘
大量的暗箱操作
介绍
在文本生成中,传统上,最大似然估计用于训练模型以一次一个标记地生成文本。每个生成的令牌都将与真实数据进行比较。如果任何令牌与实际令牌不同,该信息将用于更新模型。然而,这样的训练可能导致生成是通用的或重复的。
生成对抗网络(GAN)通过引入两个模型——生成器和鉴别器来解决这个问题。鉴别器的目标是确定一个句子 x 是真的还是假的(假的是指由模型生成的),而生成器试图生成一个可以欺骗鉴别器的句子。这两个模型相互竞争,这导致了两个网络的改进,直到生成器可以产生类似人类的句子。
尽管我们可能会在计算机视觉和文本生成社区中看到一些有希望的结果,但实际操作这种类型的建模是困难的。
GANS 的问题
- **模式崩溃(缺乏多样性)**这是 GAN 训练的通病。当模型不关心输入的随机噪声时,就会发生模式崩溃,不管输入是什么,它都会不断地生成同一个句子。从这个意义上来说,模型现在试图欺骗鉴别器,找到一个单点就足够了。
- **不稳定训练。**最重要的问题是保证发生器和鉴别器并驾齐驱。如果任何一个胜过对方,整个训练就会变得不稳定,学不到任何有用的信息。例如,当发电机的损耗缓慢降低时,这意味着发电机开始寻找方法来欺骗鉴别器,即使该代仍然不成熟。另一方面,当鉴别器为 OP 时,没有新的信息供生成器学习。每一代都会被评价为假的;因此,生成器将不得不依靠随机改变单词来搜索可能欺骗 d 的句子。
- 直觉不够。有时,您的预期建模是正确的,但它可能不会像您希望的那样工作。它可能需要更多的工作。通常,您需要通过调整学习率、尝试不同的损失函数、使用批量范数或尝试不同的激活函数来进行超参数调整。
- 大量的训练时间。一些工作报道了高达 400 个纪元的训练。如果我们与 Seq2Seq 相比,这是巨大的,seq 2 seq 可能只需要大约 50 个代来获得结构良好的一代。导致它缓慢的原因是一代人的探索。g 没有接收到哪个令牌是坏的任何明确信号。相反,它是为整个一代人而接受的。为了能够生成一个自然的句子,G 需要探索各种单词组合才能到达那里。你觉得 G 有多经常会不小心凭空产生< eos >?如果我们使用 MLE,信号非常清楚,应该有< eos >和紧随其后的< pad >。
潜在的解决方案
已经尝试了许多方法来处理这种类型的训练。
- 使用亚当优化器。有人建议使用 ADAM 作为发生器,SGD 作为鉴别器。但最重要的是,一些论文开始调整亚当的测试版。贝塔系数=(0.5,0.999)
- 瓦塞尔斯坦甘。一些使用 WGAN 的工作报告可以极大地稳定训练。然而,从我们的实验来看,WGAN 甚至达不到常规 GAN 的质量。也许我们遗漏了什么。(看到了吗?挺难的)
- GAN 变异。有人建议尝试吉隆坡或 VAE 甘。这些可以使模型更容易训练。
- 鉴频器的输入噪声。为了使鉴频器的学习与发生器的学习不相上下,发生器的学习通常比鉴频鉴相器更困难,我们在输入的同时输入一些噪声,并使用压差使事情变得更容易。
- DCGAN(深度卷积 GAN) 。这只适用于计算机视觉任务。然而,这种模型可以避免不稳定的训练。这个模型的关键是不使用 ReLU,使用 BatchNorm,使用步长卷积。
- 鉴频器组合。不是只有一个鉴别器,而是用不同的批次训练多个鉴别器,以捕捉不同方面的尊重。因此,生成器不能只欺骗单个 D,而是要更一般化,以便它可以欺骗所有的 D。这也和中途辍学的甘(很多 D,训练时辍学一些)有关。
- 参数调谐。学习率、辍学率、批量等等。很难确定一个模型比另一个模型好多少。因此,有些人会测试多个参数,看看哪个效果最好。一个瓶颈是没有针对 GAN 的评估指标,这导致需要大量手动检查来确定质量。
- 调度 G 和 D 。据报道,在许多工作中,试图学习 G 5 次然后学习 D 1 次是没有用的。如果你想尝试计划,做一些更有意义的事情。
while generator_loss > 0.5:
train_G()while discriminator_loss > 0.5:
train_D()
结论
基于对抗的文本生成为如何训练模型开辟了新的途径。不是依赖于 MLE,而是使用鉴别器来指示生成是否正确。然而,这种训练也有不好的一面,那就是很难训练。许多研究提出了一些如何避免上述问题的建议;但是,您需要尝试各种设置(或参数),以确保您的创成式模型能够正确学习。
进一步阅读
如何在训练生成对抗网络时识别不稳定模型?甘很难训练。原因是…
machinelearningmastery.com](https://machinelearningmastery.com/practical-guide-to-gan-failure-modes/) [## 从 GAN 到 WGAN
这篇文章解释了生成性对抗网络(GAN)模型背后的数学原理,以及为什么它很难被训练…
lilianweng.github.io](https://lilianweng.github.io/lil-log/2017/08/20/from-GAN-to-WGAN.html) [## soumith/ganhacks
(该列表不再保留,我不确定它在 2020 年的相关性如何),而生殖研究…
github.com](https://github.com/soumith/ganhacks) [## 甘——为什么生成性对抗网络这么难训练!
认出莫奈的画比画一幅容易。生成模型(创建数据)被认为是非常…
medium.com](https://medium.com/@jonathan_hui/gan-why-it-is-so-hard-to-train-generative-advisory-networks-819a86b3750b)
Instacart 探索性分析
在没有领域专家或业务涉众的情况下,制定可能的业务问题陈述。
介绍
Instacart 是一项当天送货和提货服务,允许消费者通过该公司的移动应用程序或网站从选定的杂货店购物,如 Trader Joe’s、Costco 和 Fairway。该公司有专门的员工从选定的商店购买食品并送货上门。该公司产生收入的方式是通过增加特定商店的价格、送货和会员费。因此,该组织的主要业务目标是,不仅增加客户会员的数量,而且改善回头客和订单。预测消费者对产品和杂货店的参与度和行为对 Instacart 的成功有着巨大的影响。
此分析的主要目的是执行探索性分析,并阐明增量业务问题以增加收入。为此,我们将依赖 Instacart 提供的历史数据。关于这个公开发布的数据集的更多信息可以在这里找到:https://www.instacart.com/datasets/grocery-shopping-2017
关于数据
该数据集由 Instacart 为 Kaggle 竞赛提供,是一组描述客户订单的关系文件。该数据集是匿名的,包含来自 20 多万 Instacart 用户的 300 多万份杂货订单样本。对于每个用户,数据集提供他们的 4 到 100 个订单,以及每个订单中购买的产品序列。该数据集还提供了下订单的星期和小时以及订单之间的相对时间度量。
每个变量的描述如下:
订单数据集: order_id:订单标识符,user_id:客户标识符,eval_set:此订单属于哪个评估集(参见下面描述的训练和先前数据集),order_number:此用户的订单序列号(1 =第一个,n =第 n 个),order_dow:订单是在一周中的哪一天下的,order_hour_of_day:订单是在一天中的哪一个小时下的,days_since_prior:自上一次订单以来的天数,上限为 30(order _ number 的 NAs = 1
产品数据集: 产品标识:产品标识,产品名称:产品名称,过道标识:外键,部门标识:外键
过道数据集: 过道 id:过道标识符,过道:过道名称
部门数据集: 部门标识:部门标识,部门:部门名称
order_products_prior 和 train 数据集: order_id:外键,product_id:外键,add_to_cart_order:每个产品被添加到购物车的顺序,重新排序:1,如果该产品在过去已经被该用户订购,0,否则,“prior”:在该用户最近的订单之前的订单,“train”:提供给竞赛参与者的训练数据,“test”:为机器学习竞赛保留的测试数据
数据收集和清理
理想情况下,在数据收集阶段之前,我们希望根据问题陈述定义数据需求,以便收集所需的数据。然而,在这种情况下,我们执行不同的方法,我们真的不知道 instacart 业务有什么问题,我们希望用可用数据来描述问题。这与数据科学项目流程观点完全不同,在数据科学项目流程观点中,我们通常希望首先与领域专家和利益相关者一起概述业务理解,并进一步定义收集方法、数据收集、清理和探索性分析。让我们从导入我们的包开始,加载每个数据集并简要地看一下它们。
instacart 订单数据集汇总
instacart 订单缺少值
查看来自客户的所有订单,我们总共有超过 300 万个订单,数字和字符串数据类型都符合预期,不需要我们更新。自从上一个订单以来,我们有超过 200,000 个丢失的值。然而,正如在变量描述中所解释的,NA 表示特定客户的 order_number 1。
instacart 产品概述
instacart 产品数据集摘要
instacart 产品缺少值
我们大约有 50,000 种产品带有产品 id、名称、通道 id 和部门 id。所有数据类型都符合预期,我们没有任何缺失值。
instacart 通道信息
instacart 通道数据汇总和缺失值
有 134 个通道具有通道 id 和通道名称。数据类型和预期的一样,我们没有任何缺失值。正如您可能注意到的,过道 id 变量是产品数据框架的常用变量。我们可以合并这两个数据框架,看看哪些产品属于哪个通道。
instacart 产品数据集
instacart 部门数据集
instacard 部门汇总
总共有 21 个部门有部门名称和 id。数据类型和预期的一样,我们没有任何缺失值。对于产品数据框架,我们有另一个公共变量“department_id”。我们可以合并部门数据框架,以查看什么产品属于哪个部门。
正如变量描述中所解释的,order products prior 数据集让我们了解在用户最近订单之前订购的订单。我们有超过 300 万的订单。数据类型正确,没有缺失值。我们还有 product_id 公共变量,我们可以将这个数据集与产品合并,以查看什么产品映射到什么订单。
我们在产品和订单数据集之间还有另一个公共变量 order_id。我们可以合并这两个数据框架,以帮助进一步收集产品和订单之间的信息。
instacart 最终产品和订单数据集
我们已经获得了超过 130 万个训练数据,数据类型正确,没有缺失值。在这一点上,instacart 提供的数据集似乎非常干净,除了合并过道、部门、产品和订单数据集,我们不需要做太多的数据争论。
数据探索
在这个阶段,我们将单独查看数据集的更新版本,并收集见解以开始创建可能的业务问题。
instacart 客户订单数量
我们在这里看到的是,23986 名客户只下了 4 份订单,19590 名客户只下了 5 份订单,依此类推……随着客户下订单数量的增加,下订单的客户数量会减少。大多数客户会下 4 到 12 份订单。如果一家企业找到了增加回头客订单数量的方法,它就能增加收入。
instacart 客户本周采购
大多数购买发生在周一和周二,其次是周日。消费者可能会在一周的第一天和第二天进行每周一次的杂货店购物。一周的其他日子之间也没有太大的差距。例如,周三和周二之间的差异并不显著。
instacart 客户购买时间
大多数购买发生在上午 10 点到下午 4 点之间。
instacart 客户购买频率
大多数顾客每周或每月都购物。考虑到大多数客户也在每周的周一或周二下订单,下订单可能需要计划工作。这可能是由于非无缝订购流程造成的。
Instacart 篮子大小分析
我们可以看到,根据购物篮的大小分布,大多数客户在每个订单中购买了 5 到 6 件产品。考虑到回头客的订单量较低,每个客户的产品量较低可能会给企业带来巨大的收入问题。
Instacart 热门产品分析
Instacart 顶级产品
前十个重新排序的项目与通常排序的前十个项目完全匹配。此外,十大购买商品中的大部分都在新鲜水果区。
Instacart 顶级部门
顶部通道是新鲜水果、新鲜蔬菜、包装蔬菜和水果,其次是酸奶和包装奶酪。
Instacart 客户购买日
正如我们前面指出的,订单百分比最高和篮子容量最大的时间是星期一和星期二。
Instacart 产品百分比日分布
正如我们之前发现的,订购量最高的产品是香蕉、有机香蕉袋、有机菠菜和有机草莓。有趣的是,在前四种产品中,香蕉在每天的订单中所占比例最大,但其他四种产品对周三、周四、周五、周六和周日的订单比例没有任何贡献。这是否与物料库存问题相关?
Instacart 部门分布
最高的部门是农产品,其次是奶制品、鸡蛋和小吃。除了一般的个人偏好和需求,消费者不从其他部门购买可能还有其他原因。例如,如果 instacart 对罐装商品具有最大的加价,但 instacart 网站或应用程序内的用户体验并不能吸引消费者购买罐装商品,则无论消费者的需求如何,罐装商品的订单金额都会很低。
数据集相当大,有许多变量可供我们分析。与我们在之前的学习关联文章中所做的类似,我们可以进一步查看产品之间的详细关联规则(尽管将现有的大型数据集拆分并转换为交易数据集具有挑战性),从天数和小时数、再订购率与订单小时数等方面调查消费者的再订购模式…
结论
查看各种数据科学流程和方法,您会发现几乎所有的流程和方法都有类似的方法,即从业务理解开始,概述要验证和解决的业务问题陈述。然而,我们可能会遇到这样的情况,领域专家、品牌所有者、业务单位或利益相关者可能不一定知道或没有时间找出业务问题是什么。在大多数情况下,他们会通过产品经理来识别、阐述业务问题,并提供切实可行的建议来解决这些问题。
在我们的 instacart 分析中,我们可以总结出可能影响收入的业务问题有:
- 客户订单的频率较低,从 4 到 12 不等。企业可以采取什么措施来提高客户订单的频率?
- 大多数客户计划每周和每月购买一次。企业可以采取什么措施来改善一周和一月中任何一天的采购?举个例子;亚马逊把他们的整个订购产品和过程做得天衣无缝,以至于我个人不会广泛地计划我的杂货购买。如果我需要亚马逊的产品,我会在当天订购。
- 除了香蕉,顶级商品大多在周一和周二出售。这是否与零售商的商品库存问题有关?比如说;有没有可能 Trader Joe’s 的有机草莓在周三就卖完了,instacart 的员工会根据顾客的要求用普通草莓代替订单?
- 除了一般的消费者和市场需求,某些部门的销售额比其他部门低还有什么原因吗?(如 instacart 网站或手机 app 可用性问题)
阐明和定义业务问题陈述对于为业务目标找到正确的解决方案极其重要。在我之前关于线性回归的文章中,我提到了一些统计学家在没有创建问题陈述的情况下就开始数据分析是多么有问题,然而,在许多情况下,利益相关者期望数据驱动和制定这些问题陈述。
Instacart 用户细分和购物篮分析
了解客户在 Instacart 上的购物行为,并做出有效的推荐
新冠肺炎在 2020 年已经是一个世界传播的疫情。因此,纽约人遵循隔离政策,彼此保持社交距离。众所周知,在纽约最受欢迎的交通方式是地铁。然而,地铁是传播新冠肺炎最危险的交通工具之一,这可能会增加地铁乘客感染新冠肺炎的风险。因此,外出获取日常所需成了纽约人头疼的问题。杂货店里的人保持社交距离是不实际的。在新冠肺炎疫情爆发期间,纽约市发布了“呆在家里”的命令,这增加了对网上购物的需求。Instacart 是一个杂货交付平台,在新冠肺炎危机期间经历了快速增长。现在,用户获得了呆在家里的价值,以使曲线变平,并降低他们自己感染病毒的风险。
主要研究目标是基于时间间隔进行用户细分,并基于用户的产品选择建立推荐系统。本研究期望在不违反社会距离规则的前提下,优化供应方的库存分配,增加顾客获得必需品的概率。
首先,我们来探究一下数据!
主要数据来源于 Instacart 的 2017 年匿名化客户随时间的订单(Stanley,2017)。它包含订单文件、产品文件、订单和产品文件、过道文件和部门文件。数据集中的每个实体都有一个关联的唯一 id。
在订单数据集中,它包含用户 id、订单 id、订单购买日期(order_dow)、订单购买时间(order_hour_of_the_day)、自上次购买以来的天数(day_since_prior)以及订单所属的指示符(eval_set)。如果是第一次购买,则自上次购买后的天数为 NaN。在部门数据集中,它包含唯一的部门 id 和关联的部门名称。在过道数据集中,它有过道 id 和过道名称。在产品数据集中,它包含产品 id、产品名称、过道 id 和部门 id。
为了制定用户订单的时间间隔,我们首先以天为单位划分用户订单。我们这里使用的数据是 order.csv,列名为“dow”。从图 1 来看,用户订单最多的日子是第 0 天和第 1 天。查看数据说明后,我们没有找到第 0 天到第 6 天的定义。我们认为 0 和 1 这两个繁忙的日子应该是周日和周一。
图 1(作者图片)
有了更详细的视图,我们选择小时作为单位来绘制订单频率条形图。两条尾巴表明 Instacart 在早上和傍晚时间没有太多的交付。大多数订单是在时间间隔小时[9,16]下的,平均每小时约有 25000 个订单。
图 2(作者图片)
结合上面的两个数字,我们决定使用热图来检查最受欢迎的订单时间。y 轴是按天计数的订单,x 轴是按小时计数的订单。从图 3 来看,较暗的部分意味着用户订单密度较高的时间段,大约是第 0 天和第 1 天的上午 9 点到下午 4 点。
图 3(作者图片)
图 4 显示了下降趋势。大部分用户在频率区间[0,40]下单。少数用户订单在 60 以上。超过 100 的唯一订单被计为一组。x 轴限制了将所有计数订单放在一个图表上。
图 4(作者图片)
一个有趣的发现是,从图 5 中,我们发现超过 400,000 个用户可能会将香蕉添加到他们的订单中。名单上大部分产品都是有机蔬菜和水果!
图 5(作者图片)
机器学习建模:
K-表示:
基于 EDA 的结果,很可能得出这样的结论:消费者更有可能在上午 10 点到下午 4 点之间购买。此外,如图所示,在第 0 天和第 1 天,Instacart 的交易量与其他日期相比相对较高。为了进一步了解消费者的购买行为并进行具体的消费者细分,我们使用了 k-means 聚类。不仅基于在星期几、星期几购买的订单,还基于自上次购买以来的天数和添加到购物车订单,来计算每个用户使用 Instacart 的频率和每个订单购买的商品的中位数。
首先,利用轮廓得分选择 k-means 中的最佳聚类数。
由于处理量大,我们对 5%的数据集(超过 10,000 条用户记录)进行了五次采样,以生成训练数据集的准确轮廓分数。正如它所建议的,我们在 k-means 算法中设置了 3 个聚类。在应用 PCA 降低维度之后,我们能够绘制每个聚类(图 6)。
图 6(作者图片)
随机森林:
在进行 k-means 聚类和标记数据后,我们使用聚类 0,1,2 来训练我们的第一个 K-means 模型。我们希望将我们的模型从无监督学习转移到有监督学习。因此,我们将数据集分为训练样本和测试样本。通过使用 GridSearchCV,我们发现应该使用 21 作为我们的估计量,使用 97 作为我们的最大叶节点。**在训练我们的模型并拟合测试集之后,**我们计算了多类别 ROC AUC 得分,该得分为 0.999,这意味着我们的随机森林模型很好地分离了三个类别。
特征重要性(作者图片)
推荐系统
在我们的推荐系统模型中,输出是大多数其他客户会购买但输入客户不经常购买的部门和通道。由于输出不仅基于大多数训练数据,而且基于输入客户购买历史的皮尔逊相似性,我们的模型考虑了不同组的客户偏好。
出于节省时间和计算的原因,我们使用来自前 10,000 个用户的数据来训练我们的模型。通过从每个集群中随机抽取 5 个用户作为输入,结果证明了我们的假设。对于每个集群中的 5 个用户和 5 个推荐的部门和通道,我们在 25 个值中寻找共享最多的前 3 个常用名称。
推荐部门:
- 第 0 类:酒精、散装、婴儿
- 第 1 类:酒、干粮和散装面食
- 第 2 组:酒类、散装、肉类和海鲜
推荐过道:
- 第 0 类:面部护理、皮肤护理、头发护理
- 集群 1:散装谷物大米干货,面部护理,皮肤护理
- 第二组:护肤、烈酒、面部护理
从该表中,我们可以看出,集群 0 和集群 1 中的客户(占总用户的 64.6%)是 Instacart 的忠实用户,他们可能有很高的需求,并在新冠肺炎期间给 Instacart 的运营带来巨大压力。
用人工神经网络预测限量版运动鞋转售价格的 Instagram 分析
“我喜欢运动鞋。我想我可以称自己为收藏家”——麦克·信田
用神经网络从大量运动鞋中寻找独角兽运动鞋
来自https://unsplash.com/photos/5d4EhqeV0Og的免版税图片
做球鞋头本身就是一种文化,有自己的行业。每个月,最大的品牌都会推出一些精选的限量版运动鞋,根据名为“抽奖”的抽奖系统在市场上销售。这创造了一个自己的新市场,在这个市场中,能够从彩票系统中赢得运动鞋的人希望以更高的价格卖给那些更想要这双鞋的人。你可以找到许多网站,像 stockx.com 的、goat.com 的,来转售未接触过的限量版运动鞋。
但转售运动鞋的问题是,每一款限量版运动鞋都不成功,也不能获得高额利润。人们必须研究“炒作”,“流行度”,这种模型是一个热门话题,比其他模型讨论得更多,如果人们能够发现这一点,甚至可以获得高达 300%的利润。
我发现了一种方法,可以通过 Instagram 分析发现某些型号的“炒作”或受欢迎程度,并研究与运动鞋相关的标签,找出哪只运动鞋是独角兽。
准备数据
Instagram Api 不允许您研究其他个人资料上的喜欢和评论,所以我们不使用 Instagram Api,而是需要像这样使用哈希查询
url='https://www.instagram.com/graphql/query/?query_hash=c769cb6c71b24c8a86590b22402fda50&variables=%7B%22tag_name%22%3A%22**azareth**%22%2C%22first%22%3A2%2C%22after%22%3A%22QVFCVDVxVUdMLWlnTlBaQjNtcUktUkR4M2dSUS1lSzkzdGVkSkUyMFB1aXRadkE1RzFINHdzTmprY1Yxd0ZnemZQSFJ5Q1hXMm9KZGdLeXJuLWRScXlqMA%3D%3D%22%7D'
如你所见,关键字 *azareth,*是我的标签。您可以简单地将关键字更改为您想要从中获取数据的任何标签。
让我们为 Air Jordan 1“无畏”球鞋选择一些标签# airjordanfearless,# fearless,# jordanbluefearless,#fearlessjordan,# aj1fearless,# ajonefearless,# airjordanonefearless
有了数据框架后,就该看看我们可以用 Instagram 散列查询做些什么了。我们可以找到与某个标签相关的总点赞数、总评论数、总发帖数,这些参数可以帮助我们预测运动鞋的“炒作”和“受欢迎程度”。
我们将需要 urlib 和请求库来打开 URL,并检索我们需要的某些值,如总喜欢,总评论,甚至图像本身。
为了创建训练数据,我制作了一些精选运动鞋的类似数据框——yee zy 700 Azareth、Nike X Sacai Blazar、Puma 拉尔夫·桑普森 OG、Nike SB Dunk X Civilist、Nike Space 嬉皮士系列。
我取了每双运动鞋的所有标签的总点赞、评论和帖子的平均值来创建训练数据。以下运动鞋的最高转售价格来自 goat.com。
数据训练和人工神经网络模型构建
数据训练
1-哈希查询为某些标签提供来自 Instagram 的最新照片,因此它减少了将任何旧型号运动鞋照片纳入数据的可能性,这验证了,因为某一运动鞋的“炒作”或“受欢迎程度”可能是根据最新照片估计的,因此我们可以知道哪些运动鞋现在正在谈论和热门,并具有更多转售价值。
2-对于照片上标签重叠的任何可能性,(这是很有可能的),我说的是总喜欢/评论和帖子的计数,以训练数据和预测转售价格。
3-为了验证模型,而不是分割数据来训练或测试,我们可以简单地将标签放入最近发布的运动鞋的 x_test 中,并将我们的预测与实际的持续转售价格进行比较。
人工神经网络
对于 X,我使用了变量“likes”、“comment”、“post”、“releaseprice”,对于 Y/Labels,我使用了“maxretailprices”,以便让模型通过从 X 变量获取数据来学习如何在神经元中放置不同的权重,并达到“maxretailprices”/Y 数据,并找到 Instagram 上的赞数和评论数与最大零售价格之间的模式。
原因是,Instagram 上与特定运动鞋相关的更多喜欢、评论和帖子将反映其炒作,在 Instagram 用户中的受欢迎程度,模型可以找到准确的权重来确定两者之间的关系
模式调谐
学习率 —我选择了 0.001 的低学习率,以便让模型找到权重并制作梯度,而不会超过最小值。
损失方法 -我选择 MSE 作为损失方法,因为我试图找到变量之间的关系,所以它是一种回归
激活方法 -Relu 是最佳选择,因为它会将所有负值变为 Instagram 显示-1 值为 0 ),如果大于 0,则放置精确值)
层和神经元 -我用神经元和层来寻找梯度不会爆炸的最佳组合,并最大限度地减少损失,并且能够在 50 个时期内找到更好的模式和权重。
结果
我没有创建足够大的训练数据来在训练和测试之间分割数据。因此,为了验证结果,我简单地创建了一些最近发布的 x_test 数据框架,就像我向您展示的那样,并将我的模型预测与 goat.com.Here 的转售价格进行了比较,例如耐克 dunk LOW sb Black 在 goat.com 的转售价格为 326 欧元
因此,通过简单的神经网络,该算法能够将运动鞋的受欢迎程度与运动鞋在市场上的估计转售价值联系起来,因此经销商和收藏家可以轻松预测哪些运动鞋是独角兽,哪些运动鞋与商店中的其他运动鞋一样。
对于完整的 jupyter 笔记本和代码,您可以通过github.com—https://github . com/Alexa Mann/insta gram-analysis-to-predict-Sneaker-retail-prices-with-ANN查看我的知识库
在 Windows 10 中安装和配置 OpenCV-4 . 2 . 0—Python
在 Windows 10 中安装 OpenCV-4.2.0 的完整指南
这篇文章将指导您在 Windows 10 (64 位)中安装和配置 OpenCV-4.2.0 的所有步骤,以便在 Anaconda 环境中使用 python。
- OpenCV 和 Anaconda,用于 Python 3.6.0+开发
我将在这里重点介绍 OpenCV for python 3.6.0+,我之前关于 VC++集成的帖子可以在这里找到。
注意:为了跟随教程,我假设你已经安装了 Anaconda 和 Python 3.6.0 。如果没有,请在继续阅读之前安装这些工具。
用于 Python 的 OpenCV-4.2.0
通过 Anaconda 安装 OpenCV 的步骤非常简单直接。不要忘记将 Anaconda 添加到您的路径中,这样您可以很容易地从提示符下访问conda
命令。
步骤 1:为 OpenCV 创建一个 conda 虚拟环境
conda create --name opencv-env python=3.6
opencv-env
是指虚拟环境的名字,你可以随意命名,但记得要挑一个有意义的名字。
- 为项目创建一个文件夹,用于存放 python 脚本。
- 通过命令行
cd C:\Users\<username>\my_folder
进入您的文件夹,使用以下命令激活您刚刚创建的虚拟环境: conda activate opencv-env
注意:如果您在 windows 中使用 bash 作为默认终端,
*conda activate opencv-env*
可能不会像预期的那样工作。这是因为默认情况下,bash 没有正确配置为运行 anaconda 脚本,所以您可以为它提供一个解决方法:
- 编辑您的。bashrc 文件
c:\Users\<username>\.bash_profile
添加下面一行代码:
用 Visual Studio 代码编辑
2.每当您想要午餐您的 bash 终端时,添加下面的参数:--login -i
,因此您将午餐您的定制 bash 概要文件,它已经被授权访问 conda 脚本。
现在,您的 conda 环境已经激活,并且完全可用。
步骤 2:安装 OpenCV 和所需的包
要使用 OpenCV,你必须安装一些重要的软件包:
pip install numpy scipy matplotlib scikit-learn
pip install opencv-contrib-python
pip install dlib
步骤 3:测试您的安装
您应该可以在 python repo 中获得最新的 OpenCV 版本。
就这些了,好好享受 OpenCV 吧。
更多安装信息,请访问 OpenCV 官方指南。
在 Windows 10 中安装和配置 OpenCV-4 . 2 . 0—v c++
在 Windows 10 中安装 OpenCV-4.2.0 的完整指南
这篇文章将指导你在两种不同的环境下在 Windows 10 (64 位)中安装和配置 OpenCV-4.2.0 的所有步骤:
- OpenCV 与 Visual Studio 2019,用于 C++开发
- OpenCV 和 Anaconda,用于 Python 3.6.0+开发
我将在这里重点介绍 OpenCV for Visual Studio with C++,python 和 Anaconda 的其他教程部分可以在 这里 找到。
注意:为了跟随教程,我假设你已经安装了 Visual Studio 2019 。如果没有,请在继续阅读之前安装这些工具。
适用于 Visual Studio 2019 的 OpenCV-4.2.0
为 Visual C++开发设置 OpenCV 的所有必要步骤。
步骤 1:安装 C++桌面开发工作负载
打开 Visual Studio 安装工具,将 C++ for desktop development 作为工作负载添加到当前的 Visual Studio IDE 版本中。这一步是必不可少的,因为如果没有所有 C++所需的库,就不能在 VS 中使用 OpenCV。
Visual Studio 安装程序向导
步骤 2:下载并安装 OpenCV-4.2.0
下载适用于 Windows 平台的 OpenCV 4.2.0 最新稳定版(opencv-4.2.0-vc14_vc15.exe)。进入 OpenCV 官方网站:https://opencv.org/->-资源->-发布点击 Windows 平台。你将被重定向到 SourceForge,下载将自动开始。
OpenCV-4.2.0 版本:https://opencv.org/releases/
在运行下载之前。exe 文件,转到 C:\文件夹并添加一个名为 opencv-4.2.0 的新文件夹。运行安装程序并将 zip 文件解压到新创建的 opencv-4.2.0 文件夹中。
将包含 OpenCV 编译版本的 zip 文件解压到您的文件夹中
步骤 3:将 OpenCV 二进制文件添加到您的系统路径中
一旦 OpenCV 正确地安装在您的文件夹中,您现在必须将二进制文件C:\OpenCV-4.2.0\opencv\build\x64\vc15\bin
添加到您的系统路径中,这样您就可以通过命令行轻松地访问 OpenCV 可执行文件。
编辑系统路径
步骤 4:配置 Visual Studio 项目以运行 OpenCV
打开 Visual Studio 2019,选择创建一个新项目,然后转到 C++控制台应用程序模板。
创建一个新项目,并选择控制台应用程序 C++模板
创建项目后,您应该有一个布局,其右侧有一个解决方案资源管理器,其中有一个源文件,并且在窗口上方的功能区中,您应该看到针对x86
平台的Debug
,这意味着该项目将针对 x86 windows 体系结构以调试模式构建和运行。
- 首先,您应该将解决方案平台从
x86
更改为x64
- 其次,您必须更改项目属性来添加 OpenCV 库
更改目标解决方案平台,并转到项目属性
在能够执行任何代码之前,有许多属性需要编辑:
- 转到配置属性/VC++目录为 OpenCV 添加包含和库目录。
编辑包含目录和库目录
单击蓝色条目旁边的右箭头
包括内部系统路径
对于包含目录,您必须添加以下路径:C:\OpenCV-4.2.0\opencv\build\include.
对库目录做同样的操作,添加这个内部路径:C:\OpenCV-4.2.0\opencv\build\x64\vc15\lib.
Include 和 Lib 目录都添加到项目中
2.用opencv_world420d.lib
OpenCV 动态库编辑 VC++项目链接器。你会在这里找到DLL(DdynamicLinkLibrary):C:\OpenCV-4.2.0\opencv\build\x64\vc15\lib
复制文件名opencv_world420d.lib
粘贴到依赖框中。
完成后,单击“确定”按钮
最后一步:测试一些代码
最后,您可以在 visual studio IDE 中运行这个演示代码,看看它是否工作正常。
生成的图像
就这样,您现在可以轻松地使用 OpenCV 了。😉
更多安装信息,请访问 OpenCV 官方指南。
在 Linux 和 MacOS 上安装和运行多个 Java 版本
在任何基于 UNIX 的系统上安装并行 Java 版本的分步指南
如果您是 Java 开发人员,您可能需要在您的机器上安装多个 Java 版本。您可以在项目中使用 Java8 或 Java11,但希望学习更新版本的 Java。或者也许你正在做两个不同的项目,其中使用了两个不同版本的 Java。
实现这一点的一种方法是安装多个 Java 版本,并手动配置不同的 Java 版本。在这种情况下,当您需要切换 Java 版本时,您必须修改一些环境变量。另一种优雅便捷的方式是使用 SDKMAN 。
SDKMAN 是一个软件开发工具包管理器,用于管理大多数基于 Unix 的系统上的多个软件开发工具包的并行版本。它允许我们安装、移除、切换和列出不同 SDK 的候选版本,包括 Java (例如,JDK、Ant、Dotty、Gradle、Scala 等等)。
在这里,我将展示如何使用 SDKMAN 在基于 UNIX 机器上管理多个 Java 版本。通过阅读本文,您将了解以下内容:
- 安装 SDKMAN
- 使用 SDKMAN 列出候选人 JDK
- 使用 SDKMAN 安装多个候选 JDK
- 使用 SDKMAN 切换候选 JDK
- 使用 SDKMAN 删除/卸载 JDK
这些指令对大多数基于 UNIX 的操作系统有效,包括 MacOS、任何 Linux OS (Ubuntu、Debian、MINT、Manjaro、OpenSUSE)、FreeBSD、Solaris、Cygwin 。
步骤 1:安装 SDKMAN
打开一个新的终端并输入
**curl -s “https://get.sdkman.io" | bash**
现在,在终端中复制并粘贴以下内容,然后输入
**source "$HOME/.sdkman/bin/sdkman-init.sh"**
它会在你的机器上安装 SDKMAN。然后,您可以检查 SDKMAN 的版本
**sdk version**
步骤 2:列出可用的 JDK
通过给出以下命令,查看 SDKMAN 提供的可用 Java 版本
**sdk list java**
它将显示来自不同供应商的所有可用 JDK 及其支持的版本。
步骤 3:安装并行 JDK
安装特定的 JDK,例如 BellSoft 的 JDK 15 Liberica
**sdk install java 15.0.0-librca**
Installing: java 15.0.0-librca
Done installing!Do you want java 15.0.0-librca to be set as default? (Y/n):
现在,您可以使用以下命令检查安装的 Java 版本
**java -version** openjdk version "15" 2020-09-15
OpenJDK Runtime Environment (build 15+36)
OpenJDK 64-Bit Server VM (build 15+36, mixed mode, sharing)
您现在可以安装另一个 JDK,例如 BellSoft 的 JDK 8 Liberica
**sdk install java 8.0.265-librca**
Installing: java 8.0.265-librca
Done installing!Do you want java 15.0.0-librca to be set as default? (Y/n):
步骤 4:在 JDK 之间切换
如果您现在列出可用的 JDK,您将看到已安装的 JDK 标记为 **installed,**如下所示。
**sdk list java**
然后,您可以使用以下命令更改 JDK
**sdk use java 8.0.265-librca** Using java version 8.0.265-librca in this shell.
您可以按如下方式检查已安装的 JDK
**jdk -version**
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (build 1.8.0_265-b01)
OpenJDK 64-Bit Server VM (build 25.265-b01, mixed mode)
步骤 5:卸载 JDK
您可以使用以下命令卸载 JDK
**sdk uninstall java 15.0.0-librca**
Uninstalling java 15.0.0-librca…
结论
在本文中,我展示了如何使用 SDKMAN 在基于 UNIX 操作系统中轻松优雅地管理多个 Java 版本。我使用 NVM 来管理本地机器上的多个 Node.js 版本,我认为 SDKMAN 在有用性和开发人员友好性方面与 NVM 不相上下。事实上,SDKMAN 支持安装其他 JVM 工具和 SDK,如 Groovy、Scala、Kotlin、Ceylon。蚂蚁,格雷尔,格雷尔斯,梅文,SBT,火花,Spring Boot,Vert.x 。如果你使用 Java 和 JVM,你应该试试 SDKMAN。管理多个 Java 和其他基于 JVM 的 SDK 版本将使您的生活更加轻松。
类似文章:
Java 和 JVM 软件开发中基本 Java 库的精选列表
towardsdatascience.com](/top-10-libraries-every-java-developer-should-know-37dd136dff54) [## 10 个优秀的 GitHub 库,适合每一个 Java 开发者
面向 Java 开发人员的基本 GitHub 库的精选列表
towardsdatascience.com](/10-excellent-github-repositories-for-every-java-developer-41084a91ade9) [## 您应该尝试的 25 个鲜为人知的 Java 库
对 Java 和 JVM 软件开发有很大帮助的库
towardsdatascience.com](/25-lesser-known-java-libraries-you-should-try-ff8abd354a94)
在你的 Ubuntu 上安装我的面部解锁
是福斯…!
TL;速度三角形定位法(dead reckoning)
在你的 Ubuntu 上安装我的软件Facerec-Linux face unlock
。它是高度优化的,并有一个用户友好的 CLI 来操作它。你可以用*apt install*
像安装其他 ubuntu 软件一样安装它。 查看安装指南 此处 。
故事
大约一年前,作为我在大学的学术项目,我第一次开发了这个软件。我决定它的名字是 Facerec 。最后我把它推到 GitHub 上,并附上了一套安装说明。最初,我没想到会有很多人使用它。它没有友好的安装/使用指南。当人们通过电子邮件和 LinkedIn 联系我,告诉我他们面临的问题时,我感到惊喜。所以我决定花更多的时间让它变得更好和用户友好。
所以我又花了几个星期在这个项目上。这一次,我想我让它变得非常神奇。我几乎重写了整个代码库,现在我正式以facerec v1.1
的名字发布它,这一切都是值得的。响应时间减少 70%,现在超级安全。此外,我已经为它创建了一个 PPA(个人包档案)。所以,现在你可以像其他 Ubuntu 软件一样安装它,用apt install
。
怎么样
- 整个模型已经更新,以获得更好的性能。
- 提高安全性。
- 严重的错误修正,如软件中心冻结问题等。
- 一个有更多功能的更好的 CLI。
- CLI 的自动完成。这是我特别引以为豪的小功能之一😂
- 一个 deb 包,PPA,和一个 docker 镜像用于测试。
欢迎投稿
- 错误报告,功能请求和 PRs 将被高度赞赏。
- 测试环境的 Dockerfile 可以在这里找到。(即将上传图片到 docker hub)
- 目前只有 Ubuntu 支持 facerec。平我,如果你想为其他发行。
安装
1。更新来源
sudo apt update
2。将 PPA 添加到您的机器中
sudo add-apt-repository ppa:rushabh-v/facerec
3。安装 Facerec
sudo apt install facerec
4。来源 bashrc
source ~/.bashrc
命令行界面
截图来自自述
仔细讨论
点击查看。如果你用 Ubuntu,可以考虑试一试,对于其他发行版,可以查看 howdy 。你可以在这里阅读更多关于我如何构建这个项目的信息。
回购的链接
[## rushabh-v/linux_face_unlock
Facerec 是一个面向 Ubuntu Linux 的人脸认证系统,可以在登录、运行“sudo”命令等时工作
github.com](https://github.com/rushabh-v/linux_face_unlock/)
安装 Pyspark 并在 macOS 和 Linux 上使用 GraphFrames
关于如何在不同操作系统上安装 Pyspark 和使用 Spark GraphFrames 的详细指南
image_credit —数据块(https://databricks.com/spark/about)
Linux(Ubuntu)
以下所有操作都应在终端下完成。
- 下载 Spark
wget [http://d3kbcqa49mib13.cloudfront.net/spark-2.2.0-bin-hadoop2.7.tgz](http://d3kbcqa49mib13.cloudfront.net/spark-2.2.0-bin-hadoop2.7.tgz)
2.解压缩文件
tar xf spark-2.2.0-bin-hadoop2.7.tgz
3.如有必要,安装 Java8
sudo add-apt-repository ppa:openjdk-r/ppasudo apt-get updatesudo apt-get install openjdk-8-jdk
您可以通过“java -version”来检查您的安装。如果不是“1.8.xxx”,您需要按照步骤 5–6 选择正确的 java 版本供 spark 使用。
sudo update-java-alternatives — set java-1.8.0-openjdk-amd64
重启你的终端。
4.(可选)如果你想更熟练地使用 Spark,你最好熟悉基本的 Linux 命令和基本的 Bash 操作。可以参考下面这本书【http://linux-training.be/linuxfun.pdf
mac 操作系统
- 安装自制软件:
/usr/bin/ruby-e " $(curl-fsSLhttps://raw . githubusercontent . com/home brew/install/master/install)"
2.安装 Scala:
brew install scala
3.安装 Spark:
brew install apache-spark
4.启动 spark python shell(在 spark 目录中):
pyspark
Jupyter 安装(Linux & Mac OS)
Jupyter 笔记本徽标
- 安装 Anaconda。
Linux:
wget [https://repo.continuum.io/archive/Anaconda2-4.3.0-Linux-x86_64.sh](https://repo.continuum.io/archive/Anaconda2-4.3.0-Linux-x86_64.sh)
Mac OS:
wget [https://repo.anaconda.com/archive/Anaconda2-2019.07-MacOSX-x86_64.sh](https://repo.anaconda.com/archive/Anaconda2-2019.07-MacOSX-x86_64.sh)
安装:
bash anaconda 2–4 . 3 . 0-Linux-x86 _ 64 . sh(使用相应的文件)
更新$PATH 变量
Linux:源码~/。bashrc
Mac OS: source ~/。bash_profile
修改 pyspark 驱动程序
导出 PYSPARK_DRIVER_PYTHON="jupyter "
导出 py spark _ DRIVER _ PYTHON _ OPTS = " notebook "
启动 spark python shell(在 spark 目录中):
。/bin/pyspark
注意事项:
- 可以执行“unset py spark _ DRIVER _ PYTHON py spark _ DRIVER _ PYTHON _ OPTS”来运行普通的 pyspark shell
- 如果你发现这个错误“我找不到匹配 PySpark 的内核。请选择一个内核:“你从讲义上传笔记本后,你只要选择已经支持 pyspark 内核的 Python2 内核即可。
- 完成这些步骤后,创建一个新的笔记本,键入“sc”并运行它。如果在输出中看到“pyspark.context.SparkContext ”,安装应该成功。
图表框架:
对于预装 Spark 版本的 ubuntu,要使用 GraphFrames:
获取 jar 文件:
在 Jupyter 笔记本
sc . addpyfile(’ path _ to _ the _ jar _ file ')中加载 jar 文件
将 pyspark shell 直接用于 GraphFrames:
。/bin/pyspark —包 graph frames:graph frames:0 . 7 . 0-spark 2.4-s _ 2.11
本地使用 Jupyter:
设置环境变量:
export SPARK _ OPTS = "—packages graph frames:graph frames:0 . 7 . 0-SPARK 2.4-s _ 2.11 "
在 Jupyter 笔记本
sc . addpyfile(’ path _ to _ the _ jar _ file ')中加载 jar 文件
在 Azure Databricks 服务中:
启动集群
搜索“graphframes”并安装库
弗洛里安·奥利沃在 Unsplash 上拍摄的照片
感谢您的阅读,我期待听到您的问题和想法。如果你想了解更多关于数据科学和云计算的知识,可以在Linkedin上找我。