我目前正在处理分类问题,并希望创建特征重要性的可视化。我使用Python XGBoost包,它已经提供了功能重要性图。但是,我找到了shap(https://github.com/slundberg/shap),这是一个Python库,可以根据树分类器为特征重要性创建非常好的图。一切正常,我也可以将创建的图保存为PNG,但是,如果我尝试将其保存为PDF或SVG,我会得到一个例外。这是我在做的事情:
首先,我训练XGBoost模型,然后用bst
表示模型。
train = remove_labels_for_binary_df(dataset_fc_baseline_1[0].train)
test = remove_labels_for_binary_df(dataset_fc_baseline_1[0].test)
results, bst = xgboost_with_bst(*transform_feat_to_num(train, test))
然后我创建shap值,使用这些值创建摘要图并保存创建可视化。如果我将情节保存为plt.savefig('shap.png')
,一切正常。
import shap
import matplotlib.pyplot as plt
shap.initjs()
explainer = shap.TreeExplainer(bst)
shap_values = explainer.shap_values(train)
fig = shap.summary_plot(shap_values, train, show=False)
plt.savefig('shap.png')
但是,我需要PDF或SVG图而不是png,因此尝试用plt.savefig('shap.pdf')
保存它,它通常工作正常,但会为shap图产生以下异常。
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-39-49d17973f438> in <module>()
1 fig = shap.summary_plot(shap_values, train, show=False)
----> 2 plt.savefig('shap.pdf')
C:\Users\Studio\Anaconda3\lib\site-packages\matplotlib\pyplot.py in
savefig(*args, **kwargs)
708 def savefig(*args, **kwargs):
709 fig = gcf()
--> 710 res = fig.savefig(*args, **kwargs)
711 fig.canvas.draw_idle() # need this if 'transparent=True' to reset
colors
712 return res
C:\Users\Studio\Anaconda3\lib\site-packages\matplotlib\figure.py in
savefig(self, fname, **kwargs)
2033 self.set_frameon(frameon)
2034
-> 2035 self.canvas.print_figure(fname, **kwargs)
2036
2037 if frameon:
C:\Users\Studio\Anaconda3\lib\site-packages\matplotlib\backend_bases.py in
print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format,
**kwargs)
2261 orientation=orientation,
2262 bbox_inches_restore=_bbox_inches_restore,
-> 2263 **kwargs)
2264 finally:
2265 if bbox_inches and restore_bbox:
C:\Users\Studio\Anaconda3\lib\site-
packages\matplotlib\backends\backend_pdf.py in print_pdf(self, filename,
**kwargs)
2584 RendererPdf(file, image_dpi, height, width),
2585 bbox_inches_restore=_bbox_inches_restore)
-> 2586 self.figure.draw(renderer)
2587 renderer.finalize()
2588 if not isinstance(filename, PdfPages):
C:\Users\Studio\Anaconda3\lib\site-packages\matplotlib\artist.py in
draw_wrapper(artist, renderer, *args, **kwargs)
53 renderer.start_filter()
54
---> 55 return draw(artist, renderer, *args, **kwargs)
56 finally:
57 if artist.get_agg_filter() is not None:
C:\Users\Studio\Anaconda3\lib\site-packages\matplotlib\figure.py in
draw(self, renderer)
1473
1474 mimage._draw_list_compositing_images(
-> 1475 renderer, self, artists, self.suppressComposite)
1476
1477 renderer.close_group('figure')
C:\Users\Studio\Anaconda3\lib\site-packages\matplotlib\image.py in
_draw_list_compositing_images(renderer, parent, artists, suppress_composite)
139 if not_composite or not has_images:
140 for a in artists:
--> 141 a.draw(renderer)
142 else:
143 # Composite any adjacent images together
C:\Users\Studio\Anaconda3\lib\site-packages\matplotlib\artist.py in
draw_wrapper(artist, renderer, *args, **kwargs)
53 renderer.start_filter()
54
---> 55 return draw(artist, renderer, *args, **kwargs)
56 finally:
57 if artist.get_agg_filter() is not None:
C:\Users\Studio\Anaconda3\lib\site-packages\matplotlib\axes\_base.py in
draw(self, renderer, inframe)
2605 renderer.stop_rasterizing()
2606
-> 2607 mimage._draw_list_compositing_images(renderer, self,
artists)
2608
2609 renderer.close_group('axes')
C:\Users\Studio\Anaconda3\lib\site-packages\matplotlib\image.py in
_draw_list_compositing_images(renderer, parent, artists, suppress_composite)
139 if not_composite or not has_images:
140 for a in artists:
--> 141 a.draw(renderer)
142 else:
143 # Composite any adjacent images together
C:\Users\Studio\Anaconda3\lib\site-packages\matplotlib\artist.py in
draw_wrapper(artist, renderer, *args, **kwargs)
58 renderer.stop_filter(artist.get_agg_filter())
59 if artist.get_rasterized():
---> 60 renderer.stop_rasterizing()
61
62 draw_wrapper._supports_rasterization = True
C:\Users\Studio\Anaconda3\lib\site-
packages\matplotlib\backends\backend_mixed.py in stop_rasterizing(self)
128
129 height = self._height * self.dpi
--> 130 buffer, bounds =
self._raster_renderer.tostring_rgba_minimized()
131 l, b, w, h = bounds
132 if w > 0 and h > 0:
C:\Users\Studio\Anaconda3\lib\site-
packages\matplotlib\backends\backend_agg.py in tostring_rgba_minimized(self)
138 [extents[0] + extents[2], self.height - extents[1]]]
139 region = self.copy_from_bbox(bbox)
--> 140 return np.array(region), extents
141
142 def draw_path(self, gc, path, transform, rgbFace=None):
ValueError: negative dimensions are not allowed
你知道如何解决这个问题吗?提前致谢!
这是an issue between NumPy and matplotlib在使用rasterized=True
(shap does if there are more than 500 datapoints)绘图时引起的,并且已在最新版本的matplotlib中得到解决。
以pdf格式保存:
plt.savefig("shap.pdf", format='pdf', dpi=1000, bbox_inches='tight')
保存为eps:
plt.savefig("shap.eps", format='eps', dpi=1000, bbox_inches='tight')
欲获得更多信息:
matplotlib.pyplot.savefig matplotlib
检查链接以了解更多信息,例如bbox_inches ='tight'的含义是什么。