<jupyter_start><jupyter_text>项目: 机票航班延误预测 欢迎来到机票航班延误预测的实战项目！在此文件中，有些示例代码已经提供给你，但你还需要实现更多的功能让项目成功运行。除非有明确要求，你无须修改任何已给出的代码。以**'练习'**开始的标题表示接下来的代码部分中有你必须要实现的功能。每一部分都会有详细的指导，需要实现的部分也会在注释中以'TODO'标出。请仔细阅读所有的提示！除了实现代码外，你还必须回答一些与项目和你的实现有关的问题。每一个需要你回答的问题都会以**'问题 X'**为标题。请仔细阅读每个问题，并且在问题后的**'回答'**文字框中写出完整的答案。我们将根据你对问题的回答和撰写代码所实现的功能来对你提交的项目进行评分。>**提示：**Code 和 Markdown 区域可通过**Shift + Enter**快捷键运行。此外，Markdown可以通过双击进入编辑模式。  开始我们知道，航班延误对于旅客、售卖机票的平台以及航空公司都是一个比较头疼的问题。造成航班延误的因素有很多，包括台风、雾霾、飞机故障、航空管制等等原因。在这个项目中，我们将探索在飞机起飞前2小时做航班延误预测这个实际问题，你将从实际问题出发，探索数据，抽取数据特征，构建模型并作出预测。这个项目的数据来自[航班动态起降数据集](https://www.kesci.com/home/dataset/59793a5a0d84640e9b2fedd3)（数据集由和鲸社区提供），该数据集用2015年5月到2017年5月的机场情况作为训练集，用201年6月作为测试集。你可以通过报名该比赛获取数据集，另外，为了方便大家获取数据，我们也提供了一个[下载地址](https://static-documents.s3.cn-north-1.amazonaws.com.cn/nd101/MLND+documents/data.zip)，请下载后放置data文件夹中。**数据说明：**- ./data/2015年5月到2017年5月城市天气.csv- ./data/2015年5月到2017年5月航班动态数据.csv- ./data/2015年5月到2017年5月特情.xlsx- ./data/机场城市对应表.xlsx  运行下面区域的代码以载入一些此项目所需的Python库。如果成功返回提示语句，则说明载入成功。<jupyter_code># 为这个项目导入需要的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

print('你已经成功载入所需要的库！')<jupyter_output>你已经成功载入所需要的库！<jupyter_text>数据初探  导入数据我们先导入数据，然后观察头部数据。可以使用[read_csv](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html), [read_excel](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_excel.html) 分别加载对应格式的数据，然后使用[head](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.head.html)观察前5条数据。<jupyter_code># 文件路径 './data/2015年5月到2017年5月航班动态数据.csv'
# 注意使用字符编码 encoding="gb2312"
# TODO: 根据以上提示信息，导入航班数据
flight_data = pd.read_csv("./data/2015年5月到2017年5月航班动态数据.csv", encoding="gb2312")

# 文件路径 "./data/2015年5月到2017年5月城市天气.csv"
# TODO：根据以上提示信息，导入天气数据
weather = pd.read_csv("./data/2015年5月到2017年5月城市天气.csv", encoding="utf-8")

# 文件路径 "./data/机场城市对应表.xlsx"
# TODO：根据以上提示信息，导入城市与机场对应数据
airport_city = pd.read_excel("./data/机场城市对应表.xlsx", encoding="gb2312")

# 文件路径 "./data/2015年5月到2017年5月特情.xlsx"
# TODO：根据以上提示信息，导入特情数据
special = pd.read_excel("./data/2015年5月到2017年5月特情.xlsx", encoding="gb2312")<jupyter_output><empty_output><jupyter_text>观察数据使用 [head](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.head.html)观察前5条数据。<jupyter_code># 观察航班数据
flight_data.head()

# 观察天气数据
weather.head()

# 通过观察，发现有一列没有用的空表格 “Unnamed: 5”，你需要使用 `del` 将其从 `weather` 数据中删除
del weather["Unnamed: 5"]

# 观察城市与机场对应数据
airport_city.head()

# 观察特情数据
special.head()<jupyter_output><empty_output><jupyter_text>问题1：我们知道，一个有监督学习问题是总有一个需要预测的目标值，那么在这个问题中，你通过了解此问题的背景以及观察以上的数据，认为此任务中的目标值是什么？在已有的数据中，给出了预测目标值吗？如果没有的话，我们要如何获得这个目标值呢？回答问题：此问题的目标值是航班的延误时间或者航班是否延误；已有的数据，没有给出预测目标值；我们要通过2015年5月到2017年5月航班动态数据这个数据中的实际起飞时间和计划起飞时间的差值计算延误时间，或者通过通过这个差值是否大于0判断航班是否延误。  整理targets值根据以上对数据的初步观察，我们发现，这样的实际问题的数据是非常不规整的。数据的targets标签并没有显式地给出，而是需要自己整理。在这一小节，我们根据飞行数据 `flight_data` 整理出我们需要的targets。我们首先定义延误时间：实际起飞时间与计划起飞时间的差；然后，我们以延误时长是否超过3小时来定义targets。同时观察到“航班是否取消”这一列数据，针对数据中的“取消”的航班，我们直接可以将其延误时间设置成12小时。**建议**：用[numpy.where](https://numpy.org/devdocs/reference/generated/numpy.where.html?highlight=wherenumpy.where)按条件选择延误时间是否超过三小时，如果超过三小时则延误目标值取1，否则延误目标值取0；另外也用[numpy.where](https://numpy.org/devdocs/reference/generated/numpy.where.html?highlight=wherenumpy.where)按条件选择`flight_data['航班是否取消']`是否为 `取消`,如果是取消则直接可以将其延误时间设置成12小时。<jupyter_code># TODO：计算 起飞延误时间，以小时为单位，注意将单位秒转换为单位小时
flight_data['起飞延误时间'] = (flight_data['实际起飞时间'] - flight_data['计划起飞时间']) / 3600

# TODO：`light_data['航班是否取消']是否为 “取消”,如果是取消则直接可以将其延误时间设置成12小时
index_cancel = np.where(flight_data['航班是否取消'] == "取消")
flight_data.loc[index_cancel[0], '起飞延误时间'] = 12
flight_data["飞机延误目标"] = (flight_data['起飞延误时间'] > 3) * 1

flight_data.head()<jupyter_output><empty_output><jupyter_text>整理简单features在课程中，所讲解的案例使用的是比较干净的数据集，然而在真实业务场景里，却很少有直接可用的数据，我们往往需要从复杂的数据中提取重要的特征来帮助我们解决实际问题。正如当前所做的项目，我们无法直接使用所有数据，而是需要进行数据归并、删选、提取重要的特征。在整理完我们的目标值之后，我们可以开始进行特征工程。根据以上的几个文件，我们可以得到很多特征，在这里，我们先抽取一个简单的特征，学习一遍在处理实际数据时的特征工程流程。我们所抽取的特征是 `weather`中的“天气”数据。但我们发现 `weather` 中的数据并不是直接可用的，而是需要我们将该天气数据按照日期和城市对齐至飞行数据`flight_data`中。具体来说，我们参考下面的图片![merge_data](./figure/merge_feature.png)- 我们先要将天气 `weather`中的“城市”一列的数据，通过机场城市`airport_city`数据中的“城市名称”和“城市编码”，将 `weather`中的“城市”转化为“城市编码”，这样才能跟`flight_data`中的机场编码对应上。- 然后我们要将 `weather`中的“日期”一列的数据对齐至`flight_data`中“计划起飞时间”上。但是，我们发现“计划起飞时间”是以秒为单位的浮点格式数据，因此我们还需要将“计划起飞时间”转换成和`weather`中的“日期”一样的时间格式。接下来就是按以上的步骤进行操作 首先，利用 [merge](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html) ，按`airport_city`中的城市名称和城市编码，将 `weather`中的城市名称转化为城市编码。<jupyter_code># TODO: 将机场编码对应到天气数据上面，根据城市名，注意 weather 数据是【城市】，而 airport_city 是【城市名称】
airport_weather = weather.merge(airport_city, left_on='城市', right_on='城市名称')

# # 去除缺失值和重复的机场天气信息
airport_weather = airport_weather.dropna()
airport_weather = airport_weather.drop_duplicates(['日期','机场编码'])
airport_weather.head()<jupyter_output><empty_output><jupyter_text>我们发现，数据`airport_weather`中的“日期”格式和`flight_data`中的“计划起飞时间”格式是不一致的，为了能够将机场天气数据`airport_weather`按照“日期”归并至飞行数据`flight_data`中，我们首先需要将`flight_data`中的“计划起飞时间”格式转化成年月日统一格式。可以先用[to_datetime](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.to_datetime.html)将浮点类型的数据转化为日期格式，然后再将日期格式的数据转化为 统一的 年月日格式。<jupyter_code># TODO：利用 to_datetime  浮点类型的数据转化为时间数据，单位为秒，utc时间为True
flight_data['计划起飞日期tmp'] = pd.to_datetime(flight_data["计划起飞时间"], utc=True, unit = 's')

# 再将日期格式的数据转化为 统一的 年月日格式。
flight_data['计划起飞日期'] = flight_data['计划起飞日期tmp'].apply(lambda x:x.strftime('%Y-%m-%d') if not(pd.isnull(x)) else None)
flight_data.head()<jupyter_output><empty_output><jupyter_text>然后，再次利用[merge](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html)，根据机场名称和日期信息，将机场天气`weather`数据对应到飞行数据 `flight_data` 中。注意，`flight_data`中是“出发机场”和“计划起飞日期”,而 `airport_weather`中对应的是“机场编码”和“日期”。<jupyter_code># TODO: merge flight_data 和 airport_weather
flight_data = flight_data.merge(airport_weather, left_on = ["出发机场", "计划起飞日期"], right_on = ["机场编码", "日期"])
flight_data.head()<jupyter_output><empty_output><jupyter_text>建立简单模型 特征处理我们可以先建立一个最简单的模型，从飞行数据`flight_data`中挑选2列数据作为features，其中一个是我们刚刚构造好的“天气”数据，另外一个feature由你来选择。注意，其中“飞机延误时间”和“飞机延误目标”并不是feature，而是targets，所以不能选择这两列作为features。 问题2：你选择的特征是特征是什么？说说你选择这个feature的理由。回答问题：我选择的特征是机场编码，因为机场的起飞地点也会影响飞机是否延误，同样的天气，不同的机场，可能飞机的延误状况不相同。<jupyter_code># TODO: 选择一列数据作为feature
features = ["天气"]
add_to_feature =  '机场编码' # 你选择的feature
features.append(add_to_feature)
data = flight_data[features]

data.head()

# TODO：从 flight_data 中取出目标"飞机延误目标"的值，numpy格式的值
targets = flight_data["飞机延误目标"].values

# train_data 的数据量和 targets 的数据量一定是相等的
assert len(data) == len(targets)<jupyter_output><empty_output><jupyter_text>到这里，我们已经提取完并得到两个特征，但是现在的特征是非数值类型的，那么我们需要先对这些非数值类型的特征进行编码。从上面的**数据探索**中的表中，我们可以看到有几个属性的每一条记录都是非数字的。通常情况下，学习算法期望输入是数字的，这要求非数字的特征（称为类别变量）被转换。转换类别变量的一种流行的方法是使用**独热编码**方案。独热编码为每一个非数字特征的每一个可能的类别创建一个_“虚拟”_变量。例如，假设`someFeature`有三个可能的取值`A`，`B`或者`C`，。我们将把这个特征编码成`someFeature_A`, `someFeature_B`和`someFeature_C`.| 特征X |                    | 特征X_A | 特征X_B | 特征X_C || :-: |                            | :-: | :-: | :-: ||  B  |  | 0 | 1 | 0 ||  C  | ----> 独热编码 ----> | 0 | 0 | 1 ||  A  |  | 1 | 0 | 0 |因此，**独热编码**将会对特征进行扩维，例如上面对例子，将对单个特征`someFeature` 扩充成3个特征`someFeature_A`, `someFeature_B`和`someFeature_C`，这种独热编码，你可以参考one-hot[get_dummies](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html) 解释和实现以及使用。另一种对非数值类型对特征进行编码对方法是直接对字符编号，例如 `someFeature` 由 1.0、2.0、3.0 来作为特征值进入模型对计算。更进一步来说，这种方法如果类型比较多对话，将会导致特征空间太离散，影响模型对建模性能。于是我们需要对这些数值进行归一化，针对该问题，在我们实际业务场景中经常使用对解决方案是使用的编码方式是 [sklearn.preprocessing.LabelEncoder.fit_transform](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.htmlsklearn.preprocessing.LabelEncoder.fit_transform)，它会将离散的字符映射到一个数值，用以表示该特征并参与模型计算。 问题3：请参考文档简单介绍一下 `LabelEncoder.fit_transform`，说一下该方法和独热表示one-hot[get_dummies](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html)有什么区别，并根据刚刚构造好对`天气`特征包含对类别数量等统计信息来回答这里为什么用 `fit_transform`？回答问题：`LabelEncoder.fit_transform` 是对不连续的数字或者文本进行编号，将各种标签分配一个可数的连续编号。两个方法的区别是：get_dummies方法返回的为数据框，OneHotEncoder方法返回的为数组。sklearn.preprocessing下的OneHotEncoder不可以直接处理string，如果数据集中的某些特征是string类型的话，需要首先将其转换为integers类型。在本题中，"天气"特征的类别很多，当类别的数量很多时，如果使用get_dummies方法，特征空间会变得非常大。并且，如果测试集中出现了训练集未曾出现过的特征取值，简单地对测试集、训练集都用get_dummies方法将导致数据错误。因此本题中用`fit_transform`方法。 判断数据中是否存在缺省值的情况，如果存在，请处理缺省值。建议，你可以通过 `any(isnull())`[isnull](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.isnull.html)去判断数据中是否存在缺失情况；然后通过[fillna](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html)去填补缺省值<jupyter_code># TODO：判断并处理`data`中的缺省值
missing_condition = data.isnull().values.any()
data = data.fillna(method = 'pad')
from sklearn import preprocessing
string_encoder = preprocessing.LabelEncoder()
# 我们首先对天气特征的进行编码
data["天气"] = string_encoder.fit_transform(data["天气"])

# TODO：对你选择的特征进行编码，如果你选择的是数值类型的特征，那么你可以按照前面所学知识进行归一化等处理
data[add_to_feature] = string_encoder.fit_transform(data[add_to_feature])<jupyter_output><empty_output><jupyter_text>模型构建现在我们可以根据上面构造好的feature和target来构建一个简单的模型。- 第一步：使用`sklearn.model_selection.train_test_split`按**0.2**的测试比例切分训练集和测试集；- 第二步：继续使用`sklearn.model_selection.train_test_split`按**0.2**的测试比例切分训练集和测试集；<jupyter_code># 导入 train_test_split
from sklearn.model_selection import train_test_split

# 将'data'和'targets'数据切分成训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(data, targets, test_size = 0.2, random_state = 0)

# 将'X_train'和'y_train'进一步切分为训练集和验证集
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=0)

# 显示切分的结果
print ("Training set has {} samples.".format(X_train.shape[0]))
print ("Validation set has {} samples.".format(X_val.shape[0]))
print ("Testing set has {} samples.".format(X_test.shape[0]))<jupyter_output>Training set has 4733699 samples.
Validation set has 1183425 samples.
Testing set has 1479282 samples.<jupyter_text>监督学习模型 模型应用你能够在 [`scikit-learn`](http://scikit-learn.org/stable/supervised_learning.html) 中选择以下监督学习模型- 高斯朴素贝叶斯 (GaussianNB)- 决策树 (DecisionTree)- 集成方法 (Bagging, AdaBoost, Random Forest, Gradient Boosting)- K近邻 (K Nearest Neighbors)- 随机梯度下降分类器 (SGDC)- 支撑向量机 (SVM)- Logistic回归（LogisticRegression） 问题4: 从上面的监督学习模型中选择两个适合我们这个问题的模型，并回答相应问题。然后从中选择一个先在我们等数据集上进行训练和测试，这一步是为了初步感受模型在此数据集上等表现。  模型1**模型名称**回答：决策树**描述一个该模型在真实世界的一个应用场景。（你需要为此做点研究，并给出你的引用出处）**回答：在真实世界中，可以根据电商客户的购买数据，用决策树判定顾客对商品购买能力。引用出处：https://www.cnblogs.com/baiboy/p/ml3.html**这个模型的优势是什么？他什么情况下表现最好？**回答： 模型优势：①决策树易于理解和实现；②对于决策树，数据预处理过程简单；③能够同时处理数据型和常规型属性，其他的技术往往要求数据属性的单一；④在相对短的时间内能够对大型数据源做出可行且效果良好的结果；⑤对缺失值不敏感；⑥可以处理不相关特征数据；⑦效率高，决策树只需要一次构建，反复使用。决策树在数据不连续的情况下表现的最好。**这个模型的缺点是什么？什么条件下它表现很差？**回答：模型缺点：①对连续性的字段比较难预测；②对有时间顺序的数据，需要很多预处理的工作；③当类别太多时，错误可能就会增加的比较快；⑤在处理特征关联性比较强的数据时表现得不是太好；⑥容易过拟合；⑦对于那些各类别样本数量不一致的数据，在决策树当中信息增益的结果偏向于那些具有更多数值的特征。决策树在数据连续，类别很多，各类别样本数量差异很大的情况下表现很差。**根据我们当前数据集的特点，为什么这个模型适合这个问题。**回答：当前数据集的点不连续，类别不多，因此决策树模型适合这个问题。  模型2**模型名称**回答：支持向量机**描述一个该模型在真实世界的一个应用场景。（你需要为此做点研究，并给出你的引用出处）**回答：支持向量机可以应用于人脸识别，人脸识别技术是一种采用计算机分析人脸图像， 从中提取出有效的识别信息，用来“辨认”身份的一门技术。引用出处：https://blog.csdn.net/weixin_43795395/article/details/88729251**这个模型的优势是什么？他什么情况下表现最好？**回答：优势： ①适合小数量样本数据；②可以解决高维问题；③理论基础比较完善；④支持向量机学习问题可以表示为凸优化问题，因此可以利用已知的有效算法发现目标函数的全局最小值。而其他分类方法（如基于规则的分类器和人工神经网络）都采用一种基于贪心学习的策略来搜索假设空间，这种方法一般只能获得局部最优解；⑤泛化错误率低，分类速度快，结果易解释。支持向量机在小样本、缺失数据少的情况下表现最好。**这个模型的缺点是什么？什么条件下它表现很差？**回答：缺点：①支持向量机模型对大规模训练样本难以实施；②用支持向量机模型解决多分类问题存在困难；③对缺失数据敏感，对参数和核函数的选择敏感。支持向量机在样本很大、需要多分类、缺失数据多的条件下表现很差。**根据我们当前数据集的特点，为什么这个模型适合这个问题。**回答：当前数据集不是多分类问题，样本不大，适合用支持向量机模型解决问题。  评价模型性能在这一部分中，我们选择上面两个模型之一来训练。在这个，分类预测问题中，我们使用**准确率**作为评价模型等标准，同时能够使用**F-beta score**作为评价指标，这样能够同时考虑查准率和查全率：$$ F_{\beta} = (1 + \beta^2) \cdot \frac{precision \cdot recall}{\left( \beta^2 \cdot precision \right) + recall} $$尤其是，当 $\beta = 0.5$ 的时候更多的强调查准率，这叫做**F$_{0.5}$ score** （或者为了简单叫做F-score）。由于数据量比较大，模型训练可能需要一些时间来运行！<jupyter_code># TODO：从sklearn中导入两个评价指标 - fbeta_score和accuracy_score
from sklearn.metrics import fbeta_score, accuracy_score

# TODO：从sklearn中导入上面你选择等一个监督学习模型
from sklearn.tree import DecisionTreeClassifier

# TODO：设置模型参数，初始化这个模型
clf = DecisionTreeClassifier()

# TODO：在训练集 X_train, y_train 上训练该模型
clf = clf.fit(X_train,y_train)

# TODO：在验证集 X_val, y_val 上预测并计算socre fbeta_score和accuracy_score
y_pred = clf.predict(X_val)
f_score = fbeta_score(y_val, y_pred, beta=0.5)
acc = accuracy_score(y_val, y_pred)

# 打印 fbeta_score和accuracy_score
print("Train and valid successed. F-score: {}, Acc: {}".format(f_score, acc))<jupyter_output>Train and valid successed. F-score: 0.09800733657822804, Acc: 0.9274892789995142<jupyter_text>问题5： 用通俗的话解释模型*用一到两段话，用外行也听得懂的话来解释最终模型是如何工作的。你需要解释所选模型的主要特点。例如，这个模型是怎样被训练的，它又是如何做出预测的。避免使用高级的数学或技术术语，不要使用公式或特定的算法名词。*回答问题：决策树通过if-then规则进行分类，从决策树的根结点到叶节点每一条路径构建一个规则，路径上的内部结点的特征对应着规则的条件，而叶节点的类对应着规则的结论。构建方法是，从根结点开始，对数据中的某一特征进行测试，根据测试结果，将实例分配到其子结点，这时，每一个子结点对应着该特征的一格取值，这样递归地对数据进行测试并且分配，直至达到叶节点。  练习：模型调优调节选择的模型的参数。使用网格搜索（GridSearchCV）来至少调整模型的重要参数（至少调整一个），这个参数至少需尝试3个不同的值。你要使用整个训练集来完成这个过程。在接下来的代码单元中，你需要实现以下功能：- 导入[`sklearn.model_selection.GridSearchCV`](http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html) 和 [`sklearn.metrics.make_scorer`](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.make_scorer.html).- 初始化你选择的分类器，并将其存储在`clf`中。 - 设置`random_state` (如果有这个参数)。- 创建一个对于这个模型你希望调整参数的字典。 - 例如: parameters = {'parameter' : [list of values]}。 - **注意：** 如果你的学习器有 `max_features` 参数，请不要调节它！- 使用`make_scorer`来创建一个`fbeta_score`评分对象（设置$\beta = 0.5$）。- 在分类器clf上用'scorer'作为评价函数运行网格搜索，并将结果存储在grid_obj中。- 用训练集（X_train, y_train）训练grid search object,并将结果存储在`grid_fit`中。**注意：** 取决于你选择的参数列表，下面实现的代码可能需要花一些时间运行！<jupyter_code># TODO：导入'GridSearchCV', 'make_scorer'和其他一些需要的库
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import make_scorer

# TODO：初始化分类器
clf = DecisionTreeClassifier(random_state = 0)

# TODO：创建你希望调节的参数列表
parameters = {'max_depth': np.arange(3, 20)}

# TODO：创建一个fbeta_score打分对象
scorer = make_scorer(fbeta_score, beta = 0.5)

# TODO：在分类器上使用网格搜索，使用'scorer'作为评价函数
grid_obj = GridSearchCV(estimator = clf, param_grid = parameters, scoring = scorer, cv = 3)

# TODO：用训练数据拟合网格搜索对象并找到最佳参数
grid_obj.fit(X_train, y_train)

# 得到estimator
best_clf = grid_obj.best_estimator_

# 使用没有调优的模型做预测
predictions = (clf.fit(X_train, y_train)).predict(X_val)
best_predictions = best_clf.predict(X_val)<jupyter_output>D:\Anaconda\lib\site-packages\sklearn\metrics\classification.py:1437: UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 due to no predicted samples.
  'precision', 'predicted', average, warn_for)
D:\Anaconda\lib\site-packages\sklearn\metrics\classification.py:1437: UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 due to no predicted samples.
  'precision', 'predicted', average, warn_for)
D:\Anaconda\lib\site-packages\sklearn\metrics\classification.py:1437: UndefinedMetricWarning: F-score is ill-defined and being set to 0.0 due to no predicted samples.
  'precision', 'predicted', average, warn_for)<jupyter_text>特征重要性分析在做数据分析过程中，我们需要分析抽取出来的特征对预测的贡献，以得出特征的重要性。特征重要性分析能够帮助我们继续进行相关的特征工程，比如过滤一些没有贡献的特征，加强一些比较重要的特征。选择一个`scikit-learn`中有`feature_importance_`属性的监督学习分类器，这个属性是一个在做预测的时候根据所选择的算法来对特征重要性进行排序的功能。在下面的代码单元中，你将要实现以下功能： - 如果这个模型和你前面使用的三个模型不一样的话从sklearn中导入一个监督学习模型。 - 在整个训练集上训练一个监督学习模型。 - 使用模型中的 `'feature_importances_'`提取特征的重要性。<jupyter_code># TODO：导入一个有'feature_importances_'的监督学习模型
from sklearn.tree import DecisionTreeClassifier

# TODO：在训练集上训练一个监督学习模型，初始化
model = DecisionTreeClassifier()

# TODO: fit 训练集
model.fit(X_train,y_train)

import matplotlib.pyplot as plt
features = ["weather", "airport_code"]

feature_important = model.feature_importances_
plt.figure(figsize=(12,8))
plt.bar(np.arange(len(features)),feature_important)
plt.xticks(np.arange(len(features)),features,fontsize=12,rotation=10)
plt.show()<jupyter_output><empty_output><jupyter_text>问题6：哪一个特征更加重要？这符合你的直觉吗？谈谈你在平时的项目中在做特征工程时，对于使用符合直觉的特征的看法，可以举例说明。回答问题：“weather”特征更重要，这个符合我的直觉，相比机场地点，天气对航班延误情况的影响更大。我平常用股票因子去预测股票收益率的时候，非常注重用符合直觉，能用经济学和统计学原理解释的因子，因为这样的模型相对更稳定，样本外的表现容易更稳定，如果某个因子在不同时间段的表现出现了变化，也能直觉上知道股票投资组合大概的变化方向。  模型对比目前为止，我们已经对一个实际问题的复杂的数据进行了处理，并抽取了一两个特征，然后进行了模型训练。你可以按照这个流程做更多的特征工程的工作。由于数据量大，我们已经做好了特征工程，同时我们也sample了部分数据，方便接下来对不同模型进行比较。这一小节，我们要学习在具体业务场景经常使用的模型，梯度提升决策树 （Gradient Boosting Decison Tree，GBDT）。GBDT在工业场景和各大数据挖掘比赛中都是非常流行的模型，在这里，我们尝试对这些流行对模型进行初探。  问题7：通俗的解释什么是 梯度提升决策树 （Gradient Boosting Decison Tree，GBDT）？并列举其优缺点。回答问题：  问题8：目前比较流行的 `GBDT`的变种有 [Xgboost](https://xgboost.readthedocs.io/en/latest/) 和 [LightGBM](https://lightgbm.readthedocs.io/en/latest/)，请比较这三个梯度提升模型，列举他们各自的特点? （你可以参考一些文档，并给出你的引用出处）回答问题： 我们已经预先对该数据做了充分的特征工程，然后 `sample` 出了部分数据。数据在路径 `./data/`下面，有训练集`train.csv`和测试集`test.csv`<jupyter_code># 直接运行读取数据，并分别得到 X 和 Y 的数据

# 处理训练集
train_x = pd.read_csv("./data/train.csv")
train_y = train_x["飞机延误目标"].values
del(train_x["飞机延误目标"])
# 处理测试集
test_x = pd.read_csv("./data/test.csv")
test_y = test_x["飞机延误目标"].values
del(test_x["飞机延误目标"])<jupyter_output><empty_output><jupyter_text>对 gbdt 进行调参按照上面简单模型构建部分的流程，先定义一个梯度提升决策树分类器 GradientBoostingClassifier，并设置里面固定参数；然后设置需要调优的参数，然后通过 网格搜索 `GridSearchCV` 进行搜索最优参数。由于数据量已经减少，这里你可以将参数设置的大一些，以提升模型的准确度，但要防止过拟合。<jupyter_code>from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import GridSearchCV
from sklearn import metrics



# TODO: 需要调的参数，比如 max_depth, n_estimators, learning_rate
cv_params = 


#TODO：设置 GBDT 分类器 GradientBoostingClassifier
model = 
# TODO: 设置 GridSearchCV
grid_cv = 
# TODO: 模型训练
grid_cv.fit(train_x, train_y)

# TODO：在测试集上预测，并计算accuracy和f-score


# TODO：打印最优参数<jupyter_output><empty_output><jupyter_text>对 Xgboost 进行调参关于xgboost 的参数设置和调参与gbdt类似，参数也是类似的，比如 `n_estimators`表示树的个数；`max_depth`表示构建树的深度，越大越容易过拟合；`gamma`表示用于控制是否后剪枝的参数；`reg_lambda`是用来控制模型复杂度的L2正则化的参数，值越大，模型越不容易过拟合，等等。由于数据量已经减少，这里你可以将参数设置的大一些，以提升模型的准确度，但要防止过拟合。如果没有安装过xgboost，你需要先运行以下代码来安装 xgboost<jupyter_code>!pip install xgboost
### 使用Xgboost 进行训练和测试
import xgboost as xgb


# TODO: 选择要调优的参数, 比如max_depth, n_estimator,learning_rate
cv_params =
model = 

grid_cv = 
grid_cv.fit(train_x, train_y)


# TODO：在测试集上预测，并计算准确率

# TODO：预测测试集的结果
predict_y = 
# TODO：计算 准确率

auc=
# 打印准确率结果
print("准确率：{}".format(auc))

# TODO：打印最优参数<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1305302448128225, 'fraction_numerical': 0.018278625535184983, 'mean_word_length': 11.146, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 65, 'https://': 20, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '152709', 'license': 'MIT', 'n_tokens_mistral': 11659, 'n_tokens_neox': 12986, 'n_words': 671, 'path': 'FlightDelayForecast/FlightDelayForecast.ipynb', 'repo_name': 'sandrawing/Udacity_Machine-Learning-Engineer', 'size': '18218'}