机器学习的核心是你所拥有的数据和你想要回答的问题
本课所用数据集:安然邮件数据
利用该文库发现该欺诈案件的嫌疑人的电子邮件中是否存在某种模式,并检查是否可以发现这种模式
嫌疑人
可能的嫌疑人:
1.被控告的人
2.已定罪但没有认罪的人
3.为政府作证,以换来起诉豁免权的人
准确率与训练集大小
MORE DATA > FINE-TUNED ALGORITHM
更多数据几乎总能帮助算法取得更好的效果
数据类型
numerical ---numerical values(numbers)
-- salary
-- number of emails sent by a given person
categorical ---limited number of discrete values(category)
-- job title
time series ---temporal value(date,time stamp)
-- time stamps in email
text ---words
-- contents of emails
-- to/from fields of emails address
数据集和问题迷你项目
安然欺诈案是一个混乱而又引人入胜的大事件,从中可以发现几乎所有想像得到的企业违法行为。安然的电子邮件和财务数据集还是巨大、混乱的信息宝藏,而且,在你稍微熟悉这些宝藏后,它们会变得更加有用。我们已将这些电子邮件和财务数据合并为一个数据集,而你将在此迷你项目中研究它。
开始:
- 克隆这个 GitHub 库:https://github.com/udacity/ud120-projects
- 运行开始代码:
datasets_questions/explore_enron_data.py
"""
Starter code for exploring the Enron dataset (emails + finances);
loads up the dataset (pickled dict of dicts).
The dataset has the form:
enron_data["LASTNAME FIRSTNAME MIDDLEINITIAL"] = { features_dict }
{features_dict} is a dictionary of features associated with that person.
You should explore features_dict as part of the mini-project,
but here's an example to get you started:
enron_data["SKILLING JEFFREY K"]["bonus"] = 5600000
"""
import pickle
enron_data = pickle.load(open("../final_project/final_project_dataset.pkl", "r"))
安然数据集的大小
聚合的安然电子邮件和财务数据集被存储到字典中,字典中的每个键是一个人名,而且值是包含此人所有特征的一个字典。
电子邮件和财务 (E+F) 数据字典被存储在 pickle 文件中,该文件可直接存储和加载 python 对象,非常方便。 使用 datasets_questions/explore_enron_data.py 加载数据集。
数据集中有多少数据点(人)?
print len(enron_data)
output:146
安然数据集中的特征
对于每个人,有多少个特征可用?
for values in enron_data.values():
print len(values)
output:21
在安然数据中查找 POI
根据我们的定义,“POI”(Person of interest,嫌疑人)特征记录着一个人是否为相关人士的信息。
E+F 数据集中有多少 POI?
也就是说,计算 data[person_name]["poi"]==1 时,字典中条目的数量。
def find_poi(enron_data):
poi_num=0
for values in enron_data.values():
if values['poi']==1:
poi_num +=1
return poi_num
print find_poi(enron_data)
output:18
存在多少poi?
我们编辑了一个包含所有 POI 姓名的列表(在 ../final_project/poi_names.txt 中)并附上了相应的邮箱地址(在 ../final_project/poi_email_addresses.py 中)。
总共有多少 POI?(使用姓名列表,不要用邮箱地址,因为许多雇员不止一个邮箱,而且其中少数人员不是安然的雇员,我们没有他们的邮箱地址。)
with open('poi_names.txt','rb') as f:
poi_n=[name for name in f if "(n)" in name]
with open('poi_names.txt','rb') as f:
poi_y=[name for name in f if "(y)" in name]
print len(poi_n)+len(poi_y)
output:35
查询数据集
1.James Prentice 名下的股票总值是多少?
和任何字典的字典一样,个人/特征可以这样被访问:
enron_data["LASTNAME FIRSTNAME"]["feature_name"]
或者
enron_data["LASTNAME FIRSTNAME MIDDLEINITIAL"]["feature_name"]
名、中间名和姓全部大写。
print enron_data['PRENTICE JAMES']['total_stock_value']
2.我们有多少来自 Wesley Colwell 的发给嫌疑人的电子邮件?
print enron_data['COLWELL WESLEY']['from_this_person_to_poi']
3.Jeffrey Skilling 行使的股票期权价值是多少?
for x in enron_data.keys():
if 'skilling jeffrey' in x.lower():
print x
print enron_data['SKILLING JEFFREY K']['exercised_stock_options']
研究安然欺诈案
1.以下哪个计谋 Enron 未参与?
- 在每月月末将资产出售给空壳公司,然后在下月初买回,以隐藏会计损失
- 导致加利福尼亚的电网故障
- 非法获取了一份政府报告,使他们得以垄断冷冻浓缩橙汁期货
- 主谋为一位沙特公主快速获得了美国国籍
- 与百视达 (Blockbuster) 影业合作,在互联网上通过流媒体传播影片
2.欺诈案发生的多数时间内,安然的 CEO 是谁?
JEFFREY SKILLING
3.安然的董事会主席是谁?
ken lay
4.欺诈案发生的多数时间内,安然的 CFO(首席财务官)是谁?
andrew fastow
5.这三个人(Lay、Skilling 和 Fastow)当中,谁拿回家的钱最多(“total_payments”特征的最大值)?
这个人得到了多少钱?
for x in enron_data.keys():
if 'skilling jeffrey' in x.lower():
print x
for x in enron_data.keys():
if 'lay ken' in x.lower():
print x
for x in enron_data.keys():
if 'fastow andrew' in x.lower():
print x
print enron_data['SKILLING JEFFREY K']['total_payments']
print enron_data['LAY KENNETH L']['total_payments']
print enron_data['FASTOW ANDREW S']['total_payments']
未填充的特征
对于数据集中的所有人,不是每一个特征都有值。当特征没有明确的值时,我们使用什么来表示它?
NaN
处理未填充的特征
how many folks in this data set have a quantified salary?known email address?
def get_quantified_salary(enron_data):
num_quantified_salary = 0
for values in enron_data.values():
if values['salary'] !='NaN':
num_quantified_salary +=1
return num_quantified_salary
print get_quantified_salary(enron_data)
def get_known_email_address(enron_data):
num_known_email_address = 0
for values in enron_data.values():
if values['email_address'] !='NaN':
num_known_email_address +=1
return num_known_email_address
print get_known_email_address(enron_data)
有量化的工资的雇员数:95
有已知邮箱的雇员数:111
字典到数组的转换
不能将 python 字典直接读入到 sklearn 分类或回归算法中;它其实需要一个 numpy 数组,或者一个由列表组成的列表(此列表本身是一个列表,它的每个元素都是数据点,而较小列表的元素是该点的特征)。
我们编写了一些辅助函数(tools/feature_format.py 中的 featureFormat() 和 targetFeatureSplit()),它们可以获取特征名的列表和数据字典,然后返回 numpy 数组。
如果特征没有某个特定人员的值,此函数还会用 0(零)替换特征值。
缺少的POI(Person Of Interest)
1.(当前的)E+F 数据集中有多少人的薪酬总额被设置了“NaN”?数据集中这些人的比例占多少?
from __future__ import division
def get_nan_salary(enron_data):
num_nan_salary = 0
for values in enron_data.values():
if values['total_payments'] =='NaN':
num_nan_salary +=1
return num_nan_salary
print get_nan_salary(enron_data)
print len(enron_data)
print round(get_nan_salary(enron_data)/len((enron_data)),2)
2.E+F 数据集中有多少 POI 的薪酬总额被设置了“NaN”?这些 POI 占多少比例?
def get_poi_nan(enron_data):
num_poi = 0
num_poi_nan = 0
for values in enron_data.values():
if values['poi'] == True:
num_poi +=1
if values['total_payments']=='NaN':
num_poi_nan +=1
return(num_poi,num_poi_nan,round(num_poi_nan/num_poi,2))
print get_poi_nan(enron_data)
如果机器学习算法将 total_payments 用作特征,你希望它将“NaN”值关联到 POI 还是非 POI?
非poi
Because No training points would have "NaN" for total_payments when the class label is "POI"
如果你再次添加了全是 POI 的 10 个数据点,并且对这些雇员的薪酬总额设置了“NaN”,你刚才计算的数字会发生变化。
Now there are 156 folks in dataset, 31 of whom have "NaN" total_payments. This makes for 20% of them with a "NaN" overall.
变化前:
total:146 len(enron_data)
nan:21
def get_nan(enron_data):
num_nan = 0
for values in enron_data.values():
if values['total_payments'] =='NaN':
num_nan +=1
return num_nan
poi:18
def get_poi(enron_data):
num_poi = 0
for values in enron_data.values():
if values['poi'] ==1:
num_poi +=1
return num_poi
poi&nan:0
def get_poi_nan(enron_data):
num_poi_nan = 0
for values in enron_data.values():
if values['poi'] ==1 and values['total_payments'] =='NaN':
num_poi_nan +=1
return num_poi_nan
变化后:(变化即为向数据集中添加全是 POI 的 10 个数据点,并且对这些雇员的薪酬总额设置了“NaN”)
total:156
nan:31
poi:28
poi&nan:10
在添加了新的数据点后,可以认为,监督式分类算法可将 total_payments 为“NaN”理解为某人是 POI 的线索。
混合数据源
此例中加入了新的 POI,而我们没有任何人的财务信息,这就带来了一个微妙的问题,即算法可能会注意到我们缺少他们的财务信息,并将这一点作为他们是 POI 的线索。换个角度来看,为我们的两个类生成数据的方式现在有所不同 - 非 POI 的人全都来自财务电子表格,之后手动加入了许多 POI。这种不同可能会诱使我们以为我们的表现优于实际状况 - 假设你使用 POI 检测器来确定某个未见过的新人是否是 POI,而且该人不在电子表格上。然后,他们的所有财务数据都将包含“NaN”,但该人极有可能不是 POI(世界上非 POI 的人比 POI 多得多,即使在安然也是如此)- 然而你可能会无意中将他们标识为 POI!
这就是说,在生成或增大数据集时,如果数据来自不同类的不同来源,你应格外小心。它很容易会造成我们在此展示的偏差或错误类型。可通过多种方法处理此问题。举例而言,如果仅使用了电子邮件数据,则你无需担心此问题(在这种情况下,财务数据中的差异并不重要,因为并未使用财务特征)。还可以通过更复杂的方法来估计这些偏差可能会对你的最终答案造成多大影响,不过此话题超出了本课程的范围。
目前的结论就是,要非常小心地对待引入来自不同来源(具体取决于类)的特征这个问题!引入此类特征常常会意外地带来偏差和错误。