"""
网格搜索:
指的是 GridSearchCV这个工具的功能, 可以帮助我们寻找最优的 超参数.
超参数解释:
在机器学习中, 我们把需要用户手动传入的参数称之为: 超参数.
交叉验证:
指的是对数据集进行划分, 即: 把数据分成N份进行验证
第1次: 第1份是 验证集(测试集), 其它是训练集, 得出: 模型的预估正确率
第2次: 第2份是 验证集(测试集), 其它是训练集, 得出: 模型的预估正确率
......
第n次: 第n份是 验证集(测试集), 其它是训练集, 得出: 模型的预估正确率
最终计算所有正确率的平均值, 结合网格搜索, 找到最优参数组合.
回顾: 机器学习的建模流程.
1. 加载数据.
2. 数据预处理.
3. 特征工程.
4. 模型训练.
5. 模型预测.
6. 模型评估.
"""
# 导包
from sklearn.datasets import load_iris # 加载鸢尾花测试集的.
from sklearn.model_selection import train_test_split, GridSearchCV # 分割训练集和测试集的, 网格搜索 => 找最优参数组合
from sklearn.preprocessing import StandardScaler # 数据标准化的
from sklearn.neighbors import KNeighborsClassifier # KNN算法 分类对象
from sklearn.metrics import accuracy_score # 模型评估的, 计算模型预测的准确率
# 1. 加载数据.
iris_data = load_iris()
# 2. 数据预处理, 即: 划分 训练集, 测试集.
x_train, x_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target, test_size=0.2, random_state=21)
# 3. 特征工程, 即: 特征的预处理 => 数据的标准化.
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train) # 训练 + 转换 => 适用于: 训练集.
x_test = transfer.transform(x_test) # 直接转换 => 适用于: 测试集.
# 4. 模型训练.
# 4.1 创建 估计器对象.
estimator = KNeighborsClassifier()
# 4.2 定义网格搜索的参数, 即: 样本可能存在的参数组合值 => 超参数.
param_dict = {'n_neighbors': [1, 2, 3, 5, 7]}
# 4.3 创建网格搜索对象, 帮我们找到最优的参数组合.
# 参1: 估计器对象, 传入1个估计器对象, 网格搜索后, 会自动返回1个功能更加强大(最优参数)的 估计器对象.
# 参2: 网格搜索的参数, 传入1个字典, 键: 参数名, 值: 参数值列表.
# 参3: 交叉验证的次数, 指定值为: 4
estimator = GridSearchCV(estimator, param_dict, cv=5)
# 4.4 调用 估计器对象的 fit方法, 完成模型训练.
estimator.fit(x_train, y_train)
# 4.5 查看网格搜索后的参数
print(f'最优组合平均分: {estimator.best_score_}')
print(f'最优估计器对象: {estimator.best_estimator_}') # 3
print(f'具体的验证过程: {estimator.cv_results_}')
print(f'最优的参数: {estimator.best_params_}')
# 5. 得到超参数最优值之后, 再次对模型进行训练.
estimator = KNeighborsClassifier(n_neighbors=3)
# 模型训练
estimator.fit(x_train, y_train)
# 模型评估
print(estimator.score(x_test, y_test)) # 0.9666666666666667