python机器学习 鸢尾花分类预测 详细教程 数据集+源码+远程部署

68 阅读8分钟

 数据集+源码+远程部署(+v:sybh0117):python机器学习 鸢尾花分类预测 详细教程 数据集+源码+远程部署

目录

​编辑

介绍

数据处理

配置流水线

分割数据

随机森林模型

模型训练

验证训练集预测集

特征重要性

混淆矩阵

AUC模型

AUC曲线

网格搜索


介绍

鸢尾花分类预测是一个典型的机器学习问题,旨在通过鸢尾花的几个特征,比如花瓣和萼片的长度和宽度,来预测鸢尾花属于哪个种类。鸢尾花数据集通常被用作统计分类技术的测试案例,是模式识别领域的一个经典问题。

鸢尾花数据集主要包括三个类别:Setosa、Versicolour和Virginica,每个类别包括50个样本,因此总共有150个样本数据。每个样本的数据包含了四个特征(萼片长度、萼片宽度、花瓣长度、花瓣宽度),这些特征都是以厘米为单位的测量值。

进行鸢尾花分类预测的步骤通常包括以下几个方面:

  1. 数据预处理:包括清洗数据、处理缺失值、特征选择等步骤。
  2. 选择一个模型:根据问题的特点选择一个合适的机器学习模型,比如逻辑回归、K最近邻(KNN)、支持向量机(SVM)或决策树等。
  3. 训练模型:使用训练数据(通常是数据集的一部分)来训练选定的机器学习模型。
  4. 模型评估和验证:用测试数据(数据集的另一部分)来评估模型的性能,并调整模型参数直至获得满意的预测结果。
  5. 应用模型进行预测:使用训练好的模型对新的鸢尾花样本进行分类预测。

鸢尾花分类预测是入门机器学习和数据科学的绝佳案例,因为它的数据集规模适中,而且只涉及到少量的特征,使得新手也能够比较容易地理解问题和处理过程。

data = pd.read_csv('data.csv')

# 假设最后一列是目标变量
X = data.iloc[:, 1:-1] # 所有行,除了最后一列的所有列
y = data.iloc[:, -1] # 所有行,只有最后一列

# 把 X 和 y 转换为 DataFrame
X = pd.DataFrame(X)
y = pd.DataFrame(y)

# 打印信息查看
print(X)
print(y)

​编辑

  1. data = pd.read_csv('data.csv'):这行代码读取一个名为'data.csv'的CSV文件,将其内容加载到data这个DataFrame对象中。这个CSV文件包含了鸢尾花数据集,这个数据集可能包含多个特征列,用于描述鸢尾花(如萼片长度、宽度等),最后一列是目标变量,即鸢尾花的品种。
  2. X = data.iloc[:, 1:-1]:这行代码用于选择特征变量。.iloc[:, 1:-1]这部分是基于位置的索引,:表示选择所有行,1:-1则表示选择第二列到倒数第二列的所有列。这里假设数据集的第一列(索引为0的列)不是特征列,可能是数据的编号或者别的非特征信息,因此从第二列开始选择到最后一列之前为特征集X。换言之,这里忽略了第一列和最后一列,仅选择中间的列作为特征变量。
  3. y = data.iloc[:, -1]:这行代码用于选择目标变量。iloc[:, -1]基于位置的索引,:表示选择所有行,-1表示选择最后一列。这里的目标变量是指鸢尾花的品种,存储于最后一列。
  4. X = pd.DataFrame(X):尽管X已经是一个DataFrame对象,这行代码显式地再次将X转换为DataFrame。这可能是为了确保X确实是DataFrame类型,或者是出于清晰表达的目的,但从实际操作的角度来看,这行代码可能是多余的。
  5. y = pd.DataFrame(y):同样的,这行代码将y(目标变量)再次转换为DataFrame类型。和上一行代码类似,这也可能是出于确保数据类型或清晰表达的目的,虽然在大多数情况下可能是不必要的。

之前鸢尾花的特征为0,1,2,3,为了更加清晰了解数据,我们将鸢尾花的真实特征作为映射

X.columns = list(map(lambda x: 'feature' + str(x), X.columns))

​编辑

数据处理

cate_cols = []  # 离散特征
num_cols = []  # 数值型特征

# 获取各个特征的数据类型
dtypes = X.dtypes

for col, dtype in dtypes.items():
    if dtype == 'object':
        cate_cols.append(col)
    else:
        num_cols.append(col)

数值型特征

class Num_Encoder(BaseEstimator, TransformerMixin):
    def __init__(self, cols=[], fillna=False, addna=False):
        self.fillna = fillna
        self.cols = cols
        self.addna = addna
        self.na_cols = []
        self.imputers = {}

    def fit(self, X, y=None):
        for col in self.cols:
            if self.fillna:
                self.imputers[col] = X[col].median()
            if self.addna and X[col].isnull().sum():
                self.na_cols.append(col)
        print(self.na_cols, self.imputers)
        return self

    def transform(self, X, y=None):
        df = X.loc[:, self.cols]
        for col in self.imputers:
            df[col].fillna(self.imputers[col], inplace=True)
        for col in self.na_cols:
            df[col + '_na'] = pd.isnull(df[col])
        return df

离散型特征

class Cat_Encoder(BaseEstimator, TransformerMixin):
    def __init__(self, cols, max_n_cat=7, onehot_cols=[], orders={}):
        self.cols = cols
        self.onehot_cols = onehot_cols
        self.cats = {}
        self.max_n_cat = max_n_cat
        self.orders = orders

    def fit(self, X, y=None):
        df_cat = X.loc[:, self.cols]

        for n, c in df_cat.items():
            df_cat[n].fillna('NAN', inplace=True)
            df_cat[n] = c.astype('category').cat.as_ordered()

            if n in self.orders:
                df_cat[n].cat.set_categories(self.orders[n], ordered=True, inplace=True)

            cats_count = len(df_cat[n].cat.categories)

            if cats_count <= 2 or cats_count > self.max_n_cat:
                self.cats[n] = df_cat[n].cat.categories
                if n in self.onehot_cols:
                    self.onehot_cols.remove(n)
            elif n not in self.onehot_cols:
                self.onehot_cols.append(n)

        print(self.onehot_cols)
        return self

    def transform(self, df, y=None):
        X = df.loc[:, self.cols]

        for col in self.cats:
            X[col].fillna('NAN', inplace=True)
            X.loc[:, col] = pd.Categorical(X[col], categories=self.cats[col], ordered=True)
            X.loc[:, col] = X[col].cat.codes

        if len(self.onehot_cols):
            df_1h = pd.get_dummies(X[self.onehot_cols], dummy_na=True)
            df_drop = X.drop(self.onehot_cols, axis=1)
            return pd.concat([df_drop, df_1h], axis=1)

        return X

配置流水线

num_pipeline = Pipeline([
    ('num_encoder', Num_Encoder(cols=num_cols, fillna='median', addna=True)),
])
X_num = num_pipeline.fit_transform(X)

cat_pipeline = Pipeline([
    ('cat_encoder', Cat_Encoder(cols=cate_cols))
])
X_cate = cat_pipeline.fit_transform(X)

​编辑

分割数据

将训练集和预测集按照2:8的比例分割

X = pd.concat([X_num, X_cate], axis=1)
print(X.shape, y.shape)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=2022)
print('【训练集】', X_train.shape, y_train.shape)
print('【测试集】', X_test.shape, y_test.shape)

​编辑

随机森林模型

rfc = RandomForestClassifier(n_estimators=100,
                           criterion='gini',
                           random_state=2022)

模型训练

rfc.fit(X_train, y_train)

​编辑

验证训练集预测集

y_train_pred = rfc.predict(X_train)
y_test_pred = rfc.predict(X_test)

accuracy_train = metrics.accuracy_score(y_train, y_train_pred)
accuracy_test = metrics.accuracy_score(y_test, y_test_pred)

print('训练集的accuracy: ', accuracy_train)
print('测试集的accuracy: ', accuracy_test)

​编辑

特征重要性

feature_importance = pd.DataFrame(rfc.feature_importances_.reshape(X.shape[1], 1), index=list(X.columns),
                                  columns=['特征重要性'])
print(feature_importance)

​编辑

混淆矩阵

confusion_matrix = metrics.confusion_matrix(y_train, y_train_pred)
df_matrix = pd.DataFrame(confusion_matrix, index=['setosa', 'versicolor', 'virginica'], columns=['setosa', 'versicolor', 'virginica'])
print(df_matrix)

​编辑

AUC模型

y_train_proba = rfc.predict_proba(X_train)
y_test_proba = rfc.predict_proba(X_test)

auc_train = metrics.roc_auc_score(y_train, y_train_proba, multi_class ='ovr')
auc_test = metrics.roc_auc_score(y_test, y_test_proba, multi_class ='ovr')

print('训练集的AUC: ', auc_train)
print('测试集的AUC: ', auc_test)

​编辑

AUC曲线

fpr, tpr, thres = metrics.roc_curve(y_test==1, y_test_proba[:, 1])
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.plot(fpr, tpr)
plt.title('ROC曲线')
plt.xlabel('FPR')
plt.ylabel('TPR')
plt.show()

​编辑

网格搜索

rfcmodel = RandomForestClassifier()

param_grid_rfr = {
    "n_estimators": np.arange(50, 300, 50),
    "min_samples_leaf": np.arange(1, 101, 30),
    "max_depth": np.arange(2, 8, 2),
    "max_leaf_nodes": np.arange(5, 20, 5)
}

rfcmodel_grid = GridSearchCV(estimator=rfcmodel,
                             param_grid=param_grid_rfr,
                             verbose=1,
                             n_jobs=-1,
                             cv=2)

rfcmodel_grid.fit(X_train, y_train)

print('【RFR】', rfcmodel_grid.best_score_)

​编辑

best_modelrfc = RandomForestClassifier(n_estimators=rfcmodel_grid.best_estimator_.get_params()['n_estimators'],
                                      min_samples_leaf=rfcmodel_grid.best_estimator_.get_params()['min_samples_leaf'],
                                      max_depth=rfcmodel_grid.best_estimator_.get_params()['max_depth'],
                                      max_leaf_nodes=rfcmodel_grid.best_estimator_.get_params()['max_leaf_nodes'])

best_modelrfc.fit(X_train, y_train)

​编辑

y_train_pred = best_modelrfc.predict(X_train)
y_test_pred = best_modelrfc.predict(X_test)

accuracy_train = metrics.accuracy_score(y_train, y_train_pred)
accuracy_test = metrics.accuracy_score(y_test, y_test_pred)

print('训练集的accuracy: ', accuracy_train)
print('测试集的accuracy: ', accuracy_test)

​编辑