Loading [MathJax]/jax/output/CommonHTML/fonts/TeX/SansSerif-Italic.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >离散分布重参数化 —— Gumbel-Softmax Trick 和 Gumbel分布

离散分布重参数化 —— Gumbel-Softmax Trick 和 Gumbel分布

作者头像
为为为什么
发布于 2024-03-28 01:48:03
发布于 2024-03-28 01:48:03
3.5K0
举报
文章被收录于专栏:又见苍岚又见苍岚

重参数化也可以用在离散分布采样中,由于对我来说相比于连续分布的重参数技巧,离散重参数难理解很多,本文单独介绍离散部分的重参数化 。

简介

这篇文章从直观感觉讲起,先讲Gumbel-Softmax Trick用在哪里及如何运用,再编程感受Gumbel分布的效果,最后讨论数学证明。

问题来源

通常在强化学习中,如果动作空间是离散的,比如上、下、左、右四个动作,通常的做法是网络输出一个四维的one-hot向量(不考虑空动作),分别代表四个动作。比如 1,0,0,0 代表上,0,1,0,0 代表下等等。而具体取哪个动作呢,就根据输出的每个维度的大小,选择值最大的作为输出动作,即 argmax(v) .

,第二个维度取到最大值 10,那么输出的动作就是 0,1,0,0,也就是说,这和多类别的分类任务是一个道理。但是这种取法有个问题是不能计算梯度,也就不能更新网络。通常的做法是加softmax函数,把向量归一化,这样既能计算梯度,同时值的大小还能表示概率的含义。softmax函数定义如下:

σ(zi)=ezij=1Kezj

那么将 v=−20,10,9.6,6.2 通过softmax函数后有

但是这么做还有一个问题,这个表示概率的向量 σ(v)=[0,0.591,0.396,0.013] 并没有真正显示出概率的含义,因为一旦某个值最大,就选择相应的动作或者分类。比如 σ(v)=[0,0.591,0.396,0.013]σ(v)=[0,0.9,0.1,0] 在类别选取的结果看来没有任何差别,都是选择第二个类别,但是从概率意义上讲差别是巨大的。所以需要一种方法不仅选出动作,而且遵从概率的含义。

很直接的方法是依概率分布采样就完事了,比如直接用np.random.choice函数依照概率生成样本值,这样概率就有意义了。这样做确实可以,但是又有一个问题冒了出来:这种方式怎么计算梯度?不能计算梯度怎么用 BP 的方式更新网络?

这时重参数(re-parameterization)技巧解决了这个问题,这里有详尽的解释,不过比较晦涩。简单来说重参数技巧的一个用处是把采样的步骤移出计算图,这样整个图就可以计算梯度BP更新了。之前我一直在想分类任务直接softmax之后BP更新不就完事了吗,为什么非得采样。后来看了VAE和GAN之后明白,还有很多需要采样训练的任务。这里举简单的VAE(变分自编码器)的例子说明需要采样训练的任务以及重参数技巧,详细内容来自视频博客

Re-parameterization Trick

原始的自编码器通常长这样:

左右两边是端到端的出入输出网络,中间的绿色是提取的特征向量,这是一种直接从图片提取特征的方式。

VAE 长这样:

VAE的想法是不直接用网络去提取特征向量,而是提取这张图像的分布特征,也就把绿色的特征向量替换为分布的参数向量,比如说均值和标准差。然后需要decode图像的时候,就从encode出来的分布中采样得到特征向量样本,用这个样本去重建图像,这时怎么计算梯度的问题就出现了。

重参数技巧可以解决这个问题,它长下面这样:

假设图中的 xϕ 表示 VAE 中的均值和标准差向量,它们是确定性的节点。而需要输出的样本 z 是带有随机性的节点,重参数就是把带有随机性的 z 变成确定性的节点,同时随机性用另一个输入节点 ϵ 代替。例如,这里用正态分布采样,原本从均值为 x 和标准差为 ϕ 的正态分布 N(x,ϕ2) 中采样得到 z 。将其转化成从标准正态分布 N(0,1) 中采样得到 ϵ ,再计算得到 z=x+ϵϕ 。这样一来,采样的过程移出了计算图,整张计算图就可以计算梯度进行更新了,而新加的 ϵ 的输入分支不做更新,只当成一个没有权重变化的输入。

到这里,需要采样训练的任务实例以及重参数技巧基本有个概念了。

Gumbel-Max trick

VAE 的例子是一个连续分布(正态分布)的重参数,离散分布的情况也一样,首先需要可以采样,使得离散的概率分布有意义而不是只取概率最大的值,其次需要可以计算梯度。那么怎么做到的,具体操作如下:

噪声,再取样:

xπ=argmax(log(πi)+Gi)

其中,

这就是 Gumbel-Max trick

Gumbel-Softmax Trick

可以通过Gumbel分布求逆从均匀分布生成,即:

Gi=log(log(Ui)),UiU(0,1)
具体实践
  • 对于网络输出的一个 n 维向量 v ,生成 n 个服从均匀分布 U(0,1) 的独立样本 ϵ1,,ϵn
  • 通过 Gi=log(log(ϵi)) 计算得到 Gi
  • 对应相加得到新的值向量
  • 通过 softmax 函数

计算概率大小得到最终的类别。其中 是温度参数。

直观上感觉,对于强化学习来说,在选择动作之前加一个扰动,相当于增加探索度,感觉上是合理的。对于深度学习的任务来说,添加随机性去模拟分布的样本生成,也是合情合理的。

Gumbel分布采样效果

为什么使用Gumbel分布生成随机数,就能模拟离散概率分布的样本呢?这部分使用代码模拟来感受它的优越性。这部分例子和代码来自这里

Gumbel分布的概率密度函数:

其中

极值分布

Gumbel分布是一类极值分布,那么它表示什么含义呢?

这里举一个类似的喝水的例子。

比如你每天都会喝很多次水(比如100次),每次喝水的量也不一样。假设每次喝水的量服从正态分布 (其实也有点不合理,毕竟喝水的多少不能取为负值,不过无伤大雅能理解就好,假设均值为5),那么每天100次喝水里总会有一个最大值,这个最大值服从的分布就是Gumbel分布。实际上,只要是指数族分布,它的极值分布都服从Gumbel分布。那么上面这个例子的分布长什么样子呢,作图有:

代码语言:text
AI代码解释
复制
from scipy.optimize import curve_fit
import numpy as np
import matplotlib.pyplot as plt
mean_hunger = 5
samples_per_day = 100
n_days = 10000
samples = np.random.normal(loc=mean_hunger, size=(n_days, samples_per_day))
daily_maxes = np.max(samples, axis=1)

def gumbel_pdf(prob,loc,scale):
    z = (prob-loc)/scale
    return np.exp(-z-np.exp(-z))/scale

def plot_maxes(daily_maxes):
    probs,hungers,_=plt.hist(daily_maxes,density=True,bins=100)
    plt.xlabel('Volume')
    plt.ylabel('Probability of Volume being daily maximum')
    (loc,scale),_=curve_fit(gumbel_pdf,hungers[:-1],probs)
    #curve_fit用于曲线拟合
    #接受需要拟合的函数(函数的第一个参数是输入,后面的是要拟合的函数的参数)、输入数据、输出数据
    #返回的是函数需要拟合的参数
    # https://blog.csdn.net/guduruyu/article/details/70313176
    plt.plot(hungers,gumbel_pdf(hungers,loc,scale))
    
plt.figure()
plot_maxes(daily_maxes)
plt.show()
pass

那么gumbel分布在离散分布的采样中效果如何呢?可以作图比较一下。先定义一个多项分布,作出真实的概率密度图。再通过采样的方式比较各种方法的效果。

如下代码定义了一个7类别的多项分布,其真实的密度函数如下图

代码语言:text
AI代码解释
复制
from scipy.optimize import curve_fit
import numpy as np
import matplotlib.pyplot as plt


n_cats = 7
cats = np.arange(n_cats)
probs = np.random.randint(low=1, high=20, size=n_cats)
probs = probs / sum(probs)
logits = np.log(probs)
def plot_probs():
    plt.bar(cats, probs)
    plt.xlabel("Category")
    plt.ylabel("Probability")


n_samples = 1000
def plot_estimated_probs(samples,ylabel=''):
    n_cats = np.max(samples)+1
    estd_probs,_,_ = plt.hist(samples,bins=np.arange(n_cats+1),align='left',edgecolor='white',density=True)
    plt.xlabel('Category')
    plt.ylabel(ylabel+'Estimated probability')
    return estd_probs

def print_probs(probs):
    print(probs.tolist())

samples = np.random.choice(cats,p=probs,size=n_samples) 

def sample_gumbel(logits):
    noise = np.random.gumbel(size=len(logits))
    sample = np.argmax(logits+noise)
    return sample
gumbel_samples = [sample_gumbel(logits) for _ in range(n_samples)]

def sample_uniform(logits):
    noise = np.random.uniform(size=len(logits))
    sample = np.argmax(logits+noise)
    return sample
uniform_samples = [sample_uniform(logits) for _ in range(n_samples)]

def sample_normal(logits):
    noise = np.random.normal(size=len(logits))
    sample = np.argmax(logits+noise)
    return sample
normal_samples = [sample_normal(logits) for _ in range(n_samples)]

plt.figure(figsize=(10,4))
plt.subplot(1,4,1)
plot_probs()
plt.subplot(1,4,2)
gumbel_estd_probs = plot_estimated_probs(gumbel_samples,'Gumbel ')
plt.subplot(1,4,3)
normal_estd_probs = plot_estimated_probs(normal_samples,'Normal ')
plt.subplot(1,4,4)
uniform_estd_probs = plot_estimated_probs(uniform_samples,'Uniform ')
plt.tight_layout()

print('Original probabilities:\t\t',end='')
print_probs(probs)
print('Gumbel Estimated probabilities:\t',end='')
print_probs(gumbel_estd_probs)
print('Normal Estimated probabilities:\t',end='')
print_probs(normal_estd_probs)
print('Uniform Estimated probabilities:',end='')
print_probs(uniform_estd_probs)

plt.figure()
plt.subplot(1,2,1)
plot_probs()
plt.subplot(1,2,2)
estd_probs = plot_estimated_probs(samples)
plt.tight_layout()#紧凑显示图片

print('Original probabilities:\t\t',end='')
print_probs(probs)
print('Estimated probabilities:\t',end='')
print_probs(estd_probs)

plt.figure()
plot_probs()
plt.show()
pass
代码语言:text
AI代码解释
复制
Original probabilities:         [0.24675324675324675, 0.1038961038961039, 0.03896103896103896, 0.23376623376623376, 0.09090909090909091, 0.14285714285714285, 0.14285714285714285]
Estimated probabilities:        [0.26, 0.109, 0.041, 0.244, 0.087, 0.113, 0.146]

真实分布

随机采样,就是真实分布

要是没有不能求梯度这个问题,直接从原分布采样是再好不过的。

接着通过前述的方法添加Gumbel噪声采样,同时也添加正态分布和均匀分布的噪声作对比

代码语言:text
AI代码解释
复制
from scipy.optimize import curve_fit
import numpy as np
import matplotlib.pyplot as plt


n_cats = 7
cats = np.arange(n_cats)
probs = np.random.randint(low=1, high=20, size=n_cats)
probs = probs / sum(probs)
logits = np.log(probs)
def plot_probs():
    plt.bar(cats, probs)
    plt.xlabel("Category")
    plt.ylabel("Probability")


n_samples = 1000
def plot_estimated_probs(samples,ylabel=''):
    n_cats = np.max(samples)+1
    estd_probs,_,_ = plt.hist(samples,bins=np.arange(n_cats+1),align='left',edgecolor='white',density=True)
    plt.xlabel('Category')
    plt.ylabel(ylabel+'Estimated probability')
    return estd_probs

def print_probs(probs):
    print(probs.tolist())

samples = np.random.choice(cats,p=probs,size=n_samples) 

def sample_gumbel(logits):
    noise = np.random.gumbel(size=len(logits))
    sample = np.argmax(logits+noise)
    return sample
gumbel_samples = [sample_gumbel(logits) for _ in range(n_samples)]

def sample_uniform(logits):
    noise = np.random.uniform(size=len(logits))
    sample = np.argmax(logits+noise)
    return sample
uniform_samples = [sample_uniform(logits) for _ in range(n_samples)]

def sample_normal(logits):
    noise = np.random.normal(size=len(logits))
    sample = np.argmax(logits+noise)
    return sample
normal_samples = [sample_normal(logits) for _ in range(n_samples)]

plt.figure(figsize=(10,4))
plt.subplot(1,4,1)
plot_probs()
plt.subplot(1,4,2)
gumbel_estd_probs = plot_estimated_probs(gumbel_samples,'Gumbel ')
plt.subplot(1,4,3)
normal_estd_probs = plot_estimated_probs(normal_samples,'Normal ')
plt.subplot(1,4,4)
uniform_estd_probs = plot_estimated_probs(uniform_samples,'Uniform ')
plt.tight_layout()

print('Original probabilities:\t\t',end='')
print_probs(probs)
print('Gumbel Estimated probabilities:\t',end='')
print_probs(gumbel_estd_probs)
print('Normal Estimated probabilities:\t',end='')
print_probs(normal_estd_probs)
print('Uniform Estimated probabilities:',end='')
print_probs(uniform_estd_probs)

plt.figure()
plt.subplot(1,2,1)
plot_probs()
plt.subplot(1,2,2)
estd_probs = plot_estimated_probs(samples)
plt.tight_layout()#紧凑显示图片

print('Original probabilities:\t\t',end='')
print_probs(probs)
print('Estimated probabilities:\t',end='')
print_probs(estd_probs)

plt.figure()
plot_probs()
plt.show()
pass

代码语言:text
AI代码解释
复制
Original probabilities:         [0.24675324675324675, 0.1038961038961039, 0.03896103896103896, 0.23376623376623376, 0.09090909090909091, 0.14285714285714285, 0.14285714285714285]
Gumbel Estimated probabilities: [0.23, 0.109, 0.034, 0.219, 0.089, 0.16, 0.159]
Normal Estimated probabilities: [0.29, 0.094, 0.012, 0.284, 0.054, 0.138, 0.128]
Uniform Estimated probabilities:[0.523, 0.002, 0.0, 0.419, 0.0, 0.028, 0.028]

可以明显看到Gumbel噪声的采样效果是最好的,正态分布其次,均匀分布最差。也就是说可以用Gumbel分布做Re-parameterization使得整个图计算可导,同时样本点最接近真实分布的样本。

数学证明

为什么添加 Gumbel 噪声有如此效果,下面阐述问题并给出证明。

,通过 softmax 函数可得,取到每个维度的概率为:

这是直接 softmax 得到的概率密度函数,如果换一种方式,对每个

下面给出Gumbel分布的概率密度函数和分布函数,并证明这件事情。

的Gumbel分布的PDF为:

CDF为

假设第,即:

关于 的条件累积概率分布函数为

即:

对 求积分可得边缘累积概率分布函数

带入式子有

化简有

积分里面是 的Gumbel分布,所以整个积分为1。则有

这和softmax的结果一致。

参考资料

文章链接: https://cloud.tencent.com/developer/article/2401857

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-3-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
保护敏感数据的艺术:数据安全指南
多年来,工程和技术迅速转型,生成和处理了大量需要保护的数据,因为网络攻击和违规的风险很高。为了保护企业数据,组织必须采取主动的数据安全方法,了解保护数据的最佳实践,并使用必要的工具和平台来实现数据安全。
小阑本阑
2023/10/13
7440
保护敏感数据的艺术:数据安全指南
Pandas高级数据处理:数据安全与隐私保护
在当今的数据驱动时代,数据安全和隐私保护已成为每个数据科学家和分析师必须重视的问题。无论是个人用户信息、企业敏感数据还是医疗记录,确保这些数据的安全性和隐私性不仅是一项法律义务,也是对用户的尊重和信任的体现。Pandas作为Python中广泛使用的数据分析库,提供了强大的功能来处理和分析数据。然而,在使用Pandas进行数据处理时,如何确保数据的安全性和隐私性同样至关重要。
Jimaks
2025/02/11
4070
分片重加密实现区块链可分享型隐私
我们习惯把数据都存储在各种云服务器上,带来方便的同时也存在很多数据隐私泄露的隐患,绝大多数的云服务供应商并不完全值得信任,他们完全可以在未经用户允许的情况下擅自泄露用户的数据,用户甚至毫不知情。
用户7358413
2020/05/24
1K0
​隐私保护:图像与视频隐私保护技术的发展
随着数字时代的到来,图像和视频数据的获取与传播变得异常容易。然而,这也带来了隐私泄露的风险,尤其是在公共场合或通过社交媒体分享的图像和视频。隐私保护技术的发展,旨在确保个人隐私在数字世界中的安全。本文将探讨图像与视频隐私保护技术的发展历程,包括关键技术、应用实例以及未来的发展方向。
二一年冬末
2024/04/29
1.1K0
【RSA2019创新沙盒】Duality:基于同态加密的数据分析和隐私保护方案
Duality Technologies成立于2016年,总部位于美国马萨诸塞州剑桥市,由著名的密码专家和数据科学家联合创立。公司致力于研究大数据/云环境下的数据安全与隐私保护技术,为企业组织提供了一个安全的数字协作平台,目前在美国和以色列开展业务。目前获得了由Team8领导的400万美元投资。2019年入选RSA大会的创新沙盒前十强,成为两家入选的数据安全公司之一(另一家是Wirewheel公司)。
绿盟科技研究通讯
2019/12/11
1.7K0
【RSA2019创新沙盒】Duality:基于同态加密的数据分析和隐私保护方案
Java - 深入理解加密解密和签名算法
Java应用接口安全性问题可能来源于多个方面,包括但不限于数据加密、身份验证、访问控制、输入验证等。下面我会对这些问题进行详细分析,并提供相应的解决方案和最佳实践。
小小工匠
2024/05/25
5650
Java - 深入理解加密解密和签名算法
密码技术在个人信息合规中的应用与落地
随着信息技术的高速发展,作为保障信息安全的重要手段,密码技术已经逐渐渗透到我们信息生活的方方面面,无论是浏览网页、即时通讯聊天,还是银行转账和智能家居等等,都涉及了密码技术的使用。2021年11月《个人信息保护法》(以下简称《个保法》)正式实施,《个保法》第五十一条明确要求个人信息处理者采取加密等安全技术措施,确保确保个人信息处理活动符合法律、行政法规的规定,并防止未经授权的访问以及个人信息泄露、篡改、丢失。事实上,密码技术除了在个人信息的传输与存储等环节作为安全保障措施外,也是个人信息去标识化/匿名化的有效方式。
FB客服
2022/02/25
1.2K0
密码技术在个人信息合规中的应用与落地
保护个人隐私数据很重要 !!!
今晚回顾了一下2018年科技界关于数据泄露而引发的个人隐私问题,特别是互联网产业大佬们的一些言论,让我对于中国用户的隐私数据有一种被过度使用的担忧,如果你也遇到了如下的几个问题,那么说明你的个人数据已经被卖了,哪里还有隐私可言。
icepy
2019/06/24
2K0
保护个人隐私数据很重要 !!!
PHP 加密与解密
在现代 Web 应用中,数据安全是至关重要的,尤其是处理用户的敏感信息时,如密码、个人身份信息、信用卡号等。为了保护这些敏感数据不被黑客窃取或篡改,我们常常需要使用加密技术对数据进行保护。PHP 作为一种广泛使用的服务器端脚本语言,也提供了多种加密和解密的方法,帮助开发者实现数据的安全保护。
繁依Fanyi
2025/02/06
7100
一文透析腾讯云如何为企业构建「数据全生命周期保护」
伴随数据成为企业的核心资产,数据安全已经成为所有企业在产业互联网时代必须直面的挑战。
腾讯安全
2019/12/26
1.9K0
一文透析腾讯云如何为企业构建「数据全生命周期保护」
关于密码存储这件事儿
在当今数字化时代,密码的安全性至关重要。不正确的密码存储方法可能导致用户数据泄露、账户被盗或系统遭受恶意攻击。因此,采用最佳实践和安全的技术方案来存储密码是至关重要的。
用户1107783
2024/03/18
3220
关于密码存储这件事儿
一款数据加密共享与签名方案
最近在研究区块链的时候关注了一下加密技术,小有心得,于是设计了一款数据加密共享与签名的方案,希望能够为做电子合同,数据存证,数据共享的朋友有所帮助吧。
深蓝studyzy
2022/06/16
4840
一款数据加密共享与签名方案
“零隐私”时代下 数字身份如何破局
“身份”这个词在人类社会中有着重要的意义。在百度百科上,它被诠释为人的出身和社会地位。也有人会将“身份”这个词拓展,将它的意义覆盖到到出身、阶层、职业、地位、状态等等。但不变的是,“身份”一直是在从不同的维度去证明,“我是谁”。
微位科技
2019/04/15
6280
“零隐私”时代下 数字身份如何破局
保护用户PII数据的8项数据匿名化技术
在当今数据驱动的市场中,数据为企业带来了更多的力量和机会。但正所谓“权力越大,责任越大。”随着越来越多的个人信息被组织收集和分析,保护个人隐私和防止滥用或未经授权访问个人数据的需求也随之而来。
FB客服
2023/08/08
1.1K0
保护用户PII数据的8项数据匿名化技术
【大数据安全】大数据安全的挑战与对策&基础设施安全
大数据安全是指在大数据环境下,为了保护数据不被非法获取、篡改或破坏,确保数据的安全性、完整性和可用性的一系列措施和技术。
Francek Chen
2025/01/22
4090
【大数据安全】大数据安全的挑战与对策&基础设施安全
加解密算法分析与应用场景
在日常开发中,无论是使用何种编程语言,我们都会遇到加解密的需求。例如,为了保护接口数据安全,我们需要对数据进行加密传输;在HTTPS协议中,通过非对称加密传输客户端私钥,然后双方使用该私钥进行对称加密通信;使用MD5算法进行文件一致性校验等。然而,面对众多的加解密方案,我们往往不清楚何时使用哪种方法。本文将为您梳理当前主流的加解密技术,并对算法进行科普性说明,但不涉及具体算法分析。根据日常应用场景,加解密技术大致可分为以下四类:
不惑
2024/05/13
7190
加解密算法分析与应用场景
Web安全系列——敏感信息泄露与加密机制
数字化时代,越来越多的数据正在被传输到Web应用程序中,这其中不乏个人或机构的敏感信息。
windealli
2023/10/13
1.4K0
Web安全系列——敏感信息泄露与加密机制
从滴滴出行下架看数据平台的隐私数据问题
7月4日晚,一则震惊互联网的消息在各媒体平台传播。这则消息是关于"滴滴出行"app的通告,由国家互联网信息办公室颁布,大意是“滴滴出行”App存在严重违法违规收集使用个人信息问题,依据相关法律规定,通知应用商店下架“滴滴出行”App,要求滴滴出行科技有限公司严格按照法律要求,参照国家有关标准,认真整改存在的问题。不久之前,《网络安全法》以及《个人信息处理法案》的重要补充——《数据安全法》于6月10日颁布。该法案9月1日开始正式实施,作为安全相关的法律,《数据安全法》规范的是数据处理活动中的数据安全,通过保障数据安全,来促进数据的进一步开发和利用,保护个人,组织的合法权益,维护国家主权及安全。数字经济蓬勃发展的今天,《网络安全法》将在其中扮演越来越重要的角色,防范国家数据安全风险,维护国家安全,保障公共利益。在进入正式问题讨论之前,我们先分析一下为什么数据安全会成为当下最重要的安全问题。主要是由于以下两点:
ThoughtWorks
2021/07/27
6950
【大数据安全】数据管理安全&安全分析&隐私保护
数据溯源技术对大数据平台中的明细数据、汇总数据使用后中各项数据的产生来源、处理、传播和消亡进行历史追踪。 大数据平台数据溯源的原则:
Francek Chen
2025/01/22
7330
【大数据安全】数据管理安全&安全分析&隐私保护
安全如何为数据库选择最佳加密方法
介绍 加密是对消息或信息进行编码以便只有授权方可以看到它的过程。加密已经进行了几个世纪。例如,在第二次世界大战中,盟军使用不成文的纳瓦霍语发送加密代码,日本人无法解码。
埃文科技
2022/05/23
7920
推荐阅读
相关推荐
保护敏感数据的艺术:数据安全指南
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档