目录
- 导言 Pip安装上述软件包
- 神经网络体系结构和训练:NSL-tf、Kymatio和LARQ 神经网络学习-TensorflowKymatio:Python中的小波散射LARQ
- 训练后校准和性能基准:NetCal、PyEER和BayComp NetcalBaycompPyEER
- 部署前压力测试:PyOD、HyPPO和Gradio PYODHyppoGradio
- 文档/宣传: Jupyter

可用资源:
- Github Repo,包含所有图像、代码:https://github.com/vinayprabhu/Favorite_PyPi_2020
- pdf格式:https://github.com/vinayprabhu/Favorite_PyPi_2020/blob/main/PyPi_2020_collage.pdf
- Colab笔记本:https://github.com/vinayprabhu/Favorite_PyPi_2020/blob/main/Colab_Pypi_Top10.ipynb
- HTML文档: https://github.com/vinayprabhu/Favorite_PyPi_2020/blob/main/Top_Pypi_2020.html
- PDF格式的笔记本: https://github.com/vinayprabhu/Favorite_PyPi_2020/blob/main/Top_Pypi_2020.pdf
介绍
“开源的力量就是人民的力量、人民的规则”——菲利普·卡恩
我支持Python作为机器学习者或数据科学家的通用语言。
我的日常工作流程包括对杂乱无章的现实世界数据做出快速反应。对我来说,研究生院和工业界之间的一个主要区别是我需要经常从头开始实现算法。一旦过了假设构建阶段,我会快速查找PyPi存储库,以检查是否已经有模块可使用。这之后通常是pip install *PACKAGE_NAME*。我发现自己站在开源巨人的肩膀上,我正利用他们精心的工作成果来扩展。
这篇文章的重点是机器学习管道,包括神经网络/深度学习。以下是10个PyPi包的基本介绍,涵盖:
a) 神经网络体系结构和训练:NSL-tf、Kymatio和LARQ
b) 训练后校准和性能基准:NetCal、PyEER和BayComp
c) 部署前压力测试:PyOD、HyPPO和Gradio
d) 文档/宣传:Jupyter
0:Pip安装上述软件包
!pipinstall--quietneural-structured-learning
!pipinstall--quietlarqlarq-zoo
!pipinstall--quietkymatio
!pipinstall--quietnetcal
!pipinstall--quietbaycomp
!pipinstall--quietpyeer
!pipinstall--quietpyod
!pipinstall--quiethyppo
!pipinstall--quietgradio
!pipinstall--quietjupyter_to_medium
神经网络体系结构和训练:NSL-tf、Kymatio和LARQ
1:神经网络学习-Tensorflow
机器学习中大多数现成分类算法的核心是先验知识的设置。简单地说,算法的设计是建立在训练集(以及测试集)中的样本是独立的、同分布的假设基础上的。然而,在现实中,这很少成立,而且样本之间存在相关性,可以利用这些相关性来实现更好的准确性和解释性。
在广泛的应用场景中,这些相关性由一个底层图(G(V,E))捕获,该图可以共同挖掘或统计推断。例如,如果你正在执行文本tweet的情感分析,那么下面的社交图提供了模拟tweet所处的社会环境的重要线索,它为推文撰写的社会背景建模。然后,可以利用这些社会邻里信息来执行网络辅助分类。

我的博士论文“网络辅助分类和数据检测(Network Aided Classification and Detection of Data)”从字面上探讨了这种图形增强机器学习的科学和算法。在这中间,我看到Tensorflow发布了神经结构学习框架,以及一系列精心制作的教程,以及一个易于遵循的NSL colab-notebook示例,真是令人振奋。
在下面的示例单元格中,我们为对抗性环境中的标准MNIST数据集训练NSL增强型神经网络:
importtensorflowastf
importneural_structured_learningasnsl
importnumpyasnp
importmatplotlib.pyplotasplt
#准备数据
(x_train,y_train),(x_test,y_test)=tf.keras.datasets.mnist.load_data()
x_train,x_test=x_train/255.0,x_test/255.0
#创建一个基本模型——序列模型、函数模型或子类模型。
model=tf.keras.Sequential([
tf.keras.Input((28,28),name='feature'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128,activation=tf.nn.relu),
tf.keras.layers.Dense(10,activation=tf.nn.softmax)
])
#正则化
adv_config=nsl.configs.make_adv_reg_config(multiplier=0.2,adv_step_size=0.05)
adv_model=nsl.keras.AdversarialRegularization(model,adv_config=adv_config)
#编译、训练和评估。
adv_model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
adv_model.fit({'feature':x_train,'label':y_train},batch_size=32,epochs=5)
adv_model.evaluate({'feature':x_test,'label':y_test})
Epoch1/5
1875/1875[==============================]-39s2ms/step-loss:0.5215-sparse_categorical_crossentropy:0.4292-sparse_categorical_accuracy:0.8781-scaled_adversarial_loss:0.0924
Epoch2/5
1875/1875[==============================]-4s2ms/step-loss:0.1447-sparse_categorical_crossentropy:0.1171-sparse_categorical_accuracy:0.9663-scaled_adversarial_loss:0.0276
Epoch3/5
1875/1875[==============================]-4s2ms/step-loss:0.0944-sparse_categorical_crossentropy:0.0758-sparse_categorical_accuracy:0.9770-scaled_adversarial_loss:0.0186
Epoch4/5
1875/1875[==============================]-4s2ms/step-loss:0.0672-sparse_categorical_crossentropy:0.0536-sparse_categorical_accuracy:0.9840-scaled_adversarial_loss:0.0137
Epoch5/5
1875/1875[==============================]-4s2ms/step-loss:0.0532-sparse_categorical_crossentropy:0.0421-sparse_categorical_accuracy:0.9876-scaled_adversarial_loss:0.0111
313/313[==============================]-1s2ms/step-loss:0.0940-sparse_categorical_crossentropy:0.0751-sparse_categorical_accuracy:0.9761-scaled_adversarial_loss:0.0189
[0.09399436414241791,
0.07509651780128479,
0.9761000275611877,
0.018897896632552147]
Y_pred_test=adv_model.predict({'feature':x_test,'label':y_test})
Y_pred_test.shape
(10000,10)
2:Kymatio:Python中的小波散射
这里是ML中最好的秘密之一:许多简单的数据集(x-mnist/猫和狗/分类)不需要反向传播或SGD等算法来训练。
这些类是足够可分离的,并且体系结构的识别能力足够高,使用Grassmannian codebooks(https://arxiv.org/pdf/1911.07418.pdf)或小波滤波器进行初始化,然后使用“一层”的超平面学习就足以获得高精度分类器。
在这方面,Kymatio在小波滤波器世界中扮演了凯撒式的角色,将之前的所有孤立项目(如ScatNet、scattering.m、PyScatWave、,WaveletScattering.jl,和PyScatHarm集成到一个易于使用的便携框架中,该框架可以无缝地跨六个前端工作:NumPy(CPU)、scikit learn(CPU),纯PyTorch(CPU和GPU)、PyTorch+scikit cuda(GPU)、TensorFlow(CPU和GPU)和Keras(CPU和GPU)。
在下面的示例单元中,我们使用内置的Scattering2D类来训练另一个MNIST神经网络,在15个epoch内达到92.84%的准确率。这个软件包非常好地记录了大量有趣的例子.
#1:导入
fromtensorflow.keras.modelsimportModel
fromtensorflow.keras.layersimportInput,Flatten,Dense
fromkymatio.kerasimportScattering2D
#上面,我们从kymatio.keras导入了Scattering2D类。
#2:模型定义
inputs=Input(shape=(28,28))
x=Scattering2D(J=3,L=8)(inputs)
x=Flatten()(x)
x_out=Dense(10,activation='softmax')(x)
model_kymatio=Model(inputs,x_out)
print(model_kymatio.summary())
#3:编译和训练
model_kymatio.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
#然后我们使用model_kymatio.fit在MNIST数据的一个子集上训练。
model_kymatio.fit(x_train[:10000],y_train[:10000],epochs=15,
batch_size=64,validation_split=0.2)
#最后,我们根据提供的测试数据评估model_kymatio。
model_kymatio.evaluate(x_test,y_test)
Model:"model"
_________________________________________________________________
Layer(type)OutputShapeParam#
=================================================================
input_1(InputLayer)[(None,28,28)]0
_________________________________________________________________
scattering2d(Scattering2D)(None,217,3,3)0
_________________________________________________________________
flatten_1(Flatten)(None,1953)0
_________________________________________________________________
dense_2(Dense)(None,10)19540
=================================================================
Totalparams:19,540
Trainableparams:19,540
Non-trainableparams:0
_________________________________________________________________
313/313[==============================]-36s114ms/step-loss:0.6448-accuracy:0.9285
[0.6448228359222412,0.9284999966621399]
3:LARQ
去年LARQ发布了新的用于训练二值化神经网络(BNNs)的开源Python库,以及他们题为《Latent Weights Do Not Exist: Rethinking Binarized Neural Network Optimization.》的论文:https://papers.nips.cc/paper/2019/file/9ca8c9b0996bbf05ae7753d34667a6fd-Paper.pdf)。
虽然人们似乎对资源受限的设备部署的模型压缩非常感兴趣(这里有42个:https://awesomeopensource.com/projects/model-compression),从零开始训练二值化神经网络似乎是一个很好的选择,许多人似乎在一开始就忽视了这一点。
LARQ包可以帮助改变这方面的内容,因为它具有易用性、快速推理(卷积操作变成了带有二值化权重的xor/位移)、出色的文档和丰富的架构示例,人们可以通过一个模型动物园Zoo来获得它们:https://docs.larq.dev/zoo/。
我们有一个使用LARQ的40kb模型,使用这个工具包很容易。除了Zoo,包也伴随着一个高度优化的计算引擎,目前支持各种移动平台,还提供了一组TensorFlow Lite指令集。
在下面的示例代码单元中,我们训练了一个13.19kb的BNN,它在6个epoch内在MNIST数据集上的准确率为98.31%,并且还演示了从LARQ zoo中提取一个SOTA预训练的QuickNet模型,可以看到运行推断是非常容易的。
importlarqaslq
#模型定义
kwargs=dict(input_quantizer="ste_sign",
kernel_quantizer="ste_sign",
kernel_constraint="weight_clip")
model_bnn=tf.keras.models.Sequential()
#在第一层中,我们只二值化权重,而不二值化输入
model_bnn.add(lq.layers.QuantConv2D(32,(3,3),
kernel_quantizer="ste_sign",
kernel_constraint="weight_clip",
use_bias=False,
input_shape=(28,28,1)))
model_bnn.add(tf.keras.layers.MaxPooling2D((2,2)))
model_bnn.add(tf.keras.layers.BatchNormalization(scale=False))
model_bnn.add(lq.layers.QuantConv2D(64,(3,3),use_bias=False,**kwargs))
model_bnn.add(tf.keras.layers.MaxPooling2D((2,2)))
model_bnn.add(tf.keras.layers.BatchNormalization(scale=False))
model_bnn.add(lq.layers.QuantConv2D(64,(3,3),use_bias=False,**kwargs))
model_bnn.add(tf.keras.layers.BatchNormalization(scale=False))
model_bnn.add(tf.keras.layers.Flatten())
model_bnn.add(lq.layers.QuantDense(64,use_bias=False,**kwargs))
model_bnn.add(tf.keras.layers.BatchNormalization(scale=False))
model_bnn.add(lq.layers.QuantDense(10,use_bias=False,**kwargs))
model_bnn.add(tf.keras.layers.BatchNormalization(scale=False))
model_bnn.add(tf.keras.layers.Activation("softmax"))
#模型定义与训练
print(lq.models.summary(model_bnn))
model_bnn.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
x_train_bnn=x_train.reshape((60000,28,28,1))
x_test_bnn=x_test.reshape((10000,28,28,1))
model_bnn.fit(x_train_bnn,y_train,batch_size=64,epochs=6)
test_loss,test_acc=model_bnn.evaluate(x_test_bnn,y_test)
print(f"Testaccuracy{test_acc*100:.2f}%")
+sequential_1summary--------------------------+
|Totalparams93.6k|
|Trainableparams93.1k|
|Non-trainableparams468|
|Modelsize13.19KiB|
|Modelsize(8-bitFPweights)11.82KiB|
|Float-32Equivalent365.45KiB|
|CompressionRatioofMemory0.04|
|NumberofMACs2.79M|
|RatioofMACsthatarebinarized0.9303|
+----------------------------------------------+
None
313/313[==============================]-1s2ms/step-loss:0.3632-accuracy:0.9831
Testaccuracy98.31%
Y_pred_bnn=model_bnn.predict(x_test_bnn)
y_pred_bnn=np.argmax(Y_pred_bnn,axis=1)
(y_pred_bnn==y_test).mean()
0.9831
importtensorflow_datasetsastfds
importlarq_zooaslqz
fromurllib.requestimporturlopen
fromPILimportImage
#####################################
img_path="https://raw.githubusercontent.com/larq/zoo/master/tests/fixtures/elephant.jpg"
withurlopen(img_path)asf:
img=Image.open(f).resize((224,224))
x=tf.keras.preprocessing.image.img_to_array(img)
x=lqz.preprocess_input(x)
x=np.expand_dims(x,axis=0)
model=lqz.sota.QuickNet(weights="imagenet")
preds=model.predict(x)
pred_dec=lqz.decode_predictions(preds,top=5)[0]
print(f'Top-5predictions:{pred_dec}')
#####################################
pred_dec=lqz.decode_predictions(preds,top=5)[0]
plt.imshow(img)
plt.title(f'Topprediction:\n{pred_dec[0]}');
Top-5predictions:[('n02504458','African_elephant',0.7053231),('n01871265','tusker',0.2933379),('n02504013','Indian_elephant',0.001338586),('n02408429','water_buffalo',7.938418e-08),('n01704323','triceratops',7.2361296e-08)]

训练后校准和性能基准:NetCal、PyEER和BayComp
在本节中,我们将研究在训练后预部署场景中有用的包,在该场景中,目标是校准预训练模型的输出,并严格地对部署的多个模型的性能进行基准测试。
1:Netcal

我经常看到ML从业者认为softmax输出值和概率之间等价。其实他们什么都不是!它们在(0,1)范围内使得它们可以伪装成概率,但“原始的”softmax值是“未经校准的”。因此,训练后的校准是深度学习中一项快速增长的工作,本文提出的技术主要分为三类(见图2):
- 装箱Binning (例如:直方图装箱、保序回归、贝叶斯分位数装箱(BBQ)、近保序回归集成(ENIR))
- 缩放Scaling (例如:Logistic校准/Platt 缩放,温度缩放,贝塔校准)
- 混合缩放装箱(Hybrid scaling-binning(https://arxiv.org/pdf/1909.10155.pdf),Python库:https://pypi.org/project/inclusion-calibration)
关于上述所有的装箱和缩放技术,NetCal中提供了编写非常好的文档的实现。
在下面的单元格中,我们看到使用MNIST测试集(来自上面的NSL训练模型)上获得的softmax值来演示温度缩放的校准和可靠性图生成的用法。
#如果你还想尝试缩放-装箱的校准
#!pip3installgit+https://github.com/p-lambda/verified_calibration.git#PyPi-->Kaput
fromnetcal.scalingimportTemperatureScaling
importmatplotlib.pyplotasplt
###初始化和转换
temperature=TemperatureScaling()
temperature.fit(Y_pred_test,y_test)
calibrated=temperature.transform(Y_pred_test)
###可视化
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,4))
axes[0].matshow(Y_pred_test.T,aspect='auto',cmap='jet')
axes[0].set_title("OriginalUncalibratedsoftmax")
axes[0].set_xlabel("Testimageindex(10kimages)")
axes[0].set_ylabel("Classindex")
#axes[0].set_xticks([])
axes[1].matshow(calibrated.T,aspect='auto',cmap='jet')
axes[1].set_title("T-scaledsoftmax")
axes[1].set_xlabel("Testimageindex(10kimages)")
#axes[1].set_xticks([])
plt.tight_layout()
plt.show()

y_pred_nsl=np.argmax(Y_pred_test,axis=1)
ind_correct=np.where(y_pred_nsl==y_test)[0]
ind_wrong=np.where(y_pred_nsl!=y_test)[0]
plt.figure(figsize=(10,4))
foriinrange(5):
plt.subplot(1,5,i+1)
ind_i=ind_correct[i]
plt.imshow(x_test[ind_i],cmap='gray_r')
class_pred_i=np.argmax(Y_pred_test[ind_i,:])
softmax_uncalib_i=str(np.round(Y_pred_test[ind_i,class_pred_i],3))
softmax_calib_i=str(np.round(calibrated[ind_i,class_pred_i],3))
plt.title(f'{class_pred_i}|{softmax_uncalib_i}|{softmax_calib_i}')
plt.tight_layout()
plt.suptitle('Correctpredictions\nClass|Uncalibrated|Calibrated');
#############################################
plt.figure(figsize=(10,4))
foriinrange(5):
plt.subplot(1,5,i+1)
ind_i=ind_wrong[i]
plt.imshow(x_test[ind_i],cmap='gray_r')
class_pred_i=np.argmax(Y_pred_test[ind_i,:])
softmax_uncalib_i=str(np.round(Y_pred_test[ind_i,class_pred_i],3))
softmax_calib_i=str(np.round(calibrated[ind_i,class_pred_i],3))
plt.title(f'{class_pred_i}|{softmax_uncalib_i}|{softmax_calib_i}')
plt.tight_layout()
plt.suptitle('Wrongpredictions\nClass|Uncalibrated|Calibrated');


fromnetcal.presentationimportReliabilityDiagram
n_bins=10
diagram=ReliabilityDiagram(n_bins)
diagram.plot(Y_pred_test,y_test)#可视化未校准的错误

2:Baycomp
ML从业者在努力解决的一个难题是严格确定一个分类器模型对另一个分类器模型的预测优势。paperswithcode平台通过错误地将第一准确度度量(见下图)作为决定度量,进一步传播了这种模型排名谬误。

那么,考虑到要部署的两个具有类似工程开销的分类模型,如何选择其中一个?
通常,我们有一个标准的基准数据集(或一组数据集),作为分类器战争的测试场。在获得“这个数据集空间上的原始准确度度量”之后,具有统计头脑的机器学习者可能倾向于使用frequentist零假设显著性检验(NHST)框架中的工具来确定哪个分类器“更好”。然而,正如这里所说,“许多科学领域意识到了频率派推理的缺点,在最激进的情况下甚至禁止在论文中使用它”。
Baycomp就是在这种背景下出现的,它为分类器的比较提供了一个贝叶斯框架。该库有助于计算三种概率:
- P_left:第一个分类器比第二个分类器具有更高准确度分数的概率。
- P_rope:差异在实际等效范围内的概率
- P_right:第二个分类器得分较高的概率。
实际等效区域(region of practical equivalence,rope)是由机器学习者指定的,该学习者精通在部署领域可以安全地假定为等价的内容。
在下面的示例单元中,我们考虑了这两种情况,一个综合示例包含两个竞争激烈的分类器,以及我们刚刚使用MNIST数据集上的NSL-TF和LARQ-BNN框架训练的两个分类器
#用于绘制精度的辅助函数
defbar_plt2(acc_1,acc_2,label_1='Legacyclassifier',label_2='Newclassifier',X_LABELS=['default'],Category_x='Dataset'):
#设置宽度
if(X_LABELS==['default']):
X_LABELS=list(string.ascii_uppercase[0:len(acc_1)])
barWidth=0.25
#设置在X轴上的位置
r1=np.arange(len(acc_1))
r2=[x+barWidthforxinr1]
#绘图
plt.bar(r1,acc_1,color='#7f6d5f',width=barWidth,edgecolor='white',label=label_1)
plt.bar(r2,acc_2,color='#557f2d',width=barWidth,edgecolor='white',label=label_2)
#在中间添加xtick
plt.xlabel(Category_x,fontweight='bold')
plt.xticks([r+barWidthforrinrange(len(acc_1))],X_LABELS)
plt.title('Accuracycomparisonofthetwoclassifiers')
#创建图例并显示图形
plt.legend()
plt.show()
returnNone
importstring
frombaycompimport*
#首先,让我们在10个假设数据集中生成两个合成分类器准确度向量。
#传统分类器获得的准确度
classifier_legacy_acc=np.random.randint(80,85,size=(10))
mean_legacy=np.mean(classifier_legacy_acc)
#新的分类器获得的准确度
classifier_new_acc=np.random.randint(80,87,size=(10))
mean_new=np.mean(classifier_new_acc)
print(f'Themeanaccuraciesofthetwoclassifiersare:{mean_legacy}and{mean_new}')
bar_plt2(classifier_legacy_acc,classifier_new_acc)
Themeanaccuraciesofthetwoclassifiersare:82.0and81.8

print('$p_{left},p_{rope},p_{right}nbsp;usingthetwo_on_multiplefunction:')
print(two_on_multiple(classifier_legacy_acc,classifier_new_acc,rope=1))
#通过一些附加参数,函数还可以绘制出这些概率的后验分布。
#测试被打包到测试类中
#上面的调用等价于
print('$p_{left},p_{rope},p_{right}nbsp;usingtheSignedRankTest.probsfunction:')
print(SignedRankTest.probs(classifier_legacy_acc,classifier_new_acc,rope=1))
#为了得到一张图,我们调用
print(SignedRankTest.plot(classifier_legacy_acc,classifier_new_acc,rope=1,names=("Legacy-SRT","New-SRT")))
#切换到另一个测试,使用另一个类:
SignTest.probs(classifier_legacy_acc,classifier_new_acc,rope=1)
#最后,我们可以构造和查询抽样后验分布。
posterior=SignedRankTest(classifier_legacy_acc,classifier_new_acc,rope=1)
print(posterior.probs())
posterior.plot(names=("legacy-Post","new-Post"))
$p_{left},p_{rope},p_{right}nbsp;usingthetwo_on_multiplefunction:
(0.28222,0.4604,0.25738)
$p_{left},p_{rope},p_{right}nbsp;usingtheSignedRankTest.probsfunction:
(0.28056,0.46356,0.25588)
######################################################
acc_bnn=np.zeros(10)
acc_nsl=np.zeros(10)
forcinrange(10):
mask_c=y_test==c
acc_bnn[c]=(y_pred_bnn[mask_c]==c).mean()
acc_nsl[c]=(y_pred_nsl[mask_c]==c).mean()
bar_plt2(acc_nsl,acc_bnn,label_1='NSL',label_2='BNN',X_LABELS=list(np.arange(10).astype(str)),Category_x='MNISTdigitclasses')
posterior=SignedRankTest(acc_nsl,acc_bnn,rope=0.005)
print(posterior.probs())
posterior.plot(names=("NSL","BNN"))
(0.0,0.2846,0.7154)


3:PyEER

比较两个分类器的另一种方法,特别是在解决二元认证问题(不是监视,而是认证)的背景下,是通过绘制DET和ROC图比较。在这方面,pyer提供了一站式服务,不仅可以绘制相关的图表,还可以自动生成指标—报告和估计最优阈值。
在下面的示例单元格中,我们将比较基于角度的离群值检测器(ABOD)和KNN inlier-outlier检测器。
frompyeer.eer_infoimportget_eer_stats
frompyeer.reportimportgenerate_eer_report,export_error_rates
frompyeer.plotimportplot_eer_stats
#收集所有的“真实分数”和“冒名分数”
gscores_abod=y_test_proba_abod[y_test_ood==0,0]
iscores_abod=y_test_proba_abod[y_test_ood==1,0]
gscores_knn=y_test_proba_knn[y_test_ood==0,0]
iscores_knn=y_test_proba_knn[y_test_ood==1,0]
#计算分类器A的统计信息
stats_abod=get_eer_stats(gscores_abod,iscores_abod)
#计算分类器B的统计信息
stats_knn=get_eer_stats(gscores_knn,iscores_knn)
print(f'EER-KNN={stats_knn.eer},EER-ABOD={stats_abod.eer}')
plot_eer_stats([stats_abod,stats_knn],['ABOD','KNN'])
##############################
importmatplotlib.imageasmpimg
img1=mpimg.imread('DET.png')
img2=mpimg.imread('ROC.png')
plt.figure(figsize=(9,4))
plt.subplot(121)
plt.imshow(img1)
plt.subplot(122)
plt.imshow(img2)
plt.show()
EER-KNN=0.0,EER-ABOD=0.008333333333333333

C: 部署前压力测试:PyOD、HyPPO和Gradio

易受分布外(OOD)样本影响,导致预测失误,是当前困扰ML从论文过渡到实际部署的最严重障碍之一,因为在实际部署中,输入无法保证来自训练时的流形。
虽然没有什么灵丹妙药(也许永远也不会有),但将OOD模型的正则化和OOD检测模块合并到你的管道中总是好的。
关于OOD检测,我觉得最近有3项工作被ML社区采纳了。
前两个是PyOD和HyPPO,用于在执行推理之前对输入进行预过滤,第三个是Gradio,它是一个非常棒的工具,用于压力测试,是FAIR的Dynabench等工作的补充。
1: PYOD

PyOD可以说是最全面和可扩展的离群值检测Python工具包,它包括30多种检测算法的实现!
它包含软件工程的实践,以确保实现的模型类通过单元测试,并进行跨平台持续集成、代码覆盖和代码可维护性检查。并且与一个干净的统一API、详细的文档和JIT编译执行相结合,使学习不同的技术和在实践中使用它们变得轻而易举。
作者在并行化上所投入的努力已经产生了非常快速和可扩展的离群值检测代码,这些代码也可以无缝兼容Python 2和3以及主要的操作系统(Windows、Linux和MacOS)。
在下面的示例单元中,我们在合成数据集上训练并可视化两个异常检测器:the Angle-Based Outlier Detector (ABOD)and the KNN outlier detector。
frompyod.models.abodimportABOD
frompyod.models.knnimportKNN#kNN检测器
frompyod.utils.dataimportgenerate_data
frompyod.utils.dataimportevaluate_print
frompyod.utils.exampleimportvisualize
#使用pyod.utils.data.generate_data()生成示例数据:
contamination=0.4#异常值百分比
n_train=200#训练点数
n_test=100#测试点个数
X_train_ood,y_train_ood,X_test_ood,y_test_ood=generate_data(n_train=n_train,n_test=n_test,contamination=contamination)
#####1:ABOD
clf_name_1='ABOD'
clf_abod=ABOD(method="fast")#初始化检测器
clf_abod.fit(X_train_ood)
y_train_pred_abod=clf_abod.predict(X_train_ood)#二值标签
y_test_pred_abod=clf_abod.predict(X_test_ood)#二值标签
y_test_scores_abod=clf_abod.decision_function(X_test_ood)#原始离群值
y_test_proba_abod=clf_abod.predict_proba(X_test_ood)#离群值概率
evaluate_print("ABOD",y_test_ood,y_test_scores_abod)#性能评估
#######2:KNN
clf_knn=KNN()#初始化检测器
clf_knn.fit(X_train_ood)
y_train_pred_knn=clf_knn.predict(X_train_ood)#二值标签
y_test_pred_knn=clf_knn.predict(X_test_ood)#二值标签
y_test_scores_knn=clf_knn.decision_function(X_test_ood)#原始离群值
y_test_proba_knn=clf_knn.predict_proba(X_test_ood)#离群值概率
evaluate_print("KNN",y_test_ood,y_test_scores_knn)#性能评估
ABODROC:0.9992,precision@rankn:0.975
KNNROC:1.0,precision@rankn:1.0
现在我们将结果可视化:
#ABOD性能
visualize("ABOD",X_train_ood,y_train_ood,X_test_ood,y_test_ood,y_train_pred_abod,
y_test_pred_abod,show_figure=True,save_figure=False)
#KNN性能;
visualize("KNN",X_train_ood,y_train_ood,X_test_ood,y_test_ood,y_train_pred_knn,
y_test_pred_knn,show_figure=True,save_figure=False)

2: Hyppo
HYPPO (HYPothesis Testing in PythOn, 发音为“Hippo”,PythOn中的假设检验)可以说是NEURODATA社区生产的最全面的多元假设检验开源软件包。在下面的图中,我们可以看到这个包中实现的模块的总体情况,包括合成数据生成(有20个依赖结构!)、独立测试、K-sample测试以及时间序列测试。

在下面的示例中,我们看到K-Sample-Distance Correlation(或“Dcorr”)测试被用于上述PyOD中generate_data模块生成数据的假设测试。在深度学习的设置中,我们可以在输入层级别或特征嵌入空间部署这些测试,以猜测输出的softmax值是否值得在推理管道中进一步处理。
fromhyppo.ksampleimportKSample
samp_in_train=X_train_ood[y_train_ood==0]
samp_out_train=X_train_ood[y_train_ood==1]
samp_in_test=X_test_ood[y_test_ood==0]
samp_out_test=X_test_ood[y_test_ood==1]
stat_in_out,pvalue_in_out=KSample("Dcorr").test(samp_in_train,samp_out_test)
print(f'In-trainv/sOut-test\nEnergyteststatistic:{stat_in_out}.Energyp-value:{pvalue_in_out}')
stat_out_in,pvalue_out_in=KSample("Dcorr").test(samp_in_test,samp_out_train)
print(f'In-testv/sOut-train\nEnergyteststatistic:{stat_out_in}.Energyp-value:{pvalue_out_in}')
stat_in_in,pvalue_in_in=KSample("Dcorr").test(samp_in_train,samp_in_test)
print(f'In-trainv/sIn-test\nEnergyteststatistic:{stat_in_in}.Energyp-value:{pvalue_in_in}')
stat_out_out,pvalue_out_out=KSample("Dcorr").test(samp_out_train,samp_out_test)
print(f'Out-trainv/sOut-test\nEnergyteststatistic:{stat_out_out}.Energyp-value:{pvalue_out_out}')
In-trainv/sOut-test
Energyteststatistic:0.8626341445137959.Energyp-value:4.357148137679374e-32
In-testv/sOut-train
Energyteststatistic:0.7584832208162725.Energyp-value:4.0495216242247524e-25
In-trainv/sIn-test
Energyteststatistic:-0.005691336487203311.Energyp-value:1.0
Out-trainv/sOut-test
Energyteststatistic:0.006631965940452427.Energyp-value:0.18021672902891694
3:Gradio

拥有一个好的GUI来与刚刚训练过的模型进行交互,到目前为止,需要大量的JavaScript前端技巧或Heroku-Flask路径,这些技巧可以将焦点从算法上移开。
多亏了Gradio,你可以用10行Python快速启动一个gui,带有预构建的输入模块,包括文本输入、图像输入、一个很棒的Toast UI图像编辑器和一个要启动的草图板!
在过去的一年里,我们在工作流程中大量使用了Gradio。
在下面的示例单元中,我们演示了两个简单的示例,即使用Gradio启动UI,以使用草图板输入对刚才训练的MNIST分类BNN模型进行压力测试,并演示使用InceptionV3模型对图像进行分类的易用性。Gradio团队还迅速添加了可解释性和嵌入可视化工具。
importgradioasgr
importrequests
inception_net=tf.keras.applications.InceptionV3()#加载模型
#*载下**ImageNet的可读标签。
response=requests.get("https://git.io/JJkYN")
labels=response.text.split("\n")
defclassify_image(inp):
print(inp.shape)
inp=inp.reshape((-1,299,299,3))
inp=tf.keras.applications.inception_v3.preprocess_input(inp)
prediction=inception_net.predict(inp).flatten()
return{labels[i]:float(prediction[i])foriinrange(1000)}
image=gr.inputs.Image(shape=(299,299,3))
label=gr.outputs.Label(num_top_classes=3)
gr.Interface(fn=classify_image,inputs=image,outputs=label,capture_session=True).launch()
importgradioasgr
importrequests
#示例1:我们使用LARQ训练的BNN来启动一个交互式UI,该UI有助于sktechpad输入和预测
defclassify(image):
print(image.shape)
prediction=model_bnn.predict(image.reshape((-1,28,28,1))).tolist()[0]
return{str(i):prediction[i]foriinrange(10)}
sketchpad=gr.inputs.Sketchpad()
label=gr.outputs.Label(num_top_classes=3)
gr.Interface(fn=classify,inputs=sketchpad,outputs=label,capture_session=True).launch()
#示例2:使用InceptionNet-V3进行图像分类
inception_net=tf.keras.applications.InceptionV3()#加载模型
#*载下**ImageNet的可读标签。
response=requests.get("https://git.io/JJkYN")
labels=response.text.split("\n")
defclassify_image(inp):
print(inp.shape)
inp=inp.reshape((-1,299,299,3))
inp=tf.keras.applications.inception_v3.preprocess_input(inp)
prediction=inception_net.predict(inp).flatten()
return{labels[i]:float(prediction[i])foriinrange(1000)}
image=gr.inputs.Image(shape=(299,299))
label=gr.outputs.Label(num_top_classes=3)
gr.Interface(fn=classify_image,inputs=image,outputs=label,capture_session=True).launch()


文档/宣传
Jupyter_to_medium:

https://youtu.be/lU9jogfXNqE
最后,我们使用 Jupyter_to_medium PyPi包从它的源代码笔记本中编写了这篇博客文章!将jupyter/colab笔记本转换成可读的博客t涉及到痛苦的拷贝粘贴动作、代码快照和插件。
现在变得非常简单:pip安装,完成笔记本,选择File→“Deploy as”,从medium插入集成令牌,并在必要时执行最终编辑/美化。
下面是一个概述图片,总结了上面探讨的包。

希望这篇博文对您有用。