day 35打卡
day 机器学习管道pipeline基础概念pipeline在机器学习领域被称为“管道”也可以翻译为“流水线”是机器学习中一个重要的概念。通常会按照一定的顺序对数据进行预处理、特征提取、模型训练和模型评估等。转换器(transformer)是一个用于对数据进行预处理和特征提取的estimator,他实现一个transformer 。转换器通常用于对数据进行预处理,例如对数据进行归一化,标准化、缺失值等,转换器也用于对数据进行特征提取,例如对数据进行特征选择、特征组合等。转换器也可以用于对数据进行特征提取。转换器的特点是无状态,不会存储任何与无关于数据的状态信息。转换器仅根据输入数据学习转换规则。并在训练集上学习转换规则,并在训练集之外的新数据上应用这些规则。常见的转换器包括数据缩放器(如standardscaler,MinMaxScaler)、特征选择器(如 selectbest\\PCA)特征提取器(如CountVectorizer、TF-idfvectorizer)等估计器(estimator)估计器是实现机器学习算法的对象或类。它用于拟合(fit)数据并进行预测,估计是机器学习模型的基本组成部分,用于从数据中学习模型、进行预测和进行模型评估。估计器主要方法是fit 和predict。fit 方法用于根据输入数据学习模型的参数和规律,而predict 方法用于根据学习到的参数和规律对新数据进行预测。估计器的特点是有状态的,他们在训练过程中存储了关于数据的状态信息,以便在预测阶段使用。估计器通过学习训练数据中的模型和规律进行预测。因此估计器需要在训练集上进行训练,并使用训练得倒的模型参数对新数据进行预测。管道了解了分类器和估计器,所以可以理解为咋机器学习由转换器、估计器、按照一定顺序组合在一起来完成流程。机器学习的管道机制通过将多个转换器和估计器顺序连接在一起,可以构建一个一个完整的数据处理和模型训练流程。pipeline 最大的价值和核心应用场景之一,就是与交叉验证和网格搜索等结合使用:1、防止数据泄漏:这是在使用交叉验证时,pipeline自动完成预处理并在每个折叠内独立(fit transform)的关键优势;2、简化超参数调优:可以方便同时调优预处理步骤和模型的参数。代码演示没有pipline 的代码# 先运行之前预处理好的代码import pandas as pd import numpy as npimport matplotlib.pyplot as pltimport seaborn as snsimport warningswarnings.filterwarnings(\'ignore\')plt.rcParams[\'font.sans-serif\'] = [\'SimHei\']plt.rcParams[\'axes.unicode_minus\'] = Falsedata=pd.read_csv(\'/Users/gj/东财-学习/python相关资料学习/Python60DaysChallenge-main/data.csv\')discrete_features = data.select_dtypes(include=[\'object\']).columns.tolist()home_ownership_mapping={ \'Own Home\':1, \'Rent\':2, \'Have Mortgage\':3, \'Home Mortgage\':4}data[\'Home Ownership\']=data[\'Home Ownership\'].map(home_ownership_mapping) years_in_mortgage_mapping={ \'<1 year\':1, \'1 year\':2, \'2 years\':3, \'3 years\':4, \'4 years\':5, \'5 years\':6, \'6 years\':7, \'7 years\':8, \'8 years\':9, \'9 years\':10, \'10+ years\':11}data[\'Years in current job\']=data[\'Years in current job\'].map(years_in_mortgage_mapping)data=pd.get_dummies(data,columns=[\'Purpose\'])data2=pd.read_csv(\'/Users/gj/东财-学习/python相关资料学习/Python60DaysChallenge-main/data.csv\')list_final=[]for i in data.columns: if i not in data2.columns: list_final.append(i)for i in list_final: data[i]=data[i].astype(int)term_mapping={ \'Short Term\':0, \'Long Term\':1}data[\'Term\']=data[\'Term\'].map(term_mapping)data.rename(columns={\'Term\':\'Long Term\'},inplace=True)continuous_features = data.select_dtypes(include=[\'int64\',\'float64\']).columns.tolist()from sklearn.model_selection import train_test_splitX=data.drop([\'Credit Default\'],axis=1)y=data[\'Credit Default\']X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=42)from sklearn.ensemble import RandomForestClassifierfrom sklearn.metrics import accuracy_score,classification_report,confusion_matriximport warningswarnings.filterwarnings(\'ignore\')print (\"-----1、默认参数随机森林(训练集)-》测试集\")import timestart_time=time.time()rf_model=RandomForestClassifier(random_state=42)rf_model.fit(X_train,y_train)rf_pred=rf_model.predict(X_test)end_time=time.time()print(f\"默认参数随机森林分类器耗时:{end_time-start_time:.4f}秒\")print(\"\\n默认参数随机森林分类器 在测试集上的分类报告:\")print(classification_report(y_test, rf_pred))print(\"默认随机森林在测试集上的混淆矩阵\")print (confusion_matrix(y_test,rf_pred))pipeline的代码教学导入库和数据加载import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as snsimport time import warningswarnings.filterwarnings(\'ignore\')plt.rcParams[\'font.sans-serif\']=[\'SimHei\']plt.rcParams[\'axes.unicode_minus\']=Falsefrom sklearn.pipeline import Pipelinefrom sklearn.compose import ColumnTransformerfrom sklearn.preprocessing import OrdinalEncoder,OneHotEncoder,StandardScalerfrom sklearn.impute import SimpleImputerfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import classification_report,confusion_matrixdata=pd.read_csv(\"/Users/gj/东财-学习/python相关资料学习/Python60DaysChallenge-main/data.csv\")print (\"原属数据加载完成,形状为:\",data.shape)print (\"数据前五行:\\n\",data.head())# ----分离特征和标签y=data[\'Credit Default\']X=data.drop([\'Credit Default\'],axis=1)print(\"\\n 特征和标签分离完成\")print(\"特征形状:\",X.shape)print(\"标签形状:\",y.shape)# 划分训练集和测试集X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=42)print(\"\\n 训练集和测试集划分完成\")print(\"训练集形状:\",X_train.shape)print(\"测试集形状:\",X_test.shape)print(\"训练集标签形状:\",y_train.shape)print(\"测试集标签形状:\",y_test.shape)定义预处理步骤colum transformer 的核心# --- 定义不同列的类型和它们对应的预处理步骤 ---# 这些定义是基于原始数据 X 的列类型来确定的# 识别原始的 object 列 (对应你原代码中的 discrete_features 在预处理前)object_cols = X.select_dtypes(include=[\'object\']).columns.tolist()# 识别原始的非 object 列 (通常是数值列)numeric_cols = X.select_dtypes(exclude=[\'object\']).columns.tolist()# 有序分类特征 (对应你之前的标签编码)# 注意:OrdinalEncoder默认编码为0, 1, 2... 对应你之前的1, 2, 3...需要在模型解释时注意# 这里的类别顺序需要和你之前映射的顺序一致ordinal_features = [\'Home Ownership\', \'Years in current job\', \'Term\']# 定义每个有序特征的类别顺序,这个顺序决定了编码后的数值大小ordinal_categories = [ [\'Own Home\', \'Rent\', \'Have Mortgage\', \'Home Mortgage\'], # Home Ownership 的顺序 (对应1, 2, 3, 4) [\'< 1 year\', \'1 year\', \'2 years\', \'3 years\', \'4 years\', \'5 years\', \'6 years\', \'7 years\', \'8 years\', \'9 years\', \'10+ years\'], # Years in current job 的顺序 (对应1-11) [\'Short Term\', \'Long Term\'] # Term 的顺序 (对应0, 1)]# 构建处理有序特征的 Pipeline: 先填充缺失值,再进行有序编码ordinal_transformer = Pipeline(steps=[ (\'imputer\', SimpleImputer(strategy=\'most_frequent\')), # 用众数填充分类特征的缺失值 (\'encoder\', OrdinalEncoder(categories=ordinal_categories, handle_unknown=\'use_encoded_value\', unknown_value=-1))])print(\"有序特征处理 Pipeline 定义完成。\")# 标称分类特征 (对应你之前的独热编码)nominal_features = [\'Purpose\'] # 使用原始列名# 构建处理标称特征的 Pipeline: 先填充缺失值,再进行独热编码nominal_transformer = Pipeline(steps=[ (\'imputer\', SimpleImputer(strategy=\'most_frequent\')), # 用众数填充分类特征的缺失值 (\'onehot\', OneHotEncoder(handle_unknown=\'ignore\', sparse_output=False)) # 进行独热编码, sparse_output=False 使输出为密集数组])print(\"标称特征处理 Pipeline 定义完成。\")# 连续特征 (对应你之前的众数填充 + 添加标准化)# 从所有列中排除掉分类特征,得到连续特征列表# continuous_features = X.columns.difference(object_cols).tolist() # 原始X中非object类型的列# 也可以直接从所有列中排除已知的有序和标称特征continuous_features = [f for f in X.columns if f not in ordinal_features + nominal_features]# 构建处理连续特征的 Pipeline: 先填充缺失值,再进行标准化continuous_transformer = Pipeline(steps=[ (\'imputer\', SimpleImputer(strategy=\'most_frequent\')), # 用众数填充缺失值 (复现你的原始逻辑) (\'scaler\', StandardScaler()) # 标准化,一个好的实践 (如果你严格复刻原代码,可以移除这步)])print(\"连续特征处理 Pipeline 定义完成。\")# --- 构建 ColumnTransformer ---# 将不同的预处理应用于不同的列子集,构造一个完备的转化器# ColumnTransformer 接收一个 transformers 列表,每个元素是 (名称, 转换器对象, 列名列表)preprocessor = ColumnTransformer( transformers=[ (\'ordinal\', ordinal_transformer, ordinal_features), # 对 ordinal_features 列应用 ordinal_transformer (\'nominal\', nominal_transformer, nominal_features), # 对 nominal_features 列应用 nominal_transformer (\'continuous\', continuous_transformer, continuous_features) # 对 continuous_features 列应用 continuous_transformer ], remainder=\'passthrough\' # 如何处理没有在上面列表中指定的列。 # \'passthrough\' 表示保留这些列,不做任何处理。 # \'drop\' 表示丢弃这些列。)print(\"\\nColumnTransformer (预处理器) 定义完成。\")# print(preprocessor) # 可以打印 preprocessor 对象看看它的结构构建完整的pipelinepipeline=Pipeline(steps=[ (\'preprocessor\',preprocessor), (\'classifier\',RandomForestClassifier(random_state=42))])print(\"\\n 完整的pipeline定义完成\")使用pipeline进行训练和评估# -----1.使用pipeline 在划分好的训练集和测试集上评估print(\"\\n-----1.默认参数随机森林(训练集)——测试集\")start_time=time.time()pipeline.fit(X_train,y_train)pipeline_pred=pipeline.predict(X_test)end_time=time.time()print(f\"pipeline训练耗时:{end_time-start_time:.4f}秒\")print(\"\\n 默认随机森林 在测试集上的分类报告:\")print(classification_report(y_test, pipeline_pred))print (\"\\n默认随机森林 在测试集上的混淆矩阵:\")print(confusion_matrix(y_test, pipeline_pred))代码汇总import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as snsimport timeimport warningswarnings.filterwarnings(\'ignore\')plt.rcParams[\'font.sans-serif\'] = [\'SimHei\']plt.rcParams[\'axes.unicode_minus\'] = False# pipeline 相关预处理工具from sklearn.pipeline import Pipelinefrom sklearn.compose import ColumnTransformer# 用于将预处理应用于不同的列,之前是对datafame 的某一列手动处理,如果在pipeline中直接用standSCaler 等函数就会对所有列处理,所以用这个工具from sklearn.preprocessing import StandardScaler,OneHotEncoder,OneHotEncoder# 用于数据预处理from sklearn.impute import SimpleImputer# 用于处理缺失值# 机器学习相关库from sklearn.ensemble import RandomForestClassifier# 随机森林分类器from sklearn.metrics import classification_report,confusion_matrix,accuracy_score,precision_score,recall_score,f1_score# 用于评估模型性能from sklearn.model_selection import train_test_split# 用于划分训练集和测试集data=pd.read_csv(\'/Users/gj/东财-学习/python相关资料学习/Python60DaysChallenge-main/data.csv\')y=data[\'Credit Default\']X=data.drop([\'Credit Default\'],axis=1)# 划分X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=42)object_cols=X.select_dtypes(include=[\'object\']).columns.tolist()# 选择类别型变量ordinal_features = [\'Home Ownership\', \'Years in current job\', \'Term\']ordinal_categories=[ [\'Own Home\', \'Rent\', \'Have Mortgage\', \'Home Mortgage\'], # Home Ownership 的顺序 (对应1, 2, 3, 4) [\'< 1 year\', \'1 year\', \'2 years\', \'3 years\', \'4 years\', \'5 years\', \'6 years\', \'7 years\', \'8 years\', \'9 years\', \'10+ years\'], # Years in current job 的顺序 (对应1-11) [\'Short Term\', \'Long Term\'] # Term 的顺序 (对应0, 1)]# 先用众数填充分类特征的缺失值,然后进行有序编码ordinal_transformer = Pipeline(steps=[ (\'imputer\', SimpleImputer(strategy=\'most_frequent\')), # 用众数填充分类特征的缺失值 (\'encoder\', OrdinalEncoder(categories=ordinal_categories, handle_unknown=\'use_encoded_value\', unknown_value=-1))])# 分类特征nominal_features=[\'Purpose\'] nominal_transformer=Pipeline(steps=[ (\'imputer\',SimpleImputer(strategy=\'most_frequent\')), (\'onehot\',OneHotEncoder(handle_unknown=\'ignore\',sparse_output=False ) )])# 连续特征continuous_features=X.columns.difference(object_cols).tolist()# 先用众数填充缺失值,进行标准化continuous_transformer=Pipeline(steps=[ (\'imputer\',SimpleImputer(strategy=\'most_frequent\')), (\'scaler\',StandardScaler())])# ---构建columntransformerpreprocessor=ColumnTransformer( transformers=[ (\'ordinal\',ordinal_transformer,ordinal_features), (\'nominal\',nominal_transformer,nominal_features), (\'continuous\',continuous_transformer,continuous_features) ], remainder=\'passthrough\')# ----1.使用pipeline在划分的训练集呵测试集print(\"------1.默认参数随机森林(训练集)---测试集\")start_time=time.time()pipeline.fit(X_train,y_train)pipeline_pred=pipeline.predict(X_test)end_time=time.time()print(f\"默认参数随机森林分类器耗时:{end_time-start_time:.4f}秒\")print(\"默认参数随机森林分类器 在测试集上的分类报告:\")print(classification_report(y_test, pipeline_pred))print(\"默认参数随机森林分类器 在测试集上的混淆矩阵:\")print(confusion_matrix(y_test, pipeline_pred))
@浙大疏锦行