#---------------------------config文件夹----------------------
import os
import pandas as pd
# 数据集路径
dataset_path = './data'
# 输出集路径
output_path = './output'
if not os.path.exists(output_path):
os.makedirs(output_path)
#数字数值列
numeric_cols=['battery_power','clock_speed','fc','int_memory','m_dep','mobile_wt',
'n_cores','pc','px_height','px_width','ram','sc_h','sc_w','talk_time']
#类别数值列 这类是 bool类型的,即是0者来表示的,即是或者否,就用one-hot编码表示成数值型的
cat_cols=['blue', 'dual_sim', 'four_g', 'three_g', 'touch_screen', 'wifi']
#要使用的特征列
feat_cols=numeric_cols+cat_cols
#标签列
label_col='price_range'
#下面只是为了获得行名而已,是辅助的作用
ttt=pd.read_csv('./data/data.csv')
print(ttt.iloc[:0])
data = [[1,2,3],[4,5,6]]
index = ['d','e']
columns=['a','b','c']
df = pd.DataFrame(data=data, index=index, columns=columns)
print (df)
print (df.iloc[:,0])
#---------------------------main.py文件夹---------------------------
'''
任务描述
建立不同的集成学习模型来进行手机的价格的预测
并使用交叉验证的方式为每个模型选择最优化的超参数
'''
import config
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import time
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.ensemble import AdaBoostClassifier, GradientBoostingClassifier, RandomForestClassifier
from mlxtend.classifier import StackingClassifier
from sklearn.model_selection import GridSearchCV
def main():
#加载数据
all_data=pd.read_csv(os.path.join(config.dataset_path,'data.csv'))
train_data,test_data=train_test_split(all_data,test_size=1/3, random_state=10)
#数据查看
inspect_dataset(train_data,test_data)
#构建训练测试数据
#特征处理
x_train,x_test=do_feature_engineering(train_data,test_data)
print('共有{}维特征'.format(x_train.shape[1]))
#标签处理
y_train=train_data[config.label_col].values
y_test=test_data[config.label_col].values
#数据建模以及验证 很多模型放到一块
print('================数据建模以及验证=================')
sclf=StackingClassifier(classifiers=[KNeighborsClassifier(), #基分类器
SVC(kernel='linear'), #基分类器
DecisionTreeClassifier()],#基分类器
meta_classifier=LogisticRegression()) #提取基分类器权重
# model_name_param_dict={'KNN':(KNeighborsClassifier(),{'n_neighbors':[5,25,55]}),
# 'LR':(LogisticRegression(),{'c':[0.01,1,100]}),
# 'SVM':(SVC(kernel='linear'),{'c':[0.01,1,100]}),
# 'DT':(DecisionTreeClassifier(),{'max_depth':[50,100,150]}),
# 'Stacking':(sclf,{'kneighborsclassifier__n_neighbors': [5, 25, 55],
# 'svc_C': [0.01, 1, 100],
# 'decisiontreeclassifier__max_depth': [50, 100, 150],
# 'meta-logisticregression__C': [0.01, 1, 100]}),
# 'AdaBoost': (AdaBoostClassifier(),
# {'n_estimators': [50, 100, 150, 200]}),
# 'GBDT': (GradientBoostingClassifier(),
# {'learning_rate': [0.01, 0.1, 1, 10, 100]}),
# 'RF': (RandomForestClassifier(),
# {'n_estimators': [100, 150, 200, 250]})
# }
#对分类器指定超参数
model_name_param_dict = {'kNN': (KNeighborsClassifier(),
{'n_neighbors': [5, 25, 55]}),
'LR': (LogisticRegression(),
{'C': [0.01, 1, 100]}),
'SVM': (SVC(kernel='linear'),
{'C': [0.01, 1, 100]}),
'DT': (DecisionTreeClassifier(),
{'max_depth': [50, 100, 150]}),
'Stacking': (sclf,
{'kneighborsclassifier__n_neighbors': [5, 25, 55], #注意拼写别错了
'svc__C': [0.01, 1, 100],
'decisiontreeclassifier__max_depth': [50, 100, 150],
'meta-logisticregression__C': [0.01, 1, 100]}),
'AdaBoost': (AdaBoostClassifier(),
{'n_estimators': [50, 100, 150, 200]}), #分类器的个数
'GBDT': (GradientBoostingClassifier(),
{'learning_rate': [0.01, 0.1, 1, 10, 100]}),
'RF': (RandomForestClassifier(),
{'n_estimators': [100, 150, 200, 250]})} #树的个数
# 比较结果的DataFrame
#新建一个空的dataframe用于存放个模型的时间准确度
results_df = pd.DataFrame(columns=['Accuracy (%)', 'Time (s)'],
index=list(model_name_param_dict.keys()))
results_df.index.name = 'Model'
for model_name, (model, param_range) in model_name_param_dict.items():
best_clf, best_acc, mean_duration = train_model(x_train, y_train, x_test, y_test,
model_name, model, param_range)
results_df.loc[model_name, 'Accuracy (%)'] = best_acc * 100
results_df.loc[model_name, 'Time (s)'] = mean_duration
results_df.to_csv(os.path.join(config.output_path, 'model_comparison.csv'))
# 模型及结果比较
print('\n===================== 模型及结果比较 =====================')
plt.figure(figsize=(10, 4))
ax1 = plt.subplot(1, 2, 1)
#注意下面的绘制图像的简单的方法,可以直接dataframe类型的.plot
results_df.plot(y=['Accuracy (%)'], kind='bar', ylim=[50, 100], ax=ax1, title='Accuracy(%)', legend=False)
ax2 = plt.subplot(1, 2, 2)
results_df.plot(y=['Time (s)'], kind='bar', ax=ax2, title='Time (s)', legend=False)
plt.tight_layout()
plt.savefig(os.path.join(config.output_path, './pred_results.png'))
plt.show()
def inspect_dataset(train_data,test_data):
'''
查看数据集
'''
print('=====================数据查看====================')
print('训练集共有{}条数据'.format(len(train_data)))
print('测试集共有{}条数据'.format(len(test_data)))
#可视化个类别的数量统计图
plt.figure(figsize=(10,5))
#训练集
ax1=plt.subplot(1,2,1)
sns.countplot(x='price_range',data=train_data) #统计train_data总数据中price_range列中每个每个数字的个数
plt.title('Training_Data')
# plt.xticks(rotation='vertical')
plt.xlabel('Price Range')
plt.ylabel('Count')
#测试集
ax1=plt.subplot(1,2,2,sharey=ax1)
sns.countplot(x='price_range',data=test_data) #统计train_data总数据中price_range列中每个每个数字的个数
plt.title('Test_Data')
# plt.xticks(rotation='vertical')
plt.xlabel('Price Range')
plt.ylabel('Count')
plt.show()
def do_feature_engineering(train_data,test_data):
'''
特征工程:处理训练集和测试集中的特征
1,类别特征,使用独热编码
2,数值特征 使用标准化或者归一化
'''
#类别特征
trn_cat_feats=train_data[config.cat_cols].values
tes_cat_feats=test_data[config.cat_cols].values
#数值特征
trn_numeric_feats=train_data[config.numeric_cols]
tes_numeric_feats=test_data[config.numeric_cols]
#独热编码 对类别特征进行独热编码然后添加到数值特征汇总,作为总的特征
enc=OneHotEncoder(sparse=False) #返回的是稀疏矩阵,不能用在模型中 sparse=False可以变成正常矩阵
enc_trn_cat_feats=enc.fit_transform(trn_cat_feats)
enc_tes_cat_feats=enc.transform(tes_cat_feats)
trn_all_feats=np.hstack((trn_numeric_feats,enc_trn_cat_feats)) #合并在一块
tes_all_feats=np.hstack((tes_numeric_feats,enc_tes_cat_feats)) #合并在一块
#标准化 类似归一化
std_scaler=StandardScaler()
scaler_trn_all_feats=std_scaler.fit_transform(trn_all_feats)
scaler_tes_al_feats=std_scaler.transform(tes_all_feats)
return scaler_trn_all_feats,scaler_tes_al_feats
def train_model(x_train, y_train, x_test, y_test, model_name, model, param_range):
"""
根据给定的参数训练模型,并返回
1. 最优模型
2. 平均训练耗时
3. 准确率
"""
print('训练{}...'.format(model_name))
clf = GridSearchCV(estimator=model,
param_grid=param_range,
cv=5, #五折训练
scoring='accuracy',
refit=True) #默认就是TRUE 意思是交叉验证后又吧全部数据训练了一边
start = time.time()
clf.fit(x_train, y_train)
# 计时
end = time.time()
duration = end - start
print('耗时{:.4f}s'.format(duration))
# 验证模型
print('训练准确率:{:.3f}'.format(clf.score(x_train, y_train)))
#有训练准确率和测试准确率
score = clf.score(x_test, y_test)
print('测试准确率:{:.3f}'.format(score))
print('训练模型耗时: {:.4f}s'.format(duration))
print()
return clf, score, duration
main()