机器学习 pipeline 可视化

2020-10-30 09:50:04 浏览数 (1)

一些有趣的技术合集,用于机器学习 pipeline 不同部分的可视化。

作者:Pier Paolo Ippolito 编译:McGL

引言

作为任何数据科学项目的一部分,数据可视化在理解更多可用数据和识别任何主要模式方面发挥着重要作用。

如果有可能使分析中的机器学习部分尽可能直观,那不是很好吗?

在本文中,我们将探索一些技术,可以帮助我们面对这一挑战,如: 平行坐标图,摘要数据表,绘制人工神经网络图等等。

本文中使用的所有代码都可以在我的 Github (pierpaolo28/Data-Visualization)上免费获得。

技巧:

超参数优化

超参数优化是机器/深度学习中最常见的动作之一。机器学习模型的调优是最佳化问题的一种。我们有一组超参数(例如:学习率,隐藏单元的数量,等等......)我们的目标是找出他们的值的正确组合,这可以帮助我们得到最小值(如损失)或最高值(如函数的准确性)。

此类任务的最佳解决方案之一是使用平行坐标图(parallel coordinates plot)(图1)。使用这种类型的图,我们可以很容易地一起比较不同的变量(例如特征),以发现可能的关系。在超参数优化的情况下,这可以作为一个简单的工具来检查什么样的参数组合可以给我们提供最大的测试精度。数据分析中平行坐标图的另一个可能用途是检查数据帧中不同特征之间的值之间的关系。

图1,是一个使用 Plotly 创建的实用示例。

代码语言:javascript复制
import plotly.express as px

fig = px.parallel_coordinates(df2, color="mean_test_score", 
          labels=dict(zip(list(df2.columns), 
          list(['_'.join(i.split('_')[1:]) for i in df2.columns]))),
          color_continuous_scale=px.colors.diverging.Tealrose,
          color_continuous_midpoint=27)

fig.show()

图1: 平行坐标超参数优化图

为了在 Python 中创建平行坐标图,可以使用不同的技术,如 Pandas、 Yellowbrick、 Matplotlib 或 Plotly。使用所有这些不同方法的一步一步解释的例子都可以在我的 notebook 链接(https://www.kaggle.com/pierpaolo28/parallel-coordinates-plots?scriptVersionId=35973765)中找到。

最后,另一个可以用来创建这种类型的图的解决方案是Weights & Biases Sweeps。Weights & Biases是一个免费的工具,可以用来自动创建不同的机器学习任务(如学习率曲线,图模型等等)的图和日志。个人和团体都适用。

Data Wrapper

Data Wrapper是一个免费的在线工具,专为创建专业图表设计。例如,这个工具被《纽约时报》、 Vox 和《连线》等杂志的文章所使用。不需要登录,所有的过程都可以在线完成。今年这个工具额外创建了一个 Python wrapper,可以使用以下方法轻松安装:

代码语言:javascript复制
pip install datawrapper

为了使用 Python API,我们还需要注册 Data Wrapper,进入设置并创建一个 API Key。使用这个 API 键,我们就可以远程使用Data Wrapper。

现在,我们可以很容易地创建一个条形图,例如,通过以下几行代码,并传递一个 Pandas 数据帧作为 create _ chart 函数的输入。

代码语言:javascript复制
from datawrapper import Datawrapper
dw = Datawrapper(access_token = "TODO")
games_chart = dw.create_chart(title = "Most Frequent Game Publishers", chart_type = 'd3-bars', data = df)
dw.update_description(
    games_chart['id'],
    source_name = 'Video Game Sales',
    source_url = 'https://www.kaggle.com/gregorut/videogamesales',
    byline = 'Pier Paolo Ippolito',
)
dw.publish_chart(games_chart['id'])

得到的图表如下所示。

一旦我们的图表发布了,我们就可以在我们的 Data Wrapper 帐户的创建的图表列表中找到它。点击我们的图表,然后我们会找到一个不同选项的列表,我们可以使用以便轻松地共享我们的图表(例如:嵌入,HTML,PNG,等等)。

Plotly预测表

在处理时间序列数据时,有时如果能够快速理解我们的模型在哪些数据点上表现不佳真的很方便,这样可以尝试理解它可能面临的限制。

一种可能的方法是创建一个汇总表,其中包括实际值和预测值,以及某种形式的度量,用于总结一个数据点的预测好坏。

使用 Plotly,可以通过创建一个绘图函数轻松实现:

代码语言:javascript复制
import chart_studio.plotly as py
import plotly.graph_objs as go
from plotly.offline import init_notebook_mode, iplot
init_notebook_mode(connected=True)
import plotly
def predreport(y_pred, Y_Test):
    diff = y_pred.flatten() - Y_Test.flatten()
    perc = (abs(diff)/y_pred.flatten())*100
    priority = []
    for i in perc:
        if i > 0.4:
            priority.append(3)
        elif i> 0.1:
            priority.append(2)
        else:
            priority.append(1)
    print("Error Importance 1 reported in ", priority.count(1),
          "casesn")
    print("Error Importance 2 reported in", priority.count(2), 
          "casesn")                                 
    print("Error Importance 3 reported in ", priority.count(3),    
          "casesn")
    colors = ['rgb(102, 153, 255)','rgb(0, 255, 0)', 
              'rgb(255, 153, 51)', 'rgb(255, 51, 0)']
    fig = go.Figure(data=[go.Table(header=
                    dict(
                        values=['Actual Values', 'Predictions', 
                        '% Difference', "Error Importance"],
                        line_color=[np.array(colors)[0]],
                        fill_color=[np.array(colors)[0]],
                                    align='left'),
                    cells=dict(
                       values=[y_pred.flatten(),Y_Test.flatten(),
                               perc, priority], 
                       line_color=[np.array(colors)[priority]],
                       fill_color=[np.array(colors)[priority]],  
                                    align='left'))])
    init_notebook_mode(connected=False)
    py.plot(fig, filename = 'Predictions_Table', auto_open=True)
    fig.show()

然后调用这个函数会得到以下输出(请随意测试图3中的表) :

代码语言:javascript复制
Error Importance 1 reported in  34 cases 

Error Importance 2 reported in  13 cases 

Error Importance 3 reported in  53 cases

图3: 预测表

决策树

决策树是机器学习模型中最容易解释的类型之一。由于它们的基本结构,很容易通过查看树的不同分支的条件来检查算法是如何决定的。此外,决策树也可以作为一种特征选择技术,考虑到算法将那些对我们期望的分类/回归任务最有价值的特征置于树的顶层。通过这种方式,树底部的特征可以被丢弃,因为它携带的信息更少。

可视化分类/回归决策树的最简单方法之一是使用 sklearn.tree 中的 export_graphviz。在本文中,使用了 dtreevz 库提供的一种不同的、更完整的方法。

使用这个库,只需使用以下几行代码就可以创建一个分类决策树:

代码语言:javascript复制
from dtreeviz.trees import *

viz = dtreeviz(clf,
               X_train,
               y_train.values,
               target_name='Genre',
               feature_names=list(X.columns),
               class_names=list(labels.unique()),
               histtype='bar', 
               orientation ='TD')
              
viz

得到的绘图如图4所示。

图4: 分类决策树

在图4中,不同的类用不同的颜色表示。所有不同类的特征分布都表示在树的起始节点上。只要我们向下移动每个分支,算法就会尝试使用每个节点图下面描述的特征最好地分离不同的分布。沿着分布生成的圆表示在跟随某个节点后正确分类的元素数量,元素数量越大,圆的大小就越大。

图5展示了一个使用决策树回归器的例子。

图5: 决策树回归器

决策边界

决策边界是图形化地理解机器学习模型如何进行预测的最简单方法之一。在 Python 中绘制决策边界的最简单方法之一是使用 Mlxtend。这个库实际上可以用来绘制机器学习和深度学习模型的决策边界。图6显示了一个简单的例子。

代码语言:javascript复制
from mlxtend.plotting import plot_decision_regions 
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import itertools
gs = gridspec.GridSpec(2, 2)

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

clf1 = LogisticRegression(random_state=1,
                          solver='newton-cg',
                          multi_class='multinomial')
clf2 = RandomForestClassifier(random_state=1, n_estimators=100)
clf3 = GaussianNB()
clf4 = SVC(gamma='auto')

labels = ['Logistic Regression','Random Forest','Naive Bayes','SVM']
for clf, lab, grd in zip([clf1, clf2, clf3, clf4],
                         labels,
                         itertools.product([0, 1], repeat=2)):

    clf.fit(X_Train, Y_Train)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X_Train, Y_Train, clf=clf, legend=2)
    plt.title(lab)

plt.show()

图6: 绘制决策边界

Mlxtend 的一些可能的替代方案是: Yellowbrick、 Plotly 或者一个普通的 Sklearn 和 Numpy 实现。使用所有这些不同方法的一步一步的例子都可以在我的notebook的这个链接(Machine Learning Visualization 5)中找到。

此外,在训练期间的决策边界融合的不同的动画版本可在我的网站上的这个链接(Animated Training ML Model)看到。

绘制决策边界的一个主要局限性是它们只能在二维或三维空间中很容易地可视化。由于这些限制,因此在绘制决策边界图之前,大多数时候可能需要降低输入特征的维数(使用某种形式的特征提取技术)。

人工神经网络

另一个技术,在创建新的神经网络架构时可视化他们的结构是非常有用的。使用 ANN Visualiser 可以很容易地做到这一点(图7)。

代码语言:javascript复制
from keras.models import Sequential
from keras.layers import Dense
from ann_visualizer.visualize import ann_viz

model = Sequential()
model.add(Dense(units=4,activation='relu',
                  input_dim=7))
model.add(Dense(units=4,activation='sigmoid'))
model.add(Dense(units=2,activation='relu'))

ann_viz(model, view=True, filename="example", title="Example ANN")

图7: ANN图

Livelossplot

在训练和验证过程中,能够自动绘制实时神经网络的损失和准确率,对于即时了解网络是否随着时间的推移而取得进展有很大帮助。使用 Livelossplot可以很容易地做到这点。

在图8中,是一个在 Pytorch 中训练一个变分自动编码器(VAE)时实时创建的损失图的例子。

图8: 实时VAE训练

使用 Livelossplot,可以很容易地通过存储我们想要记录的所有指标在字典中,并在每次迭代结束时更新图表来实现。如果我们有兴趣创建多个图形(例如:一个是损失,另一个是整体的准确率)。

代码语言:javascript复制
from livelossplot import PlotLosses
liveloss = PlotLosses()
for epoch in range(epochs):
    logs = {}
    for phase in ['train', 'val']:
        losses = []
        
        if phase == 'train':
            model.train()
        else:
            model.eval()
        
        for i, (inp, _) in enumerate(dataloaders[phase]):
            out, z_mu, z_var = model(inp)
            rec=F.binary_cross_entropy(out,inp,reduction='sum')/
                                       inp.shape[0]
            kl=-0.5*torch.mean(1 z_var-z_mu.pow(2)-torch.exp(z_mu))
            loss = rec   kl
            losses.append(loss.item())
        
            if phase == 'train':
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
        
        prefix = ''
        if phase == 'val':
            prefix = 'val_'
        logs[prefix   'loss'] = np.mean(losses)
    liveloss.update(logs)
    liveloss.send()

Livelossplot 还可以与其他库如 Keras,Pytorch-Lighting,Bokeh 等一起使用。

变分自动编码器

变分自动编码器(VAE)是一种用于创建一些输入数据的潜在表示的概率生成模型(如图片),这种表示能够简明地理解原始数据并从中生成全新的数据(例如用不同形象的汽车设计训练 VAE 模型,然后可以使模型创造全新的想象的汽车设计)。

继续从使用 Livelossplot 训练的变分 Autoencoder 示例,我们甚至可以通过检查潜在空间(图9)如何从一个迭代变化到另一个迭代(即我们的模型随着时间的推移改进了多少,以区分不同的类) ,使我们的模型更有趣。

这可以很容易地通过在前面的训练循环中添加以下函数来实现:

代码语言:javascript复制
def latent_space(model, train_set, it=''):
    x_latent = model.enc(train_set.data.float())
    plt.figure(figsize=(10, 7))
    plt.scatter(x_latent[0][:,0].detach().numpy(), 
                x_latent[1][:,1].detach().numpy(), 
                c=train_set.targets)
    plt.colorbar()
    plt.title("VAE Latent Space", fontsize=20)
    plt.xlabel("X", fontsize=18)
    plt.ylabel("Y", fontsize=18)
    plt.savefig('VAE_space' str(it) '.png', format='png', dpi=200)
    plt.show()

图9: VAE潜在空间进化

最后,一个类似的过程可以被应用,来实时可视化我们的 VAE 如何从迭代到迭代改进生成真实的图像(图10)。

代码语言:javascript复制
def manifold(model, it='', n=18, size=28): 
    result = torch.zeros((size * n, size * n))
    # Defyining grid space
    s, s2 = torch.linspace(-7, 7, n), torch.linspace(7, -7, n)
    grid_x, grid_y = torch.std(s)*s, torch.std(s2)*s2
    for i, y_ex in enumerate(grid_x):
        for j, x_ex in enumerate(grid_y):
            z_sample = torch.repeat_interleave(torch.tensor([
                       [x_ex, y_ex]]),repeats=batch_size, dim=0)
            x_dec = model.dec(z_sample)
            element = x_dec[0].reshape(size, size).detach()
            result[i * size: (i   1) * size, 
                   j * size: (j   1) * size] = element
    plt.figure(figsize=(12, 12))
    plt.title("VAE Samples", fontsize=20)
    plt.xlabel("X", fontsize=18)
    plt.ylabel("Y", fontsize=18)
    plt.imshow(result, cmap='Greys')
    plt.savefig('VAE' str(it) '.png', format='png', dpi=300)
    plt.show()

图10: VAE 渐渐改进生成新的数字

我个人网站有一个使用 ONNX 在线部署的变分自动编码器的实际演示,可以实时进行推理。链接:https://pierpaolo28.github.io/Projects/ONNX/home.html?fbclid=IwAR13tKnQFfobSq4udV-N9FMfFZ6wUmAvU7GVn5yl0Cj4ttOw3uyl6TNNbMw

Word Embeddings

神经网络 Embeddings 是为了学习如何将某种形式的类别数据转换为数值数据而设计的一类神经网络。与使用其他技术(如 One Hot Encoding)相比,使用 Embeddings 可能有相当大的优势,因为在转换数据时,它们能够了解数据的特征,从而构建一个更简洁的表示(创建一个潜在空间)。最著名的两种预训练的 word embeddings 是 word2vec 和 Glove。

一个简单的例子,我们现在要绘制一个代表不同图书作者的 embed 空间。首先,我们需要在一些可用的数据上创建一个训练模型,然后访问模型 embedded 层(在这种情况下称为embed)的训练权重,并将它们存储在一个数据帧中。完成这个过程后,我们只需绘制三个不同的坐标(图11)。

代码语言:javascript复制
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d, Axes3D
embedding_weights=pd.DataFrame(model.embed.weight.detach().numpy())
embedding_weights.columns = ['X1','X2','X3']
fig = plt.figure(num=None, figsize=(14, 12), dpi=80, 
                 facecolor='w', edgecolor='k')
ax = plt.axes(projection='3d')
for index, (x, y, z) in enumerate(zip(embedding_weights['X1'], 
                                      embedding_weights['X2'], 
                                      embedding_weights['X3'])):
    ax.scatter(x, y, z, color='b', s=12)
    ax.text(x, y, z, str(df.authors[index]), size=12, 
            zorder=2.5, color='k')
ax.set_title("Word Embedding", fontsize=20)
ax.set_xlabel("X1", fontsize=20)
ax.set_ylabel("X2", fontsize=20)
ax.set_zlabel("X3", fontsize=20)
plt.show()

在这个例子中,网络的 embedding 维数被直接设置为3,以便于创建三维可视化。另一种可能的解决方案可能是使用较高的 embedding 输出大小,然后应用某种形式的特征提取技术(例如t-SNE,PCA 等)以便观察结果。

另一个可以用来可视化分类数据的有趣技术是 Wordclouds (图12)。例如,这种类型的表示可以通过创建一个图书作者名字的字典以及在数据集中他们各自的频率计数来实现。然后,在数据集中出现得更频繁的作者将用更大的字体大小在图中表示。

代码语言:javascript复制
from wordcloud import WordCloud
d = {}
for x, a in zip(df.authors.value_counts(),
                df.authors.value_counts().index):
    d[a] = x
wordcloud = WordCloud()
wordcloud.generate_from_frequencies(frequencies=d)
plt.figure(num=None, figsize=(12, 10), dpi=80, facecolor='w',
           edgecolor='k')
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")
plt.title("Word Cloud", fontsize=20)
plt.show()

图12: Wordcloud 例子

像往常一样,完整的代码可以在我的 Github (pierpaolo28/Data-Visualization)上找到。

可解释的人工智能

可解释的人工智能如今是一个不断发展的研究领域。在决策应用(如就业)中使用人工智能最近引起了个人和当局的一些关注。这是因为,在使用深度神经网络时,目前还不可能(至少在很大程度上)理解算法在执行预定任务时执行的决策过程。由于决策过程缺乏透明度,公众可能会对模型本身的可信度感到困惑。因此,为了防止人工智能模型中出现任何形式的偏见,对可解释人工智能的需求正在成为下一个确定的进化步骤。在过去的几年中,不同的可视化技术被引入,以使机器学习更加易于理解,例如:

  • 卷积神经网络滤波器和特征图的研究
  • 图网络
  • 基于贝叶斯的模型
  • 因果推理应用于机器学习
  • 本地/全局代理模型
  • 引入局部可解释模型-无关解释(LIME)和 Shapley 值

如果你对如何使机器学习模型更加易于理解感兴趣,目前在 Python 中为了将可解释的人工智能应用到深度学习中,两个最有趣的库是 Pytorch的Captum 和 XAI。

由于这个研究领域正在不断改进,我将在未来的一篇专门讨论可解释人工智能的文章中涵盖所有这些不同的主题(甚至更多)。

总结

如果你有兴趣了解更多的机器学习可视化技术,Python Yellowbrick 库正是聚焦这个话题。提供的可视化工具包括: 特征排序、 ROC/AUC 曲线、 K-Elbow 图和各种文本可视化技术。

最后,在过去的几年里,为了使机器学习的可视化更加容易,不同的框架已经开始进化了,比如 TensorBoard,Weights & Biases 和 Neptune.ai。

希望你喜欢这篇文章,谢谢你的阅读!

来源:https://towardsdatascience.com/machine-learning-visualization-fcc39a1e376a

0 人点赞