当前位置: 首页 > 编程日记 > 正文

隐私数据在隐私AI框架中的安全流动

作者 | Rosetta技术团队

责编 | 晋兆雨

出品 | AI科技大本营

本文中,我们将介绍为了保护用户的隐私数据,在隐私  AI  框架的计算任务全流程中,数据是如何以密文形式流动,同时仍正确完成加法、乘法等计算步骤的。

隐私 AI 系统存在的目的就是赋能 AI,使得各种 AI场景下对用户隐私数据的使用都是安全的。那么,这样的系统就需要提供充分的保障,从理论到工程实现的每一个阶段都应该是经得起推敲、抵抗得住各种  攻击的。不能简单的认为只需要各方先在本地自己的数据上计算出一个模型,然后将模型结果交换一下  计算下其模型参数的平均值,就不会泄露各方的隐私数据了。现代密码学(Cryptography)是建立在严格的数学定义、计算复杂度假设和证明基础之上的,其中 MPC  (Multi-Party  Computation)方向是专门研究多个参与方如何正确、安全的进行联合计算的子领域,Rosetta、TFEncrypted等隐私 AI框架都采用了 MPC技术以提供可靠的安全性。下面我们就结合具体案例看的看下在 Rosetta中隐私数据是如何得到安全保护的。

案例

Alice,Bob和 Charley三人最近需要在他们的 AI系统中引入对数据的隐私保护能力。他们很重视安全性,所以他们想通过一个简单的例子 —— 乘法(multiply),来验证下隐私 AI 框架是否真正做到了隐私安全。

他们约定:Alice的输入为 1.2345;Bob 的输入为 5.4321;而 Charley拿到相乘的结果。他们按照 Rosetta 提供的教程,快速编写了如下代码(脚本名为 rosetta-mul.py):

#!/usr/bin/env python3
import latticex.rosetta as rtt 
import tensorflow as tfrtt.activate("SecureNN")
x = tf.Variable(rtt.private_console_input(0, shape=(1,))) # Alice's input y = tf.Variable(rtt.private_console_input(1, shape=(1,))) # Bob's input
z = tf.multiply(x, y) # z = x * ywith tf.Session() as sess:
sess.run(tf.global_variables_initializer())
res = sess.run(rtt.SecureReveal(z, receive_party=4)) # 'b0100' means Charley
print('z:', res)rtt.deactivate()

接着,他们各自打开一个终端,分别进行如下操作:

Alice ( P0) 在终端敲下如下命令行,并根据提示输入自己的私有数据:

$ python ./rosetta-mul.py --party_id=0
please input the private data (float or integer): 1.2345

Bob ( P1) 执行同样的操作,输入的也是只有自己才知晓的私有数据:

$ python ./rosetta-mul.py --party_id=1
please input the private data (float or integer): 5.4321

Charley ( P2) 在终端敲下如下命令行,等一会儿就可以得到所期望的计算结果:

$ python ./rosetta-mul.py --party_id=2 z: [b'6.705910'] 

注:

对于 Charley来说,由于没有数据,故不会提示输入。

Alice和 Bob的本地输出都会是 z:[b'0.000000'], 而不会拿到正确的结果。

可以看出,Charley  拿到的最终结果与逻辑上明文结果(6.70592745)相比,误差(0.00001745)可以忽略不计。系统的正确性得到了验证。

如果想让误差更小,可以通过配置提升精度,或使用128-bit 的数据类型。

上面短短的几行代码,虽然结果是正确的,但是他们三人对于系统安全性方面仍有一些困惑:

  • Alice、Bob的私有输入会不会被另外两方知道?

  • Charley拿到的结果会不会被 Alice、 Bob知道?

  • 整个程序运行过程中,有没有其他数据的泄漏?

  • 如果前几问的回答都是否定的,那 Charley 又是如何得到明文?

在回答这些问题之前,为简化描述、突出本质,我们需要简单介绍一下MPC实际落地中常用的安全假设。

假定系统中有 3 个节点, P0/P1/P2,其中成P0/P1为数据参与方,而P2是辅助节点,用于随机数生成。

  • 只考虑半诚实( Semi-Honest )安全模型,即三方都会遵守协议执行的流程,并且其中诚实者占多数( Honest-Majority),也就是说三个节点中只会有一个“坏人”。更为复杂的恶意( Malicious)模型等安全场景可参考其他相关论文。

  • 内部数据类型为64位无符号整型,即uint64_t。

下面我们就按照 输入--计算--输出 的顺序,详细介绍 Rosetta 中数据的表示与流动,以及所用到相关技术与算法在工程上的优化实现。


隐私数据的输入  

隐私计算问题,首先要解决的是隐私数据的输入。

在上述案例中,是通过如下两行代码来完成私有数据的安全输入的:

x = tf.Variable(rtt.private_console_input(0, shape=(1,))) # Alice's input 
y = tf.Variable(rtt.private_console_input(1, shape=(1,))) # Bob's input

如代码所示, rtt.private_console_input是 Rosetta 众多 API 之一,Rosetta还提供了rtt.private_input,等 API,用来处理隐私数据的输入。

这里发生了什么?x,y 的值会是什么?

在进入剖析之前,先来了解一个重要的概念 —— 秘密分享。

秘密分享

什么是 秘密分享(Secret Sharing)[1]?先来看一种简单的两方additive的构造:

给定一个数 x,定义 share(x)= (x0, x1) = (x − r, r),其中r是随机数,并且与x独立。可以看到, x = x0 + x1 = x -r + r。原始数据x的秘密分享值(x0,x1)将会由两个数据参与方 (P0,P1) 各自保存。

在秘密分享的方案中,所有的数据,包括中间数值都会分享在两个参与方之间。直观的看,参与的两方不会得到任何的明文信息。理论上,只需要在环上支持加法和乘法,就可以进一步通过组合来支持上层各种更复杂的函数。下文我们会看到关于乘法的详细解析,读者可以回过头来再看 这段话。

那工程上是如何处理的呢?假设P0有一个私有数据x,三方之间可以简单交互一下实现:

方案1:生成一个随机数 r,发送给 P0/P1。然后本地设置 x0 = x - r, P1 本地设置 x1 = r。此时 share(x) = (x0, x1) = (x - r, r),与上面的定义一致。

这是方案之一,后文基于这个方案进行讲解。在本文最后,我们会提一下实际落地时的进一步优化方案。

回到主线,结合方案1,我们以Alice 的输入值x = 1.2345为例看下具体过程。

第一步,浮点数转定点数。

对于有数据输入的一方,需要先将真实的浮点数转成定点数。

浮点数转定点数:即浮点数乘以一个固定的缩放因子(scale,一般为2^k)使其变成定点数(取其整数部分,舍弃小数部分)。当最后需要还原真实的原始浮点数时,用定点数除以缩放因子即可。

我们先选定一个缩放因子,这里取scale=  2^(18)。

经过缩放后,得到 x = 1.2345 * (1<<18) = 323616.768,取整数部分即323616,用于后续计算。

这里是有精度损失的,但在精度允许的范围内,不会影响后面的计算。

第二步,生成随机数 r。也叫掩码(Maskingvalue),用来隐藏真实值。

p2生成一个随机数 r,是一个 64-bit 空间的无符号整数。(如,r = fdad72ecbfbefeb9。这里用十六进制表示,下同)

p2将r发送给P0,P1。此时,P0,P1都拥有一个相同的随机数r了。

第三步,设置秘密分享值。

按秘密分享 方案1 的定义, P0 本地设置 x0 = x - r, P1 本地设置 x1 = r。所以有:

P0:x0= 4f020-fdad72ecbfbefeb9 = 2528d134045f167

P1:x1= fdad72ecbfbefeb9

4f020是 323616 的十六进制表示。

如果计算结果大于 64 bit 的空间范围,需要对结果取模(64 位空间)。下同。

至此,我们获得了关于x的分享值,share(x)=(x0,x1)=(x-r,r)=(2528d134045f167,fdad72ecbfbefeb9)

感兴趣的读者朋友可以验证一下(x0+x1)mod  。

同理,我们对Bob的输入值进行一样的处理。

上面三步,其实就是 private_console_input 的工作机制与过程。经过处理后,各方本地都存储着如下值:


P0

P1

P2
X0

2528d134045f16

X1

fdad72ecbfbefeb9

X2

0

Y0

d8e19bd0a532750

Y1

f271e642f5c29328

Y2

0

我们用 Xi,Yi 表示 X,Y 在 Pi的分享值。(下同)

P2 为何是0呢?在本方案中 P2 作为一个辅助节点,不参与真正的逻辑计算。

我们可以看到,在处理隐私数据输入的整个过程中, P0无法知道 Y 值, P1 无法知道 X 值, P2 无法知道 X 或 Y 值。

最后,我们总结一下这三个主要阶段:

密文上的协同计算

这是计算的核心。

上一步,我们保证了输入的安全,没有信息的泄漏,各方无法单独拿到其他节点的私有输入。接下来,看一下计算的代码,只有一行:

z = tf.multiply(x, y) # z = x * y

在这个计算的过程中发生了什么?下面结合乘法(Multiply) 算子原理进行实例讲解。

Multiply 算子原理

乘法相对较为复杂,我们结合经典的 Beaver Triple 方法[2]加以介绍。该方法是由密码学家 Donald Beaver在 1991 年提出,主要思想是通过乘法。协议基本原理如下:

输入:P0 拥有 X,Y的秘密分享值 X0,Y0;P1拥有X,Y的秘密分享值 X1,Y1。

这里有 share(X) = (X0, X1),share(Y) = (Y0, Y1)。在此案例中,这里的输入,就对接上一节所述的"隐私输入"的输出结果。

计算步骤:

1.P2 本地生成一组随机数A,B,C,且满足 C = A*B。

A,B,C 的生成步骤:P2 随机生成 A0,A1,B0,B1,C0,令 A = A0 + A1,B = B0 + B1,得到C= A*B, C1 = C - C0。其中AI,BI,CI 是 A,B,C 的分享值。这些都是在 P2 本地完成的。这也就是 P2 做为辅助节点的作用(用于随机数生成)。

这里 A,B,C 一般被称为三元组(Beaver'sTriple)。

比如,某次生成的随机数如下:

A0

2373edde1a0e5dcd

A1

ad483b77e4e5db41

B0

d81a4646be1c0cb8

B1

78222aff7dcc1ae8

C0

62a175e20f9a1542

C1

483498026c6ab57e

感兴趣的读者朋友可以验证一下。如 A = A0 + A1 =2373eddela0e5dcd + ad483b77e4e5db41 = d0bc2955fef4390e。这个 A 是个随机数。

2.将上一步生成的随机数的秘密分享值分别发送给P0,P1。

即将A0,B0,C0发送给P0;将A1,B1,C1发送给P1。

此时, P0,P1拥有如下值:


P0


P1

A0

2373edde1a0e5dcd

A1

ad483b77e4e5db41

B0

d81a4646be1c0cb8

B1

78222aff7dcc1ae8

C0

62a175e20f9a1542

C1

483498026c6ab57e

3.P0 计算 E0 和 F0;P1 计算 E1 和 F1。并交换 Ei,Fi。

P0 本地计算 E0 = X0 - A0, F0 = Y0 - B0。

P1 本地计算 E1= X1 - A1, F1 = Y1 - B1。

此时, P0,P1拥有如下值:


P0


P1

E0

dede9f352637939a

E1

50653774dad92378

F0

3573d3764c371a98

F1

7a4fbb4377f67840

交 换 Ei,Fi。

P0将E0,F0发送给P1;P1将E1,F1发送给P0。此时,P0,P1都拥有E0,F0,E1,F1。

4.本地计算 得到 E和 F。

P0,P1 各自本地计算 E = E0 + E1, F= F0 + F1。


P0


P1

E

2f43d6aa0110b712

E

2f43d6aa0110b712

F

afc38eb9c42d92d8

F

afc38eb9c42d92d8

5.本地计算 Z0;P1本地计算 Z1。

现在, P0 已经拥有 A0,B0,C0,E,F;P1已经拥有 A1,B1,C1,E,F。有了这些就可以计算出 Z= X*Y 的秘密分享值 Z0,Z1了。即:

P0 本地计算 Z0 = E * B0 + A0 * F+ C0;

P1 本地计算 Z1 = E * B1 + A1 * F+ C1 + E * F。


P0


P1

Z0

1db35d14c12a

Z1

ffffe24ca30611b0

正确性可以通过以下恒等式加以验证:

输出:P0,P1 分别持有 Z = X * Y的秘密分享值 Z0,Z1。

我们可以看到,从输入到计算再到输出,整个过程中,没有泄漏任何隐私数据。

整个算子计算结束时,P0单独拥有X0,Y0,A0,B0,C0,E0,F0,E1,F1,E,F,Z0,P1单独拥有X1,Y1,A1,B1,C1,E0,F0,E1,F1,E,F,Z1,P2单独拥有 A0,B0,C0,A1,B1,C1,三方都无法单独得到 X 或 Y 或 Z。

最后,我们总结一下(1~5 对应着上面的步骤):

获取明文结果

输入到计算再到输出,各节点只能看到本地所单独拥有的秘密分享值(一些毫无规律的64位随机数),从上文也可以看到,节点是无法独自得到任何隐私数据的。那么,当计算结束后,如果想得到结果的明文,怎么获取呢?

Rosetta 提供了一个恢复明文的接口,使用很简单。

res = sess.run(rtt.SecureReveal(z, receive_party=4)) # 'b0100' means Charley 
print('z:', res)

那这个 rtt.SecureReveal 是如何工作的呢?

其实非常简单:如果本方想要知道明文,只需要对方把他的秘密分享值发给我,然后本地相加即可。

比如,上一节结尾处,我们知道了各方(P0/P1/P2)的分享值如下:


P0

P1

P2

Z0

1db35d14c12a

Z1

ffffe24ca30611b0

Z2

0

结合实例,Charley(P2)想要获取结果明文,那么,P0,P1将各自的分享值Z0,Z1发给P2,然后P2本地相加即可。即: 1db35d14c12a + ffffe24ca30611b0 = 1ad2da(1757914)。我们将此值进一步再转换为浮点数,就可以得到我们想要的用户态的明文值了:1757914 / (1 << 18)=6.7059097

效率优化

上面介绍的 秘密分享 与 multiply 算子 都是基于最基本的算法原理,在时间上和通信上的开销还是比较大的,在实际工程实现中,还可以进一步进行优化以提升性能。在介绍优化方案之前,先了解一下什么是PRF[3]?

PRF[3],Pseudo-Random Function。简单来说,即给定一个随机种子 key,一个计数器 counter, 执行 PRF(key, counter) ,会得到一个相同的随机数。

补充说明一下。例如, P0,P1 执行 PRF(key01,counter01),会产生一个相同的随机数。这里的 key01, counter01 对于的 P0,P1 来说是一致的。程序会维护这两个值,对使用者来说是透明

关于秘密分享

来看看优化版本(假设:P0有一个私有数据x)。

方案2(优化版):P0,P1 使用 PRF(Key01,counter) 本地同时生成一个相同的随机数r。然后P0本地设置x0=x-r,P1本地设置x1=r。此时 share(x) = (x0,x1)x=(x = r.r),与定义一致。此版本无需 P2 的参与。没有通信开销。

目前 Rosetta 开源版本中使用的正是此方案。

方案3(优化版):P0 设置 x0 = x-r, P1 设置 X1 = 0 即可。此时 share(x) = (x, 0)。此版本无需 P2 的参与。没有通信开销,也没有计算开销。

上述各个版本(包括方案1),都是可行且安全的。可以看到P1/P2并不知道 P0 的原始输入值。

关于 Multiply 算子

Multiply 算子中输入,输出部分没有变化,主要是计算步骤中的第1步与第2步有些许变化,以减少通信量。这里也只描述这两步,其余与前文相同。

在上文的描述中,我们知道 P2 生成三元组后,需要将其分享值发送给P0,P1。当我们有了 PRF 后,可以这么做:

  1. P0,P2 使用PRF(Key02,counter02)同时生成 A0,B0,C0;P0,P1使用RF(Key12,counter12)同时生成 A1,B1。

  2. 然后,P2令A=A0+A1,B=B0+B1,得到C=A*B,C1=C-C0。P2将发送给P1。P2的任务完成。

目前 Rosetta 开源版本中使用的是此方案。

相比于原始版本,优化版本只需要发送 C1,不用再发送 A0,A1,B0,B1,C0。

在 Rosetta中,我们还针对具体的各个不同的算子进行了一系列的算法、工程优化,欢迎感兴趣的读者来进一步了解。

小结

安全性是隐私 AI框架的根本,在本篇文章中,我们结合隐私数据输入的处理和密文上乘法的实现,介绍了“随机数”  形式的密文是如何在多方之间流动,同时“神奇”的仍能保证计算逻辑的正确性的。我们这里对于安全性的说明是直观上的描述,而实际上,这些算法的安全性都是有严格数学证明的。感兴趣的读   者可以进一步去探索相关的论文。

Rosetta 将持续集成安全可靠的密码学算法协议作为“隐私计算引擎”到框架后端中,也欢迎广大开发者参与到隐私AI 的生态建设中来。

作者简介:

Rosetta技术团队,⼀群专注于技术、玩转算法、追求⾼效的⼯程师。Rosetta是⼀款基于主流深度学习框架TensorFlow 的隐私AI框架,作为矩阵元公司⼤规模商业落地的重要引擎,它承载和结合了隐私计算、区块链和AI三种典型技术。我们专门为AI从业者撰写了隐私计算+AI从技术到实战的全教程,力图让相关行业从业者0难度一键掌握隐私计算技术的用法

参考文献

[1]  秘密共享,

https://en.wikipedia.org/wiki/Secret_sharing

[2] Beaver,Donald."Efficientmultipartyprotocolsusingcircuitrandomization."Annual InternationalCryptologyConference.Springer,Berlin,Heidelberg,1991.

[3]  PRF的一个简单介绍

https://crypto.stanford.edu/pbc/notes/crypto/prf.html

更多精彩推荐
  • 比Python 3.8快20%,Pyston v2正式发布

  • 一口气看完45个寄存器,CPU核心技术大揭秘

  • 或许,人工智能比你还要老

  • 深度揭秘:腾讯存储技术发展史

  • 程序员必备!CSDN 公众号新功能上线!现在体验有惊喜!

相关文章:

MS Sql Server 作业编辑报错以及不显示历史记录

如下图&#xff1a; 解决方法&#xff1a; 1.开始->运行&#xff0c;输入dcomcnfg.exe 2.打开组件服务器->计算机->我的电脑->DCOM配置&#xff1b; 3.找到Microsoft Office Excel或者Microsoft Office Word点击右键->属性 4.选择安全&#xff0c;将启动和激活权…

基于Guava实现的文件复制

需求&#xff1a;现需要将文件D:\A\B\C\abc.txt进行一下操作 1.在文件夹D:\A\B\C下&#xff0c;没有以abc命名的文件夹则创建 2.将目标文件D:\A\B\C\abc.txt复制到abc下 实现代码&#xff1a; /*** 以目标文件名创建文件夹&#xff0c;并将目标文件复制到该文件夹下** param sr…

破局传统算法痛点,腾讯安全首提基于跨模态检索的二进制代码-源代码匹配

整理 | 高卫华出品 | AI科技大本营头图 | CSDN付费下载自视觉中国近日&#xff0c;在NeurIPS 2020正式发布的论文入选名单中&#xff0c;腾讯安全科恩实验室聚焦解决二进制安全问题的《CodeCMR: Cross-Modal Retrieval For Function-Level Binary Source Code Matching》&#…

DataGrid删除确认及Item颜色交替

有时候我们需要在删除DataGrid中Item相对应的数据时&#xff0c;需要弹出一个确认对话框来提示使用者&#xff0c;其实这个功能非常简单&#xff0c;下面的代码可以在DataGrid的Item 中产生颜色交替的效果。 private void dg_ItemDataBound(object sender, DataGridItemEve…

SharePoint 2010 自定义日志

7/6/2012 How to log to the SharePoint ULS Logs(Clean Debugging and Error Logging broken down into steps) By: Philip Stathis 原文地址 http://www.thesharepointblog.net/Lists/Posts/Post.aspx?ID122 This article is meant to introduce a simple error logging rou…

使用Bot Service创建Bot Framework

创建Bot Service&#xff1a;进入至Azure控制台中&#xff0c;新建Bot Service&#xff0c;如不知道Bot Service在哪个选项中&#xff0c;可以先查找Bot Service再创建 在弹出的查询结果中&#xff0c;选择Bot Service&#xff0c;点击后会进入至下一个步骤 在弹出的Bot Servic…

[转]大三下,我们该做什么?一篇被转万次的日志,你值得一看

大三下&#xff0c;我们该做什么&#xff1f;一篇被转万次的日志&#xff0c;你值得一看 还有几个月&#xff0c;你就不得不参加考研、就业大军了&#xff0c;你做好准备了么&#xff1f;你知道211学校、985学校和非211、985的主要区别么&#xff1f;找工作机会一定是不均等的。…

如何在DataGrid里面产生滚动条而不滚动题头

作者Blog&#xff1a;http://blog.csdn.net/cuike519/ 我们在开发的时候一定遇到&#xff0c;使用DataGrid的时候由于不想分页&#xff08;数据没有那么多&#xff09;但是又显示不在一页里面&#xff0c;此时我们希望在DataGrid里面出现一个滚动条&#xff0c;可以上下滚动Dat…

“小霸王学习机”再现?树莓派400正式发布,售价70美元

整理 | 高卫华出品 | AI科技大本营头图 | CSDN 下载自视觉中国11月2日&#xff0c;树莓派 4 的制造商正式推出了树莓派 400&#xff0c;这是一款集成了 4GB 内存树莓派 4 的紧凑型键盘。有了树莓派 400&#xff0c;只需使用其两个微型HDMI端口之一&#xff0c;将其插入电视或显…

display的block、none、inline属性及解释

常会用到display对应值有block、none、inline这三个值 参数&#xff1a; block :块对象的默认值。用该值为对象之后添加新行。之前也添加一行。 none :隐藏对象。与visibility属性的hidden值不同&#xff0c;其不为被隐藏的对象保留其物理空间 inline :内联对象的默认值。用该值…

datagrid分页问题(前后跳页)《控件版》

在ASCX中写的。 在CSDN上看了很多的DATAGRID分页问题&#xff0c;当然DATAGRID有自己的分页项&#xff0c;功能是很有限的&#xff0c;我也在CSDN上看了很多自己分页的代码&#xff0c;发现都是用C#写的&#xff0c;我写了一个用ASP。NET中VB语言写的。以下代码供大家参考。 HT…

F5第一个10000台

F5中国第一个累积销售10000台&#xff0c;花了整整9年时间。下一个累积销售10000台需要多少时间&#xff0c;5年&#xff0c;3年&#xff0c;甚至更短的时间&#xff1f;让我们拭目以待。转载于:https://blog.51cto.com/f5555/1126095

java内存溢出的情况解决方法

内存溢出虽然很棘手&#xff0c;但也有相应的解决办法&#xff0c;可以按照从易到难&#xff0c;一步步的解决。  第一步&#xff0c;就是修改JVM启动参数&#xff0c;直接增加内存。这一点看上去似乎很简单&#xff0c;但很容易被忽略。JVM默认可以使用的内存为64M&#xff…

DataGrid基于Access的快速分页法

DataGrid基于Access的快速分页法撰文/ 黎波DataGrid是一个功能非常强大的ASP.NET Web服务器端控件&#xff0c;它除了能够方便地按各种方式格式化显示表格中的数据&#xff0c;还可以对表格中的数据进行动态的排序、编辑和分页。使Web开发人员从繁琐的代码中解放。实现DataGrid…

urlrewrite使用小结

urlrewrite顾名思义&#xff0c;就是对URL进行重写&#xff0c;用户得到的全部都是经过处理后的URL地址&#xff0c;这样做我觉得好处有三&#xff1a;一&#xff1a;提高安全性&#xff0c;可以有效的避免一些参数名、ID等完全暴露在用户面前&#xff0c;如果用户随便乱输的话…

性能超越图神经网络,将标签传递和简单模型结合实现SOTA

译者 | 刘畅出品 | AI科技大本营头图 | CSDN付费下载自视觉中国图神经网络&#xff08;GNNs&#xff09;是图学习中一种主流的技术。然而&#xff0c;对于GNN为什么在实际使用中很成功以及它们是否是优异性能所必需的技术&#xff0c;了解相对较少。本文展示了许多标准的传导节…

模仿VIMD的模式的简化代码示例

按numpad0来切换模式&#xff0c;按t显示不同的结果&#xff1b; Numpad0:: tfmode:!tfmode aaa:(tfmode1?"AAAA":"BBBB") SplashImage Off SplashImage, "",X500 Y500 W200 B fs10 CT00FFFF CW000000,%aaa%, , 切换模式提示 WinSet, Tr…

DataGrid连接Access的快速分页法(1)——需求与现状

作者&#xff1a;黎波一、需求分析 DataGrid是一个功能强大的ASP.NET Web服务器端控件&#xff0c;它除了能够按各种方式格式化显示数据&#xff0c;还可以对数据进行动态的排序、编辑和分页。大大减轻了广大Web程序员的工作量。实现DataGrid的分页功能一直是很多入门者感到棘手…

CSDN公众号新功能上线,居然还能搜出小姐姐???

为了给各位打工人更好的搜索体验CSDN总是在学习新技能这次CSDN公众号又给大家带来了一项全新的搜索技能在CSDN旗下的公众号内回复消息就能自动回复想搜索的内容啦小编来给大家演示一下&#xff0c;在公众号内输入“mysql安装教程”&#xff0c;就能得到CSDN全站内关于mysql安装…

p2v、v2v 转换-windows篇

问题&#xff1a;如何把 xenserver的虚拟机转成Esxi的虚拟机 如何把物理机转成Esxi的虚拟机答案&#xff1a;↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓首先介绍一下实验环境。一台xenserver主机上两台虚拟机 win03和win08 转到Esxi5.0的一台主机上。Esxi5.0在某个…

WebViewJavascriptBridge原理解析

基本说明 我们的项目是一个OC与javascript重度交互的app&#xff0c;OC与javascript交互的那部分是在WebViewJavascriptBridge的github地址的基础上修改的&#xff0c;WebViewJavascriptBridge应该是当前最流行最成功的OC与Web交互实现了。最近看了一下他的实现原理&#xff0c…

DataGrid连接Access的快速分页法(2)——SQL语句的选用(升序与降序)

作者&#xff1a;黎波 一、相关概念 在 ACCESS 数据库中&#xff0c;一个表的主键&#xff08;PRIMARY KEY&#xff0c;又称主索引&#xff09;上必然建立了唯一索引&#xff08;UNIQUE INDEX&#xff09;&#xff0c;因此主键字段的值是不会重复的。并且索引页依据索引列的值…

从谷歌AutoML到百度EasyDL,AI大生产时代,调参师不再是刚需

出品 | AI科技大本营头图 | 付费下载于视觉中国2018 年&#xff0c;Google Cloud 宣布将 AutoML 作为机器学习产品的一部分。至此&#xff0c;AutoML 开始进入大众的视野。 实际上&#xff0c;2013 年AutoWEKA的发布可以算作AutoML的开端&#xff1b;2014 年&#xff0c;ICML开…

Python 语法小知识

为什么80%的码农都做不了架构师&#xff1f;>>> 序列解包 将含有多个值的序列解开&#xff0c;然后把值存放到变量中&#xff0c;当函数或者方法返回元组时这个特性很有用&#xff0c;可以把返回的序列值直接赋值给变量&#xff0c;在序列解包时等号两边的元素个数…

CSS布局之-水平垂直居中

对一个元素水平垂直居中&#xff0c;在我们的工作中是会经常遇到的&#xff0c;也是CSS布局中很重要的一部分&#xff0c;本文就来讲讲CSS水平垂直居中的一些方法。另外&#xff0c;文中的css都是用less书写的&#xff0c;如果看不懂less&#xff0c;可以把我给的demo链接打开&…

DataGrid连接Access的快速分页法——动态生成SQL语句

作者&#xff1a;黎波using System;using System.Text;namespace Paging{/// <summary>/// FastPaging 的摘要说明。/// </summary>public class FastPaging {private FastPaging() {}/// <summary>/// 获取根据指定字段排序并分页查询的 SELECT 语句。/// &…

一文读懂机器学习“数据中毒”

作者 | Ben Dickson翻译 | 火火酱~出品 | AI科技大本营头图 | 付费下载于视觉中国在人类的眼中&#xff0c;下面的三张图片分别展示了三样不同的东西&#xff1a;一只鸟、一只狗和一匹马。但对于机器学习算法来说&#xff0c;这三者或许表示同样的东西:一个有黑边的白色小方框。…

chartee

2019独角兽企业重金招聘Python工程师标准>>> 一个绘制图表的类库&#xff0c;支持绘制股票的K线图&#xff0c;还可以绘制曲线、柱状图等等。 Code4App编译测试&#xff0c;测试环境&#xff1a;Xcode 4.3, iOS 5.0。 转载:http://www.adobex.com/ios/source/detail…

C语言存储类关键字

1、static这个关键字有三种用法&#xff1a;&#xff08;1&#xff09;第一种是用来修饰局部变量&#xff0c;使之成为静态局部变量&#xff1b;静态局部变量存储在数据段/bss段中&#xff0c;作用域是代码块作用域&#xff0c;生命周期是程序生命周期&#xff0c;链接属性是无…