Python scikit-learn,交叉验证,网格搜索,GridSearchCV,自动调参调优

交叉验证的目的:为了让被评估的模型更加准确可信

这里的验证是训练的一部分,和测试集无关。 


demo.py(K近邻分类算法,交叉验证,网格搜索,GridSearchCV):

import pandas as pd
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler


# K近邻算法,预测用户入住哪个酒店

# 读取数据
data = pd.read_csv("./data/FBlocation/train.csv")
# print(data.head(3))
'''
row_id    x      y    accuracy   time     place_id
   0   0.7941  9.0809    54     470702   8523065628
   1   5.9567  4.7968    13     186555   1757726713
   2   8.3078  7.0407    74     322648   1137537235
x,y表示入住用户的位置坐标,accuracy表示定位的准确度,time表示入住时间,place_id表示入住的酒店(目标值)
'''

# 处理数据
# 1、缩小数据量。 (截取某地理范围内的数据,减少数据量和计算时间,实际应用中可以根据情况忽略这一步)
data = data.query("x>1.0 & x<1.25 & y>2.5 & y<2.75")  # query()根据条件筛选数据。

# 2、处理时间戳。 (将时间戳字符串转换成年、月、日、周、时、分、秒等的形式)
time_value = pd.to_datetime(data['time'], unit='s')  # unit转换的最小单位(s:秒)
print(time_value)
'''
600   1970-01-01 18:09:40
957   1970-01-01 02:11:10
...                  ...
Name: time, Length: 17710, dtype: datetime64[ns]
'''

# 把日期格式转换成字典格式(方便获取年、月、日、时、分、秒等)
time_value = pd.DatetimeIndex(time_value)

# 构造一些新特征 (根据情况增加新特征)
data['day'] = time_value.day
data['hour'] = time_value.hour
data['weekday'] = time_value.weekday

# 把时间戳特征删除
data = data.drop(['time'], axis=1)
print(data)
'''
row_id    x       y    accuracy   day   hour  weekday   place_id
  600   1.2214  2.7023    17       1     18     3      6683426742
  957   1.1832  2.6891    58      10      2     5      6683426742
  4345  1.1935  2.6550    11       5     15     0      6889790653
 ...                                                         ...
'''

# 3、把入住数量少于n个用户的酒店数据删除
place_count = data.groupby('place_id').count()
tf = place_count[place_count.row_id > 3].reset_index()  # bool索引,保留count大于3的数据。 reset_index()表示重新设置索引(从0开始的索引)
data = data[data['place_id'].isin(tf.place_id)]  # bool索引,保留入住数大于3的数据。(isin()表示是否在)

# 取出数据当中的特征值和目标值
y = data['place_id']  # 目标值
x = data.drop(['place_id'], axis=1)  # 特征值 (可以考虑把不相关的row_id数据删除)

# 进行数据的分割。划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)  # 25%的数据作为测试集。(推荐0.25)

# 特征工程(特征标准化)
std = StandardScaler()
# 对训练集和测试集的特征值进行标准化
x_train = std.fit_transform(x_train)
x_test = std.transform(x_test)  # fit()填充数据,transform()转换数据。当填充数据后就不需要重新填充了(不会重新计算均值和标准差)。 标准化使用的均值和标准差取决于fit()填充的数据。


# 进行K近邻算法的算法流程
# knn = KNeighborsClassifier(n_neighbors=5)  # 超参数n_neighbors(表示K近邻中的K值)
knn = KNeighborsClassifier()  # 如果用交叉验证和网格搜索进行参数调优,就不需要手动指定超参数。


# 构造一些参数的值进行搜索 (字典类型,可以有多个参数)
param = {"n_neighbors": [3, 5, 10]}

# 进行交叉验证和网格搜索(自动进行调参调优)
gc = GridSearchCV(knn, param_grid=param, cv=2)  # cv=2表示2折交叉验证(推荐10折交叉验证)

gc.fit(x_train, y_train)  # 填充训练数据

# 预测准确率
print("在测试集上准确率:", gc.score(x_test, y_test))  # 0.432624113475

print("在交叉验证当中最好的结果:", gc.best_score_)  # 0.390684110971 并没有使用测试集。(验证集是从训练集中分的)

print("选择最好的模型是:", gc.best_estimator_)  # KNeighborsClassifier(algorithm="auto", n_neighbors=10)

print("每个超参数每次交叉验证的结果:", gc.cv_results_)
'''
{"split0_test_score": array([0.344, 0.362, 0.386]), 
 "split1_test_score": array([0.353, 0.373, 0.394]), 
 "mean_test_score": array([0.348, 0.367, 0.390]), 
 "params": ({'n_neighbors': 3}, {'n_neighbors': 5}, {'n_neighbors': 10})}
'''

猜你喜欢

转载自blog.csdn.net/houyanhua1/article/details/87974469