1. 为什么机器学习需要数据可视化?

在机器学习项目中,数据可视化绝不是锦上添花的装饰品。我处理过的真实案例中,约70%的特征工程问题都是通过可视化发现的。Seaborn作为基于matplotlib的高级接口,提供了更简洁的API和更美观的默认样式,特别适合机器学习工作流。

最近一个客户案例让我印象深刻:他们花费两周时间调整的模型,准确率始终卡在82%上不去。当我用Seaborn的pairplot画出特征关系矩阵后,立刻发现两个关键特征存在明显的非线性关系。简单添加一个交互项后,模型准确率直接提升到89%。

2. 机器学习专用可视化工具箱

2.1 分布可视化实战

机器学习最常用的distplot已被升级为displot和histplot。对于2023年的新版本,我的建议是:

# 现代写法
import seaborn as sns
sns.displot(data=df, x='feature', hue='target', kind='kde', 
            height=5, aspect=1.5, palette='viridis')

关键参数解析:

  • aspect 控制长宽比(1.5:1更适合宽屏显示)
  • palette 推荐使用'viridis'/'plasma'等感知均匀的色系
  • multiple='stack' 适合类别对比

经验:当特征有>1000个唯一值时,务必加上 kde=False ,否则计算代价极高。

2.2 特征关系矩阵

新版pairplot有个隐藏技巧——通过 corner=True 节省50%绘图时间:

g = sns.pairplot(df, vars=num_features, hue='target',
                 corner=True, plot_kws={'alpha':0.5})
g.map_lower(sns.kdeplot, levels=4)  # 下三角添加密度线

我常用的优化组合:

  1. 数值变量: diag_kind='kde'
  2. 分类变量: plot_kws={'jitter':0.2}
  3. 大数据集: plot_kws={'s':8} 减小点大小

2.3 热力图进阶技巧

特征相关性热力图的常见误区是直接使用 .corr() 。我推荐采用以下改进方案:

# 计算相关性的更稳健方法
corr = df[num_features].apply(lambda x: pd.to_numeric(x, errors='coerce'))
corr = corr.dropna().corr(method='spearman')  # 非参数方法

# 热力图优化
mask = np.triu(np.ones_like(corr, dtype=bool))  # 隐藏上三角
sns.heatmap(corr, mask=mask, annot=True, 
           fmt='.2f', cmap='vlag', center=0,
           linewidths=.5, cbar_kws={'shrink':.8})

避坑指南:当特征>20个时,一定要设置 annot=False ,否则文字会重叠无法辨认。

3. 模型诊断可视化方案

3.1 残差分析四象限图

传统残差图经常漏掉关键信息。我的标准诊断流程包含四个子图:

from sklearn.linear_model import LinearRegression

model = LinearRegression().fit(X_train, y_train)
residuals = y_test - model.predict(X_test)

fig, axes = plt.subplots(2, 2, figsize=(12,10))
sns.residplot(x=model.predict(X_test), y=residuals, 
              lowess=True, ax=axes[0,0])
sns.boxplot(x=pd.qcut(model.predict(X_test), 5), 
            y=residuals, ax=axes[0,1])
sns.histplot(residuals, kde=True, ax=axes[1,0])
stats.probplot(residuals, plot=axes[1,1])

这个组合能同时检测:

  • 非线性模式(左上)
  • 异方差性(右上)
  • 分布偏离(左下)
  • 正态性(右下)

3.2 决策边界可视化

对于二维特征空间,我开发了一套动态可视化方案:

from mlxtend.plotting import plot_decision_regions

# 包装成标准函数
def plot_2d_decision(model, X, y, title):
    X_array = X.values if hasattr(X, 'values') else X
    y_array = y.values if hasattr(y, 'values') else y
    
    plt.figure(figsize=(10,6))
    plot_decision_regions(X_array, y_array, clf=model, legend=2)
    plt.title(title)
    plt.xlabel(X.columns[0])
    plt.ylabel(X.columns[1])
    
    # 添加数据分布边际
    sns.kdeplot(x=X.iloc[:,0], y=X.iloc[:,1], 
                levels=5, color='black', alpha=0.5)

关键改进点:

  1. 自动处理DataFrame/array输入
  2. 叠加KDE轮廓显示数据密度
  3. 标准化图形尺寸和标签

4. 特征重要性可视化

4.1 排列重要性可视化

比默认的feature_importances_更可靠的方法是排列重要性:

from sklearn.inspection import permutation_importance

result = permutation_importance(model, X_val, y_val, 
                               n_repeats=10, random_state=42)

imp_df = pd.DataFrame({
    'feature': X.columns,
    'importance': result.importances_mean,
    'std': result.importances_std
}).sort_values('importance')

plt.figure(figsize=(10,6))
sns.barplot(x='importance', y='feature', data=imp_df, 
           xerr=imp_df['std'], palette='rocket')
plt.title('Permutation Importance with Standard Deviation')

4.2 SHAP值瀑布图

集成SHAP和Seaborn的进阶方案:

import shap

explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_sample)

# 整理为DataFrame
shap_df = pd.DataFrame({
    'feature': X.columns,
    'shap_abs': np.abs(shap_values).mean(0),
    'shap_mean': shap_values.mean(0)
}).sort_values('shap_abs', ascending=False)

# 双轴可视化
fig, ax1 = plt.subplots(figsize=(10,6))
ax2 = ax1.twiny()

sns.barplot(x='shap_abs', y='feature', data=shap_df, 
           palette='mako_r', ax=ax1)
sns.pointplot(x='shap_mean', y='feature', data=shap_df,
             color='red', ax=ax2, scale=0.5)

ax1.set_xlabel('Mean Absolute SHAP Value')
ax2.set_xlabel('Mean SHAP Value (Red Dots)')

这种呈现方式既能看出特征重要性,又能显示影响方向。

5. 超参数调优可视化

5.1 网格搜索热力图

改进版的网格搜索可视化:

cv_results = pd.DataFrame(grid.cv_results_)

# 透视关键参数
heatmap_data = cv_results.pivot_table(index='param_max_depth',
                                     columns='param_min_samples_leaf',
                                     values='mean_test_score')

plt.figure(figsize=(10,8))
sns.heatmap(heatmap_data, annot=True, fmt='.3f',
           cmap='YlGnBu', cbar_kws={'label':'Accuracy'})
plt.title('Hyperparameter Tuning Heatmap')

我通常会添加:

  1. linewidths=0.5 增强单元格边界
  2. annot_kws={'size':8} 调整标注字号
  3. plt.axhline / axvline 标记最优参数

5.2 学习曲线诊断

动态学习曲线绘制方案:

from sklearn.model_selection import learning_curve

train_sizes, train_scores, test_scores = learning_curve(
    estimator=model, X=X_train, y=y_train,
    train_sizes=np.linspace(0.1, 1.0, 10), cv=5)

# 计算统计量
train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)

# 增强型学习曲线
plt.figure(figsize=(10,6))
sns.lineplot(x=train_sizes, y=train_mean, color='blue', 
            label='Training Score')
plt.fill_between(train_sizes, train_mean-train_std,
                train_mean+train_std, alpha=0.15, color='blue')

sns.lineplot(x=train_sizes, y=test_mean, color='green',
            label='CV Score')
plt.fill_between(train_sizes, test_mean-test_std,
                test_mean+test_std, alpha=0.15, color='green')

plt.axhline(y=baseline_score, color='red', linestyle='--')

关键增强点:

  1. 使用fill_between显示方差
  2. 添加基线参考线
  3. 采用seaborn的lineplot保证平滑显示

6. 分类任务专属可视化

6.1 混淆矩阵热力图

带权重的混淆矩阵展示:

from sklearn.metrics import confusion_matrix

cm = confusion_matrix(y_true, y_pred, normalize='true')

plt.figure(figsize=(8,6))
sns.heatmap(cm, annot=True, fmt='.2f', cmap='Blues',
           xticklabels=classes, yticklabels=classes)
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Normalized Confusion Matrix')

# 添加分类报告摘要
for i in range(len(classes)):
    plt.text(len(classes)+0.5, i+0.5, 
            f'Precision: {precision[i]:.2f}\nRecall: {recall[i]:.2f}',
            va='center')

6.2 ROC曲线对比

多模型ROC对比技巧:

from sklearn.metrics import roc_curve, auc

plt.figure(figsize=(10,8))
models = [('LR', model1), ('RF', model2), ('XGB', model3)]

for name, model in models:
    y_score = model.predict_proba(X_test)[:,1]
    fpr, tpr, _ = roc_curve(y_test, y_score)
    roc_auc = auc(fpr, tpr)
    
    sns.lineplot(x=fpr, y=tpr, label=f'{name} (AUC = {roc_auc:.2f})')
    
plt.plot([0,1], [0,1], 'k--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc='lower right')

优化点:

  1. 自动计算AUC并显示在图例
  2. 使用sns.lineplot保证平滑曲线
  3. 45度参考线作为基准

7. 时间序列预测可视化

7.1 预测结果对比

带置信区间的预测可视化:

plt.figure(figsize=(12,6))
sns.lineplot(data=df, x='date', y='actual', label='Actual')
sns.lineplot(data=df, x='date', y='predicted', label='Predicted')

# 添加置信区间
plt.fill_between(df['date'], 
                df['pred_lower'], 
                df['pred_upper'],
                color='gray', alpha=0.2)

# 标记重大事件
for event_date, label in zip(event_dates, event_labels):
    plt.axvline(x=event_date, color='red', linestyle='--', alpha=0.5)
    plt.text(event_date, plt.ylim()[1]*0.9, label, 
            rotation=90, va='top')

7.2 季节性分解

基于Seaborn的季节性分析:

from statsmodels.tsa.seasonal import seasonal_decompose

result = seasonal_decompose(ts_data, model='additive', period=12)

fig, axes = plt.subplots(4, 1, figsize=(12,10))
sns.lineplot(x=result.observed.index, y=result.observed, ax=axes[0])
axes[0].set_title('Observed')

sns.lineplot(x=result.trend.index, y=result.trend, ax=axes[1])
axes[1].set_title('Trend')

sns.lineplot(x=result.seasonal.index, y=result.seasonal, ax=axes[2])
axes[2].set_title('Seasonal')

sns.lineplot(x=result.resid.index, y=result.resid, ax=axes[3])
axes[3].set_title('Residual')

8. 高维数据可视化技巧

8.1 t-SNE与UMAP对比

from sklearn.manifold import TSNE
from umap import UMAP

# 降维计算
tsne = TSNE(n_components=2, random_state=42)
umap = UMAP(n_components=2, random_state=42)

X_tsne = tsne.fit_transform(X_scaled)
X_umap = umap.fit_transform(X_scaled)

# 对比可视化
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16,6))
sns.scatterplot(x=X_tsne[:,0], y=X_tsne[:,1], hue=y, 
               palette='viridis', ax=ax1)
ax1.set_title('t-SNE Projection')

sns.scatterplot(x=X_umap[:,0], y=X_umap[:,1], hue=y,
               palette='viridis', ax=ax2)
ax2.set_title('UMAP Projection')

8.2 平行坐标图

改进版平行坐标可视化:

from pandas.plotting import parallel_coordinates

# 数据预处理
df_parallel = df[features + ['target']].copy()
df_parallel['target'] = df_parallel['target'].astype('category')

plt.figure(figsize=(12,6))
parallel_coordinates(df_parallel, 'target', 
                    colormap='viridis', alpha=0.5)
plt.xticks(rotation=45)
plt.grid(alpha=0.3)

# 添加中位数线
for feat in features:
    medians = df_parallel.groupby('target')[feat].median()
    for i, (cat, val) in enumerate(medians.items()):
        plt.scatter(i, val, color='red', s=50, zorder=10)

优化点:

  1. 使用viridis色系保证颜色辨识度
  2. 添加特征中位数标记
  3. 调整坐标轴标签角度

9. 自动化可视化工作流

9.1 自动化EDA函数

我常用的EDA自动化函数:

def auto_eda(df, target=None, num_features=None, cat_features=None):
    """自动化探索性数据分析可视化"""
    
    # 确定特征类型
    if num_features is None:
        num_features = df.select_dtypes(include=np.number).columns.tolist()
        if target in num_features:
            num_features.remove(target)
    
    if cat_features is None:
        cat_features = df.select_dtypes(exclude=np.number).columns.tolist()
    
    # 创建图形网格
    fig = plt.figure(figsize=(18, 15))
    gs = fig.add_gridspec(3, 3)
    
    # 1. 目标变量分布
    ax1 = fig.add_subplot(gs[0, :2])
    if target:
        if df[target].nunique() > 10:
            sns.histplot(df[target], kde=True, ax=ax1)
        else:
            sns.countplot(x=target, data=df, ax=ax1)
        ax1.set_title(f'Distribution of {target}')
    
    # 2. 数值特征箱线图
    ax2 = fig.add_subplot(gs[0, 2])
    if num_features:
        sns.boxplot(data=df[num_features].melt(), 
                   x='variable', y='value', ax=ax2)
        ax2.set_xticklabels(ax2.get_xticklabels(), rotation=45)
        ax2.set_title('Numeric Features Distribution')
    
    # 3. 类别特征计数
    ax3 = fig.add_subplot(gs[1, 0])
    if cat_features:
        sns.countplot(x=cat_features[0], data=df, ax=ax3)
        ax3.set_title(f'Distribution of {cat_features[0]}')
    
    # 4. 特征相关性
    ax4 = fig.add_subplot(gs[1, 1:])
    if len(num_features) > 1:
        corr = df[num_features].corr()
        sns.heatmap(corr, annot=True, fmt='.2f', 
                   cmap='coolwarm', center=0, ax=ax4)
        ax4.set_title('Feature Correlation')
    
    # 5. 特征与目标关系
    if target:
        ax5 = fig.add_subplot(gs[2, :])
        if df[target].nunique() > 5:
            # 回归问题
            for feat in num_features[:3]:
                sns.regplot(x=feat, y=target, data=df, 
                           scatter_kws={'alpha':0.3}, 
                           line_kws={'color':'red'}, 
                           ax=ax5, label=feat)
        else:
            # 分类问题
            sns.violinplot(x=target, y=num_features[0], 
                          data=df, ax=ax5)
        ax5.set_title(f'Feature-Target Relationship')
        ax5.legend()
    
    plt.tight_layout()
    return fig

9.2 交互式可视化集成

结合Plotly的交互式方案:

import plotly.express as px
from plotly.subplots import make_subplots

def interactive_feature_analysis(df, target):
    """交互式特征分析仪表板"""
    fig = make_subplots(rows=2, cols=2,
                       specs=[[{'type':'xy'}, {'type':'polar'}],
                             [{'type':'xy'}, {'type':'xy'}]],
                       subplot_titles=('Distribution', 
                                      'Radial Visualization',
                                      'Feature Correlation',
                                      'Target Relationship'))
    
    # 1. 目标变量分布
    if df[target].nunique() > 10:
        trace1 = px.histogram(df, x=target, nbins=30)
    else:
        trace1 = px.pie(df, names=target)
    fig.add_trace(trace1.data[0], row=1, col=1)
    
    # 2. 雷达图
    num_cols = df.select_dtypes(include=np.number).columns.tolist()
    if len(num_cols) > 3:
        df_norm = (df[num_cols] - df[num_cols].mean()) / df[num_cols].std()
        df_norm['target'] = df[target]
        trace2 = px.line_polar(df_norm, r=num_cols[0], 
                              theta=num_cols[1:4], 
                              line_close=True,
                              color='target')
        fig.add_trace(trace2.data[0], row=1, col=2)
    
    # 3. 相关性热力图
    corr = df[num_cols].corr().round(2)
    trace3 = px.imshow(corr, text_auto=True,
                      color_continuous_scale='RdBu',
                      zmin=-1, zmax=1)
    fig.add_trace(trace3.data[0], row=2, col=1)
    
    # 4. 特征与目标关系
    if df[target].nunique() > 5:
        trace4 = px.scatter(df, x=num_cols[0], y=target,
                           trendline='ols')
    else:
        trace4 = px.box(df, x=target, y=num_cols[0])
    fig.add_trace(trace4.data[0], row=2, col=2)
    
    fig.update_layout(height=800, showlegend=False)
    return fig

10. 可视化优化与性能技巧

10.1 大数据集采样策略

处理百万级数据时的可视化技巧:

def smart_sampling(df, target=None, n_samples=10000):
    """智能采样保持数据分布"""
    if len(df) <= n_samples:
        return df.copy()
    
    if target:
        # 分层采样
        sample = df.groupby(target, group_keys=False).apply(
            lambda x: x.sample(min(len(x), int(n_samples/df[target].nunique()*1.5)))
        )
    else:
        # 随机采样+聚类保持结构
        from sklearn.cluster import MiniBatchKMeans
        kmeans = MiniBatchKMeans(n_clusters=50, random_state=42)
        df['_cluster'] = kmeans.fit_predict(df.select_dtypes(include=np.number))
        sample = df.groupby('_cluster').apply(
            lambda x: x.sample(min(len(x), int(n_samples/50)))
        )
    
    return sample.sample(n=min(len(sample), n_samples), random_state=42)

10.2 图形渲染加速

Seaborn图形加速技巧:

  1. 关闭阴影计算: sns.set_context("notebook", rc={"lines.linewidth": 1})
  2. 使用rasterized=True渲染大数据点:
    sns.scatterplot(x='x', y='y', data=df, 
                   rasterized=True, alpha=0.1)
    
  3. 预聚合数据:
    hexbin = sns.jointplot(x='x', y='y', data=df, 
                          kind='hex', gridsize=50)
    

10.3 图形导出最佳实践

出版级图形导出设置:

plt.savefig('visualization.pdf', 
           dpi=300, 
           bbox_inches='tight',
           pad_inches=0.1,
           format='pdf', 
           metadata={'Title': 'ML Visualization',
                    'Author': 'Your Name',
                    'Keywords': 'machine learning,seaborn'})

# 同时生成PNG缩略图
plt.savefig('visualization.png',
           dpi=120,
           bbox_inches='tight',
           format='png')

关键参数:

  • dpi :印刷用300dpi,网页显示72-120dpi
  • bbox_inches='tight' :自动裁剪空白边缘
  • pad_inches :控制边距
  • PDF适合矢量图形,PNG适合网页嵌入

11. 常见问题解决方案

11.1 图形元素重叠问题

解决方案矩阵:

问题类型 解决方法 代码示例
标签重叠 调整旋转角度 plt.xticks(rotation=45)
图例遮挡 调整位置/分栏 plt.legend(ncol=2, bbox_to_anchor=(1,1))
点重叠 使用透明度/抖动 sns.stripplot(jitter=0.2, alpha=0.5)
热力图层级 调整字号/格式 sns.heatmap(annot_kws={'size':8}, fmt='.1f')

11.2 颜色方案选择指南

颜色使用决策树:

  1. 数据类型:

    • 连续型: cmap='viridis' / 'plasma'
    • 分类型: palette='Set2' / 'Paired'
    • 发散型: cmap='vlag' / 'RdBu'
  2. 色盲友好方案:

    sns.set_palette(sns.color_palette([
        '#1f77b4',  # 蓝色
        '#ff7f0e',  # 橙色
        '#2ca02c',  # 绿色
        '#d62728',  # 红色
        '#9467bd'   # 紫色
    ]))
    
  3. 打印安全检查:

    from matplotlib.colors import to_grayscale
    gray = to_grayscale(color)
    if np.mean(gray) < 0.3 or np.mean(gray) > 0.7:
        print("低对比度警告")
    

12. 完整机器学习可视化流程示例

12.1 回归问题全流程

# 1. 数据概览
auto_eda(df, target='price')

# 2. 特征工程可视化
g = sns.pairplot(df, vars=['sqft', 'bedrooms', 'age'], 
                hue='location', corner=True)
g.map_lower(sns.kdeplot)

# 3. 模型诊断
plot_residuals(model, X_test, y_test)

# 4. 特征重要性
plot_shap_summary(model, X_sample)

# 5. 预测结果对比
plt.figure(figsize=(12,6))
sns.regplot(x=y_test, y=y_pred, 
           scatter_kws={'alpha':0.3},
           line_kws={'color':'red'})
plt.plot([y_test.min(), y_test.max()],
        [y_test.min(), y_test.max()], 'k--')

12.2 分类问题全流程

# 1. 类别分布检查
sns.catplot(x='target', col='segment', 
           data=df, kind='count',
           col_wrap=3, height=4, aspect=1.2)

# 2. 特征与目标关系
for feature in num_features:
    sns.violinplot(x='target', y=feature, 
                  data=df, inner='quartile')

# 3. 决策边界
plot_2d_decision(model, X[['pca1','pca2']], y, 
                'Decision Boundary')

# 4. 模型评估
plot_roc_curve(models, X_test, y_test)
plot_confusion_matrix(model, X_test, y_test)

13. 扩展工具链集成

13.1 与Yellowbrick集成

from yellowbrick.features import PCA
from yellowbrick.model_selection import FeatureImportances

# PCA可视化
visualizer = PCA(scale=True, proj_features=True)
visualizer.fit_transform(X, y)
visualizer.show()

# 特征重要性
viz = FeatureImportances(model, relative=False)
viz.fit(X, y)
viz.show()

13.2 与Pandas Profiling结合

from pandas_profiling import ProfileReport

profile = ProfileReport(df, title='Data Profile')
profile.to_file("report.html")

# 提取关键可视化
corr_plot = profile.description_set['correlations']['pearson']
missing_plot = profile.description_set['missing']

14. 版本兼容性指南

14.1 Seaborn版本差异处理

常见API变更应对方案:

功能 v0.11-写法 v0.12+写法 兼容方案
分布图 sns.distplot sns.histplot 检查版本后动态调用
回归图 sns.regplot sns.lmplot 优先使用 regplot
多面板图 sns.factorplot sns.catplot 函数别名检查
颜色控制 palette 参数 hue 嵌套控制 统一使用 palette

兼容性代码示例:

import seaborn as sns
from distutils.version import LooseVersion

if LooseVersion(sns.__version__) < LooseVersion('0.12'):
    sns_hist = sns.distplot
else:
    sns_hist = sns.histplot

14.2 与Matplotlib样式集成

统一样式配置方案:

# 基础样式
plt.style.use('seaborn')
sns.set_theme(style='whitegrid', 
             font='Arial',
             rc={
                 'axes.titlesize': 14,
                 'axes.labelsize': 12,
                 'xtick.labelsize': 10,
                 'ytick.labelsize': 10,
                 'figure.figsize': (10,6),
                 'figure.dpi': 100,
                 'savefig.dpi': 300
             })

# 颜色循环
sns.set_palette(sns.color_palette('husl', 8))

15. 项目实战案例

15.1 房价预测可视化方案

完整可视化工作流:

  1. 数据质量检查

    # 缺失值模式
    sns.heatmap(df.isnull(), cbar=False)
    
    # 异常值检测
    sns.boxplot(data=df[num_features], orient='h')
    
  2. 空间分布可视化

    # 地理热力图
    sns.scatterplot(x='longitude', y='latitude',
                   size='price', hue='price',
                   sizes=(20,200), palette='viridis',
                   data=df)
    
  3. 特征交互分析

    sns.lmplot(x='sqft_living', y='price',
              hue='waterfront', col='zipcode',
              col_wrap=3, data=df.sample(1000))
    

15.2 客户流失分析仪表板

分类问题可视化组合:

  1. 流失特征雷达图

    features = ['tenure', 'monthly_charges', 'total_charges']
    df_norm = (df[features] - df[features].mean()) / df[features].std()
    df_norm['churn'] = df['churn']
    
    sns.lineplot(data=df_norm.melt(id_vars='churn'),
                x='variable', y='value',
                hue='churn', err_style='band',
                palette='Set2')
    
  2. 关键指标趋势

    sns.relplot(x='tenure', y='monthly_charges',
               hue='churn', col='contract',
               kind='line', estimator=np.mean,
               ci=95, col_wrap=2, data=df)
    
  3. 模型解释可视化

    # SHAP摘要图
    explainer = shap.TreeExplainer(model)
    shap_values = explainer.shap_values(X_test)
    shap.summary_plot(shap_values, X_test)
    

16. 性能优化与大数据处理

16.1 分布式可视化方案

Dask集成示例:

import dask.dataframe as dd

ddf = dd.from_pandas(df, npartitions=4)

# 分布式计算直方图
hist = ddf['value'].compute().value_counts().sort_index()
sns.barplot(x=hist.index, y=hist.values)

16.2 采样策略对比

不同采样方法可视化效果:

方法 适用场景 代码实现 可视化保真度
随机采样 均匀分布数据 df.sample(1000)
分层采样 类别不平衡数据 df.groupby('class').sample(200)
聚类采样 保持数据结构 如上smart_sampling函数
时间窗口采样 时间序列数据 df.resample('W').first()

17. 交互式报告生成

17.1 自动化报告生成

使用Jupyter Notebook模板:

from IPython.display import HTML, display

def generate_report(df, model, X_test, y_test):
    """生成交互式HTML报告"""
    
    # 1. 数据概览
    display(HTML("<h2>1. Data Overview</h2>"))
    auto_eda(df, target=target)
    
    # 2. 模型评估
    display(HTML("<h2>2. Model Performance</h2>"))
    plot_roc_curve(model, X_test, y_test)
    plot_confusion_matrix(model, X_test, y_test)
    
    # 3. 特征重要性
    display(HTML("<h2>3. Feature Importance</h2>"))
    plot_shap_summary(model, X_test.sample(100))
    
    # 导出为HTML
    plt.savefig('report.png')
    display(HTML(f'<img src="report.png" width="800">'))

17.2 参数化可视化模板

使用Jinja2创建模板:

from jinja2 import Template

viz_template = Template("""
{% for fig in figures %}
<section>
    <h3>{{ fig.title }}</h3>
    <img src="{{ fig.path }}" width="800">
    <p>{{ fig.caption }}</p>
</section>
{% endfor %}
""")

figures = [
    {'title': 'Data Distribution',
     'path': 'dist.png',
     'caption': 'Histogram of target variable'},
    {'title': 'Feature Importance',
     'path': 'importance.png',
     'caption': 'SHAP values for top features'}
]

HTML(viz_template.render(figures=figures))

18. 前沿可视化技术

18.1 动态可视化

使用Matplotlib动画:

from matplotlib.animation import FuncAnimation

fig, ax = plt.subplots(figsize=(10,6))
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro', alpha=0.3)

def init():
    ax.set_xlim(0, 10)
    ax.set_ylim(0, 10)
    return ln,

def update(frame):
    xdata.append(np.random.rand())
    ydata.append(np.random.rand())
    ln.set_data(xdata, ydata)
    return ln,

ani = FuncAnimation(fig, update, frames=100,
                   init_func=init, blit=True)
HTML(ani.to_jshtml())

18.2 3D决策边界

from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111, projection='3d')

# 生成网格
xx, yy = np.meshgrid(np.linspace(-3,3,50),
                    np.linspace(-3,3,50))
zz = model.decision_function(np.c_[xx.ravel(),
                                  yy.ravel()]).reshape(xx.shape)

# 绘制表面
ax.plot_surface(xx, yy, zz, rstride=1, cstride=1,
               cmap=plt.cm.coolwarm, alpha=0.6)

# 绘制数据点
ax
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐