作为任何数据科学项目的一部分,数据可视化在了解更多可用数据和识别任何主要模式方面发挥着重要作用。
如果能够使分析中的机器学习部分尽可能直观,那不是很好吗?
在本文中,我们将探讨一些可以帮助我们应对这一挑战的技术,例如:平行坐标图、汇总数据表、绘制人工神经网络图等等。
超参数优化是机器/深度学习中最常见的活动之一。机器学习模型调优是一种优化问题。我们有一组超参数(例如学习率、隐藏单元的数量等),我们的目标是找出它们值的正确组合,这可以帮助我们找到最小值(例如:损失)或最大值(例如:准确率)。
在我之前的一篇文章中,我详细介绍了我们可以在这个范围内使用什么样的技术以及如何在 3D 空间中测试它们,在这篇文章中,我将向您展示我们如何实现这一点,以便在一个二维空间报告。
此类任务的最佳解决方案之一是使用平行坐标图(图1)。使用这种类型的图,我们实际上可以很容易地比较不同的变量(例如:特征),以发现可能的关系。在超参数优化的情况下,这可以用作一个简单的工具来检查哪些参数组合可以为我们提供最大的测试精度。数据分析中平行坐标图的另一种可能用途是检查数据框中不同特征之间的值关系。
在图1中,提供了一个使用 Plotly 创建的实际示例。
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中找到。
最后,可用于创建此类图的另一种可能的解决方案是使用Weights & Biases Sweeps功能。 Weights & Biases是一个免费工具,可用于为个人或团队自动创建不同机器学习任务(例如:学习曲线、图形模型等)的图表和日志。
Data Wrapper 是专为专业图表创建而设计的免费在线工具。 例如,该工具用于《纽约时报》、Vox 和 WIRED 等期刊的文章中。 无需登录,所有过程都可以完全在线完成。
今年还为此工具创建了一个 Python wrapper。 这可以使用以下方法轻松安装:
pip install datawrapper
为了使用 Python API,我们还需要注册 Data Wrapper,进入设置并创建一个 API Key。 使用这个 API Key,我们就可以远程使用 Data Wrapper。
此时,我们可以轻松地创建条形图,例如,使用以下几行代码并将 Pandas 数据框作为 create_chart
函数的输入。
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'])
生成的图表如下图所示。
图 2:Data Wrapper 条形图
发布图表后,我们可以在 Data Wrapper Account 的已创建图表列表中找到它。 单击我们的图表,我们将找到一个不同选项列表,我们可以使用这些选项轻松共享我们的图表(例如:Embed、HTML、PNG 等)。 此链接提供了所有不同类型的受支持图表的完整列表。
在处理时间序列数据时,有时能够非常方便地快速了解我们的模型在哪些数据点上表现不佳,以便尝试了解它可能面临的限制。
一种可能的方法是创建一个汇总表,其中包含实际值和预测值以及某种形式的指标来总结预测数据点的好坏程度。
使用 Plotly,这可以通过创建绘图函数轻松完成:
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 plotlydef 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),
"cases\n")
print("Error Importance 2 reported in", priority.count(2),
"cases\n")
print("Error Importance 3 reported in ", priority.count(3),
"cases\n")
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()
调用此函数将产生以下输出:
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
。 在本文中,使用 dtreeviz
库提供了一种不同且更完整的方法。
使用该库,只需使用以下几行代码即可创建分类决策树:
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 中,不同的类别用不同的颜色表示。 所有不同类的特征分布都在树的起始节点中表示。 只要我们向下移动每个分支,算法就会尝试使用每个节点图下方描述的特征来最好地分离不同的分布。 分布旁边生成的圆圈表示跟随某个节点后正确分类的元素数量,元素数量越多,圆圈的大小越大。
图 5 显示了一个使用决策树回归器的示例。
图 5:决策树回归器
决策边界是以图形方式了解机器学习模型如何进行预测的最简单方法之一。 在 Python 中绘制决策边界的最简单方法之一是使用 Mlxtend。 该库实际上可用于绘制机器学习和深度学习模型的决策边界。 图 6 显示了一个简单的示例。
from mlxtend.plotting import plot_decision_regions
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import itertoolsgs = 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 实现。 使用所有这些不同方法的分步示例可在此链接的我的笔记本中找到。
此外,我的网站上的此链接上提供了在训练期间收敛的不同动画版本的决策边界。
绘制决策边界的主要限制之一是它们只能在两个或三个维度上轻松可视化。 由于这些限制,因此大多数时候可能需要在绘制决策边界之前减少输入特征的维数(使用某种形式的特征提取技术)。
另一种在创建新的神经网络架构时非常有用的技术是可视化它们的结构。 这可以使用 ANN Visualiser 轻松完成(图 7)。
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 轻松完成。
在图 8 中,提供了在训练变分自编码器 (VAE) 时在 Pytorch 中实时创建的损失图示例。
使用 Livelossplot,这可以通过将我们想要记录的所有指标存储在字典中并在每次迭代结束时更新绘图来轻松完成。 如果我们对创建多个图感兴趣(例如,一个用于损失,一个用于整体准确率),则可以应用相同的过程。
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-Lightning、Bokeh 等……
变分自编码器 (VAE) 是一种概率生成模型,用于创建一些输入数据(例如:图像)的潜在表示,能够简洁地理解原始数据并从中生成全新的数据(例如:训练 VAE 模型具有不同的汽车设计图像,然后可以建模以创建全新的富有想象力的汽车设计)。
继续使用 Livelossplot 训练的变分自编码器示例,我们甚至可以通过检查潜在空间(图 9)如何从一次迭代到另一次迭代来使我们的模型更有趣(以及因此我们的模型在区分不同类别方面随着时间的推移改进了多少)。
这可以通过在前面的训练循环中添加以下函数来轻松完成:
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)。
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 在线部署以进行动态推理的变分自编码器的实际演示。
神经网络嵌入是一类神经网络,旨在学习如何将某种形式的分类数据转换为数值数据。考虑到在转换数据时,他们能够了解其特征并因此构建更简洁的表示(创建潜在空间),因此使用嵌入比使用其他技术(例如 One Hot Encoding)具有相当大的优势。两种最著名的预训练词嵌入类型是 word2vec 和 Glove。
作为一个简单的例子,我们现在将绘制一个代表不同书籍作者的嵌入空间。首先,我们需要在一些可用数据上创建一个训练模型,然后访问模型嵌入层(在本例中称为嵌入)的训练权重并将它们存储在数据框(data frame)中。完成此过程后,我们只需绘制三个不同的坐标(图 11)。
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()
图 11:词嵌入
在此示例中,网络的嵌入维度已直接设置为 3,以便轻松创建 3D 可视化。 另一种可能的解决方案可能是使用更高的嵌入输出大小,然后应用某种形式的特征提取技术(例如:t-SNE、PCA 等)以可视化结果。
另一种可用于可视化分类数据的有趣技术是 Wordclouds(图 12)。 例如,这种类型的表示可以通过在数据集中创建书籍作者姓名及其各自频率计数的字典来实现。 在数据集中出现得更频繁的作者将在图中以更大的字体大小表示。
from wordcloud import WordCloudd = {}
for x, a in zip(df.authors.value_counts(),
df.authors.value_counts().index):
d[a] = xwordcloud = 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 帐户上找到。
如今,可解释人工智能是一个不断发展的研究领域。在决策应用(如:就业)中使用人工智能最近引起了个人和当局的一些担忧。这是因为,在使用深度神经网络时,目前(至少在完全程度上)理解算法在必须执行预定任务时执行的决策过程是不可能的。由于决策过程缺乏透明度,公众可能会对模型本身的可信度产生困惑。因此,为了防止人工智能模型中存在任何形式的偏见,对可解释人工智能的需求现在正成为热点。
在过去的几年里,为了使机器学习更易于解释,已经引入了不同的可视化技术,例如:
如果您有兴趣了解有关如何使机器学习模型更易于解释的更多信息,那么 Python 中当前可用于在深度学习中应用可解释 AI 的两个最有趣的库是 Pytorch 的 Captum 和 XAI。
由于这个研究领域在不断改进,我的目标是在未来的一篇专门讨论可解释人工智能的文章中涵盖所有这些不同的主题(以及更多主题)。
如果您有兴趣了解更多机器学习可视化技术,Python Yellowbrick 库高度关注该主题。提供的可视化工具的一些示例包括:特征排名、ROC/AUC 曲线、K-Elbow 图和各种文本可视化技术。
最后,在过去几年中,已经开始开发了不同的框架以使机器学习可视化更容易,例如:TensorBoard, Weights & Biases 和 Neptune.ai。
原文链接:Machine Learning Visualization