健全的逻辑和单调的 AI 模型
已发表: 2022-03-11AI 正迅速成为一项惊人的资产,在图像识别、围棋甚至扑克等领域达到了超人的性能水平。 许多人对人工智能和人类的未来感到兴奋。 与此同时,人们普遍认为 AI 确实存在一个令人讨厌的缺陷:当前状态下的 AI 可能无法预测地不可靠。
经典的例子是危险! IBM 挑战赛期间,IBM AI 沃森轻松地清理了棋盘,却错过了“最后的危险!” 问题,属于美国城市类别:“它最大的机场以二战英雄的名字命名; 它是二战中第二大战役。” 沃森回答说:“多伦多是什么????”——额外的问号(和低赌注)表明了它的怀疑。
因此,即使人工智能在很长一段时间内(数月、数年、甚至数十年)都具有童话般的性能,但总是有这种令人烦恼的可能性,即突然之间,它会莫名其妙地犯错。
我们人类最关心的不是人工智能会犯错,而是这个错误有多“不合逻辑”。 在 Watson 的案例中,不知道问题答案的人会“从逻辑上”尝试至少猜测美国的一个主要城市。 我相信这是我们尚未公开采用自动驾驶汽车的主要原因之一:即使自动驾驶汽车在统计上可能更安全,但我们担心它们的底层人工智能可能会出现与 Watson 类似的意外错误,但后果更严重。
这让我想知道,正确的 AI 模型能否解决这个问题? 正确的人工智能是否有能力在关键时刻做出正确的决定,即使它没有所有的答案? 这样的人工智能将能够改变技术的进程,让我们获得人工智能的童话般的好处……
我相信这些问题的答案是肯定的。 我相信像 Watson 那样的错误可以通过使用改进的、逻辑上更受约束的模型来避免,这些模型的早期原型被称为单调机器学习模型。 暂时不详述,使用适当的单调 AI 模型:
- 自动驾驶汽车会更安全,因为即使在存在大量其他信号的情况下,检测到最少量的人类信号也总是足以激活安全协议。
- 机器学习 (ML) 系统对对抗性攻击和意外情况更加稳健。
- ML 性能将更合乎逻辑且更易于理解。
我相信我们正在从 AI 的计算和算法能力大幅增长的时代走向 AI 的技巧、有效性和理解力的时代,而单调的机器学习模型是这一激动人心的旅程的第一步。 单调模型使 AI 更“合乎逻辑”。
编者注:鼓励希望在了解 ML 基础知识方面迈出自己第一步的读者阅读我们关于 ML 的介绍性文章。
单调人工智能模型理论
那么什么是单调模型呢? 松散地说,单调模型是具有某些特征(单调特征)的 ML 模型,这些特征的增加总是会导致模型增加其输出。
从技术上...
...有两个地方上面的定义是不精确的。
首先,这里的特征是单调递增的。 我们也可以有单调递减的特征,其增加总是导致模型减少。 两者可以简单地通过取反(乘以-1)相互转换。
其次,当我们说输出增加时,我们并不是说它严格增加——我们的意思是它不会减少,因为输出可以保持不变。
在现实生活中,许多变量对表现出单调关系。 例如:
- 旅行的汽油价格在行驶距离上单调增加。
- 信用越好,获得贷款的可能性就越大。
- 预计驾驶时间会随着交通量的增加而增加。
- 收入随着广告点击率的增加而增加。
尽管这些逻辑关系足够清晰,但对于使用有限数据且没有领域知识进行插值的 ML 模型,它们可能不是。 事实上,该模型可能会错误地插入它们,从而导致荒谬和古怪的预测。 确实捕获此类知识的机器学习模型在实践中表现更好(通过避免过度拟合),更容易调试,并且更易于解释。 在大多数用例中,单调模型应与普通模型结合使用,作为学习器集合的一部分。
单调 AI 模型真正大放异彩的一个地方是对抗性鲁棒性。 单调模型是“强化”机器学习模型,这意味着它们可以抵抗对抗性攻击。 只能操纵非单调特征的攻击者无法避开单调 AI 模型,因为他们无法更改示例相对于单调 AI 模型的标签。
单调 AI 模型的用例
到目前为止,这个讨论完全是理论上的。 让我们讨论一些现实生活中的用例。
用例 #1:恶意软件检测
单调 AI 模型最酷的用例之一就是它们在恶意软件检测中的应用。 作为 Windows Defender 的一部分实施,每台最新的 Windows 设备中都存在一个单调模型,可以悄悄地保护用户免受恶意软件的侵害。
在一种情况下,恶意软件作者冒充合法的注册企业来欺骗证书颁发机构,成功地使用受信任的证书对其恶意软件进行数字代码签名。 一个幼稚的恶意软件分类器可能会使用代码签名作为一种特征,并且会指示此类样本是良性的。
但 Windows Defender 的单调 AI 模型并非如此,其单调特征只是指示恶意软件的特征。 无论恶意软件作者向其恶意软件中注入了多少“良性”内容,Windows Defender 的单调 AI 模型都将继续捕获样本并保护用户免受损害。
在我的红队黑客机器学习课程中,我教授了几种规避基于 ML 的恶意软件分类器的技术。 其中一种技术包括用“良性”内容/特征填充恶意样本以逃避幼稚的 ML 模型。 单调模型可以抵抗这种攻击,并迫使恶意行为者更加努力地工作,如果他们想要逃避分类器的话。
用例 #2:内容过滤
假设一个团队正在为学校图书馆构建一个网上冲浪内容过滤器。 单调的 AI 模型非常适合在这里使用,因为包含不适当内容的论坛也可能包含大量可接受的内容。
一个简单的分类器可能会权衡“适当”特征的存在与“不适当”特征的存在。 但这行不通,因为我们不希望我们的孩子访问不适当的内容,即使它只占内容的一小部分。
用例 #3:自动驾驶汽车 AI
想象一下构建一个自动驾驶汽车算法。 它查看图像并看到绿灯。 它还看到一个行人。 它应该权衡每个信号吗? 绝对不。 行人的存在足以做出停车的决定。 行人的存在应被视为单调特征,在这种情况下应使用单调 AI 模型。
用例 #4:推荐引擎
推荐引擎是单调 AI 模型的一个很好的用例。 一般来说,他们可能对每个产品有很多输入:星级、价格、评论数量等。在所有其他输入相同的情况下,例如星级和价格,我们更喜欢评论数量更多的产品。 我们可以使用单调的 AI 模型来执行这样的逻辑。
用例 #5:垃圾邮件和网络钓鱼过滤
此用例类似于恶意软件检测用例。 恶意用户可能会在他们的垃圾邮件或网络钓鱼电子邮件中注入看似良性的术语,以欺骗垃圾邮件过滤器。 单调的 AI 模型将对此免疫。
实施与示范
在单调 AI 模型的免费实现方面,三个最受支持的模型脱颖而出:XGBoost、LightGBM 和 TensorFlow Lattice。
单调 ML XGBoost 教程
基于多年的实证研究和竞争,XGBoost 被认为是结构化数据上性能最好的算法之一。 此外,XGBoost 中还实现了单调性。
以下有关如何使用单调 ML 模型的演示 XGBoost 教程附带 Python 存储库。
首先导入一些库:
import random import numpy as np import matplotlib.pyplot as plt %matplotlib inline from sklearn.metrics import confusion_matrix import seaborn as sns sns.set(font_scale=1.4)
我们要建模的场景是内容过滤或恶意软件数据库。 我们将有一些benign_features
特征,例如,与“科学”、“历史”和“体育”相关的内容量,或者在恶意软件案例中,“代码签名”和“公认的作者”。
此外,我们将有malicious_features
特征,它可以建模,例如,与“暴力”和“毒品”相关的内容量,或者在恶意软件案例中,“调用加密库的次数”和“对与已知的恶意软件家族相似。”
我们将通过生成模型对情况进行建模。 我们使用以下函数随机生成大量数据点,大约一半是良性的,一半是恶意的:
def flip(): """Simulates a coin flip.""" return 1 if random.random() < 0.5 else 0
每个数据点将随机生成其特征。 “良性”数据点对良性特征的偏差更高,而“恶意”数据点对恶意特征的偏差更高。
我们将使用三角分布,如下所示:
bins = [0.1 * i for i in range(12)] plt.hist([random.triangular(0, 1, 1) for i in range(50000)], bins)
我们将使用此函数来捕获上述逻辑:
def generate(): """Samples from the triangular distribution.""" return random.triangular(0, 1, 1)
然后,我们将继续创建我们的数据集:
m = 100000 benign_features = 5 malicious_features = 5 n = benign_features + malicious_features benign = 0 malicious = 1 X = np.zeros((m, n)) y = np.zeros((m)) for i in range(m): vec = np.zeros((n)) y[i] = flip() if y[i] == benign: for j in range(benign_features): vec[j] = generate() for j in range(malicious_features): vec[j + benign_features] = 1 - generate() else: for j in range(benign_features): vec[j] = 1 - generate() for j in range(malicious_features): vec[j + benign_features] = generate() X[i, :] = vec
X
包含随机生成的特征的向量,而y
包含标签。 这个分类问题不是微不足道的。
您可以看到,良性样本通常在前几个特征中具有更大的权重,而恶意样本通常在最后几个特征中具有更大的权重。
准备好数据后,让我们执行一个简单的训练-测试拆分:
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
我们将使用一个函数来准备数据以用于我们的 XGBoost 教程:
import xgboost as xgb def prepare_for_XGBoost(X, y): """Converts a numpy X and y dataset into a DMatrix for XGBoost.""" return xgb.DMatrix(X, label=y) dtrain = prepare_for_XGBoost(X_train, y_train) dtest = prepare_for_XGBoost(X_test, y_test) dall = prepare_for_XGBoost(X, y)
现在,让我们在数据上训练和测试一个简单的(非单调的)XGBoost 模型。 然后我们将打印出混淆矩阵,以查看正确标记的正例、正确标记的负例、错误标记的正例和错误标记的负例的数字分解。

params = {"n_jobs": -1, "tree_method": "hist"} model_no_constraints = xgb.train(params=params, dtrain=dtrain) CM = predict_with_XGBoost_and_return_confusion_matrix( model_no_constraints, dtrain, y_train ) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Unconstrained model's training confusion matrix") plt.show() print() CM = predict_with_XGBoost_and_return_confusion_matrix( model_no_constraints, dtest, y_test ) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Unconstrained model's testing confusion matrix") plt.show() model_no_constraints = xgb.train(params=params, dtrain=dall)
查看结果,我们可以看到没有明显的过拟合。 我们将这些结果与单调模型的结果进行比较。
为此,让我们训练和测试一个单调的 XGBoost 模型。 我们传入单调约束的语法是一个序列 ( f 0 , f 1 , ..., f N ),其中每个f i是 -1、0 或 1 之一,这取决于我们是否希望特征i是单调的分别递减、无约束或单调递增。 在手头的情况下,我们将恶意特征指定为单调递增。
params_constrained = params.copy() monotone_constraints = ( "(" + ",".join([str(0) for m in range(benign_features)]) + "," + ",".join([str(1) for m in range(malicious_features)]) + ")" ) print("Monotone constraints enforced are:") print(monotone_constraints) params_constrained["monotone_constraints"] = monotone_constraints model_monotonic = xgb.train(params=params_constrained, dtrain=dtrain) CM = predict_with_XGBoost_and_return_confusion_matrix(model_monotonic, dtrain, y_train) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Monotonic model's training confusion matrix") plt.show() print() CM = predict_with_XGBoost_and_return_confusion_matrix(model_monotonic, dtest, y_test) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Monotonic model's testing confusion matrix") plt.show() model_monotonic = xgb.train(params=params_constrained, dtrain=dall)
很明显,单调模型的性能与无约束模型的性能相同。
现在,我们将创建一个对抗性数据集。 我们将获取所有恶意样本,并通过将它们全部设置为 1 来“填充”它们的良性特征。然后我们将看看这两个模型如何并排执行。
X_adversarial = X[y == malicious] y_adversarial = len(X_adversarial) * [malicious] for i in range(len(X_adversarial)): vec = X_adversarial[i, :] for j in range(benign_features): vec[j] = 1 X_adversarial[i, :] = vec
让我们将它们转换为 XGBoost 摄取的形式:
dadv = prepare_for_XGBoost(X_adversarial, y_adversarial)
对于 XGBoost 教程的最后一步,我们将测试两种机器学习模型类型:
CM = predict_with_XGBoost_and_return_confusion_matrix( model_no_constraints, dadv, y_adversarial ) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Unconstrained model's confusion matrix on adversarial dataset") plt.show()
CM = predict_with_XGBoost_and_return_confusion_matrix( model_monotonic, dadv, y_adversarial ) plt.figure(figsize=(12, 10)) sns.heatmap(CM / np.sum(CM), annot=True, fmt=".2%", cmap="Blues") plt.ylabel("True Label") plt.xlabel("Predicted Label") plt.title("Monotonic model's confusion matrix on adversarial dataset") plt.show()
如您所见,单调 AI 模型对对抗性攻击的鲁棒性大约高出 2,500 倍。
光GBM
在 LightGBM 中使用单调特征的语法是类似的。
TensorFlow 点阵
TensorFlow Lattice 是另一个解决单调性约束的框架,它是一组预构建的 TensorFlow Estimator 以及 TensorFlow 运算符,用于构建您自己的格模型。 格子是多维插值查找表,这意味着它们是均匀分布在空间中的点(如网格),以及这些点处的函数值。 根据谷歌人工智能博客:
“......查找表值被训练以最小化训练示例的损失,但此外,查找表中的相邻值被限制为沿着输入空间的给定方向增加,这使得模型输出增加那些方向。 重要的是,因为它们在查找表值之间进行插值,所以晶格模型是平滑的并且预测是有界的,这有助于避免在测试时出现虚假的大小预测。”
可以在此处找到有关如何使用 TensorFlow Lattice 的教程。
单调 AI 模型和未来
从保护设备免受恶意攻击到提供合乎逻辑且有用的餐厅推荐,单调的 AI 模型已被证明是对社会的一大福音,也是掌握的绝佳工具。 单调模型将引领我们进入 AI 安全、技巧和理解的新时代。 所以我说,这是单调的人工智能模型,这是进步。