面向人工智能: 对红酒数据集进行分析 (实验四)

pranaa 2024-10-16 11:31:02 阅读 84

由于直接提供截图是不切实际的,我将详细解释如何使用<code>scikit-learn(通常称为sk-learn)自带的红酒数据集进行葡萄酒数据的分析与处理。这包括实验要求的分析、数据的初步分析(完整性和重复性)以及特征之间的关联关系分析。

1. 分析实验要求

实验的主要目标是使用scikit-learn中的红酒数据集(通常是UCI机器学习库中的Wine Recognition dataset)来分析葡萄酒的化学成分与葡萄酒类型或质量之间的关系。通常,该数据集包含多种葡萄酒的化学成分(如酒精度、苹果酸含量等)以及葡萄酒的类别或质量评分。

2. 初步分析数据

2.1 加载数据

首先,你需要加载红酒数据集。在scikit-learn中,这可以通过load_wine函数完成。

# 导入必要的库

from sklearn.datasets import load_wine

import pandas as pd

import matplotlib.pyplot as plt

import seaborn as sns

# 加载红酒数据集

wine_data = load_wine()

# 将数据转换为Pandas DataFrame

df = pd.DataFrame(wine_data.data, columns=wine_data.feature_names)

df['class'] = wine_data.target # 将目标变量(葡萄酒的类别)添加到DataFrame中

2.2 检查数据的完整性和重复性

完整性:通过检查数据的形状(shape)和特征名称(feature_names)来验证数据是否完整。

# 检查数据的形状

print("Data shape:", df.shape) # 查看样本数量和特征数量

重复性:在大多数情况下,UCI数据集不会包含重复的样本。然而,为了确认,你可以使用Pandas库检查数据的唯一性。

# 检查是否有重复的行

print("Number of duplicate rows:", df.duplicated().sum()) # 如果输出为0,则表示没有重复行

3. 分析实验数据各特征之间的关联关系

3.1 使用统计方法

使用Pandas的describe函数查看特征的统计描述,包括均值、标准差等,这些可以帮助你了解数据的分布情况。

print(df.describe())

3.2 绘制直方图和箱线图

绘制特征的直方图和箱线图,以观察特征的分布和可能的异常值。

<code># 绘制直方图

df.iloc[:, :-1].hist(bins=30, figsize=(15, 10), layout=(4, 4))

plt.tight_layout()

plt.show()

# 使用subplots=True让matplotlib自动处理布局

# df.iloc[:, :-1].hist(bins=30, figsize=(15, 15), layout=None, subplots=True)

# plt.tight_layout() # 尝试调整子图参数, 以便子图之间的重叠最小化

# plt.show()

# 绘制箱线图

plt.figure(figsize=(10, 8))

sns.boxplot(data=df.iloc[:, :-1])

plt.title('Boxplot of Wine Dataset Features')

plt.show()

 subplots是一个用来控制自动处理布局的参数,但在这里是不适用的,因为hist 方法在 pandas 的 DataFrame 中并没有 subplots 参数。 subplots=True 是不适用于 pandas 的 hist 方法的,这是 matplotlib 中某些函数(如 subplot_mosaic 或在创建多个子图时)的参数。

为了在 pandas 中绘制多个特征的直方图,并且让 pandas 自动处理子图的布局,应该使用 subplots=True 的方式,但这不是通过 hist 方法的参数来实现的。相反,你需要调整 figsize 来确保图形足够大,以容纳所有特征的直方图。由于 pandas 的 hist 方法不直接支持复杂的子图布局,它通常会将所有直方图绘制在一个连续的网格中,或者可以通过迭代每列来手动创建子图。

为了简化这个过程,我们可以使用 pandas 的 hist 方法,并接受它自动选择的布局,或者我们可以使用 matplotlib 的子图功能来更精细地控制布局。

以下是使用 pandas hist 方法并调整 figsize 的示例:

(figsize:指定figure的宽和高,单位为英寸)

# 绘制特征分布的直方图

fig, axes = plt.subplots(nrows=4, ncols=4, figsize=(15, 15)) # 假设4x4布局,但会有些空白

axes = axes.flatten() # 将二维数组转换为一维,以便迭代

# 注意:如果特征数量不是16个,则以下循环将不会为所有特征绘制直方图

# 或者,你可以根据特征数量动态调整nrows和ncols

for i, feature in enumerate(df.columns[:-1]): # 遍历除'class'之外的所有特征

if i < len(axes): # 确保索引不会超出axes的长度

df[feature].hist(ax=axes[i], bins=30)

axes[i].set_title(feature)

else:

# 如果特征数量超过16个,你可以在这里添加代码来处理额外的特征

# 例如,创建一个新的图形或调整布局

break

# 如果特征数量少于16个,可以移除多余的子图(可选)

for ax in axes[len(df.columns[:-1]):]:

ax.remove()

plt.tight_layout()

plt.show()

上面的代码在特征数量不是16个时会留下空白的子图。一个更灵活的方法是使用 GridSpec 或类似的方法来动态地创建子图网格。不过,对于简单的用例,可能只需要调整 figsize 并接受 pandas hist 方法的默认布局。

如果只是想让 pandas 自动处理布局,并希望图形足够大以清晰显示所有直方图,可以这样做:

# 绘制特征分布的直方图,让pandas自动处理布局

df.iloc[:, :-1].hist(bins=30, figsize=(15, 20)) # 调整figsize的高度以容纳更多直方图

plt.tight_layout() # 尝试调整子图参数,但效果可能有限

plt.show()

3.3 计算特征之间的相关性

使用Pandas的corr函数计算特征之间的相关系数(如皮尔逊相关系数),以分析它们之间的线性关系。

# 计算特征之间的相关系数矩阵

correlation_matrix = df.iloc[:, :-1].corr() # 排除'class'列

# 打印相关系数矩阵

print("Correlation Matrix:")

print(correlation_matrix)

# 绘制热力图以更直观地查看相关性

plt.figure(figsize=(10, 8))

sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm') code>

plt.title('Correlation Heatmap of Wine Dataset Features')

plt.show()

注意:

pandas用于数据处理,matplotlib.pyplotseaborn用于数据可视化。使用load_wine函数加载了红酒数据集,并将其转换为pandas.DataFrame以便于处理。在分析特征之间的关联关系时,排除了目标变量'class'列,只计算了特征之间的相关系数。绘制直方图和箱线图时,layout参数要根据特征数目进行相应的调整。如果特征数量不是3的倍数,可能需要调整layout参数或使用plt.subplots来更灵活地控制子图的布局。seabornheatmap函数用于绘制相关系数矩阵的热力图,它提供了直观的视觉表示来查看哪些特征之间存在强相关性

结果:

4.决策树模型:

(使用准确度和AUC指标进行模型评估)

准确度指标:

<code># 划分数据集

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 训练模型

clf = DecisionTreeClassifier(random_state=42)

clf.fit(X_train, y_train)

# 预测测试集

y_pred = clf.predict(X_test)

# 评估模型(准确度)

accuracy = accuracy_score(y_test, y_pred)

print(f"Accuracy: {accuracy:.2f}")

 AUC指标:

y_scores = clf.predict_proba(X_test) # 获取每个类别的概率

auc = roc_auc_score(y_test, y_scores, multi_class='ovr', average='macro') code>

print(f"Macro-average AUC: {auc:.2f}")

clf:这是一个已经训练好的分类器对象,在这个例子中,它是一个DecisionTreeClassifier实例。.predict_proba(X_test):这是clf对象的一个方法,用于对给定的测试集X_test中的样本进行预测,但它不直接给出类标签(即预测结果所属的类别),而是给出每个样本属于各个类别的概率。这个方法返回一个二维数组,其中每一行对应X_test中的一个样本,每一列对应一个类别,元素值是该样本属于对应类别的概率。y_scores:这个变量接收了.predict_proba(X_test)方法的返回值,即测试集中每个样本属于各个类别的概率。

第二行代码用于计算ROC曲线下的面积(AUC):

y_test:这是测试集的真实标签,即每个样本的实际类别。y_scores:这是通过.predict_proba(X_test)得到的预测概率。multi_class='ovr'code>:这个参数指定了如何将多分类问题转换为多个二分类问题以计算AUC。'ovr'代表“一对一”(One-vs-Rest),即对于每个类别,都将其视为正类,其余所有类别视为负类,然后计算每个类别的ROC AUC,最后通过某种方式(如平均)汇总这些AUC值。average='macro'code>:这个参数指定了如何汇总每个类别的AUC值。'macro'意味着简单地计算所有类别AUC的未加权平均值。

AUC(Area Under the Curve)通常用于评估二分类问题的ROC曲线下的面积,但葡萄酒数据集是一个多分类问题。对于多分类问题,我们可以计算加权平均AUC(通过roc_auc_scoremulti_class参数设置为ovrovo),但更常见的做法是使用准确度、F1分数、混淆矩阵等指标。 

如果数据集是高度不平衡的,使用精确度-召回率曲线可能更加合适,因为它能更好地反映模型在少数类上的性能 。

结果:

5.随机森林:

<code># 划分数据集

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 训练随机森林模型

clf = RandomForestClassifier(n_estimators=100, random_state=42)

clf.fit(X_train, y_train) # 注意:ravel()将y_train从二维数组转换为一维数组

#预测测试集的概率

y_score = clf.predict_proba(X_test)

# 评估模型(准确度)

# 预测测试集的标签

y_pred = clf.predict(X_test) # 注意:这里使用原始标签的索引进行预测

accuracy = accuracy_score(y_test, y_pred)

print(f"Accuracy: {accuracy:.2f}")

auc = roc_auc_score(y_test, y_score, multi_class='ovr', average='macro') code>

print(f"Macro-average AUC: {auc:.2f}")

 结果:

(居然准确度和AUC指标都是1!!怀疑)

如果你得到的准确度和AUC都为1,这通常意味着你的模型在测试集上表现得非常完美,几乎没有任何错误。然而,这种情况在实际应用中是非常罕见的,特别是当使用随机森林这样的集成学习方法时,因为数据集通常包含一些噪声或难以预测的样本。

不放心搜了一下出现这种情况的原因,大家可以参考一下: 

以下是一些可能导致这种情况的原因:

过拟合:模型在训练集上表现得太好,以至于它学习到了训练数据中的噪声或特定模式,而这些模式在测试集中并不适用。然而,随机森林通常具有较好的抗过拟合能力,所以这可能是不太可能的原因,除非数据集非常小或非常特殊。

数据泄漏:在训练和测试集之间存在某种形式的重叠或信息泄漏。例如,如果测试集中的某些样本在无意中用于训练模型,或者如果特征和标签之间存在直接的依赖关系(这些依赖关系在训练集和测试集中都被保留了下来),那么模型可能会表现得异常好。

简单的数据集:数据集可能非常简单,以至于即使是随机猜测也能得到很好的结果。然而,由于你正在使用随机森林这样的复杂模型,并且通常预期它在更复杂的数据集上也能表现良好,所以这种情况也不太可能。

标签不平衡:如果测试集中的大多数样本都属于同一个类别,并且模型只是简单地预测这个最常见的类别,那么准确度可能会很高,但这并不意味着模型实际上能够区分不同的类别。然而,在这种情况下,AUC通常不会接近1,因为它考虑了所有类别的区分能力。

随机性:虽然你设置了<code>random_state来确保结果的可重复性,但随机森林的每次运行都可能略有不同(尽管差异很小)。然而,这种随机性不太可能导致准确度和AUC都为1。

评估错误:可能你在评估模型时犯了某种错误。例如,你可能错误地将训练集用作测试集,或者你可能在计算AUC时使用了错误的参数或方法。

模型参数:在某些情况下,随机森林的参数(如n_estimators)可能被设置得非常高,导致模型过度拟合训练数据。然而,即使在这种情况下,通常也不会看到准确度和AUC都为1的完美结果。

为了诊断这个问题,可以尝试以下步骤:

检查数据:确保训练集和测试集之间没有重叠,并且它们都正确地反映了你要解决的问题。检查标签:确保测试集的标签是正确的,并且没有误用训练集的标签。交叉验证:使用交叉验证来评估模型,这可以帮助你了解模型在不同测试集上的表现。简化模型:尝试使用更简单的模型(如决策树)来查看是否仍然得到相同的结果。检查AUC计算:确保你正确地计算了AUC,并且使用了适当的参数(如multi_class='ovr'code>和average='macro'code>)。如果你对二分类问题使用AUC,请确保你的问题是二分类的,或者你已经将多类问题转换为了多个二分类问题。查看预测结果:查看模型的预测结果,特别是那些被错误分类的样本,以了解模型可能存在的问题。调整模型参数:尝试调整随机森林的参数,如n_estimatorsmax_depth等,以查看是否对结果有影响。然而,请注意,过度调整参数可能会导致过拟合。

 6.调试

scaler = StandardScaler()

X_train_scaled = scaler.fit_transform(X_train)

X_test_scaled = scaler.transform(X_test);

param_grid = {

'n_estimators': [50, 100, 200],

'max_depth': [None, 10, 20, 30],

'min_samples_split': [2, 5, 10],

'min_samples_leaf': [1, 2, 4]

}

grid_search = GridSearchCV(clf, param_grid, cv=5, scoring='accuracy', verbose=2, n_jobs=-1) code>

grid_search.fit(X_train_scaled, y_train)

best_clf = grid_search.best_estimator_

y_pred_best = best_clf.predict(X_test_scaled)

print("Best Parameters:", grid_search.best_params_)

print("Best Accuracy:", accuracy_score(y_test, y_pred_best))

print("Classification Report with Best Parameters:\n", classification_report(y_test, y_pred_best))

结果:

结论

通过上述步骤,可以初步了解红酒数据集的完整性、重复性以及各特征之间的关联关系。这些数据分析步骤对于进一步的数据处理和建模(如分类或回归)至关重要。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。