同态加密和SEAL库的介绍(九)CKKS 参数心得 1

news2024/11/24 12:34:01

写在前面:

        前面几篇有官方的说明和示例做支撑,相信能给大家比较多的参考价值。但是由于没能对同态加密有更深入的了解,所以在我具体使用的时候出现各种问题。本篇是针对这些问题做的一些测试,由结论产生的了些个人的推测,希望对大家有帮助。

一、引入和参数配置

        上篇性能测试中,官方提到了一句:“不推荐在CKKS中使用BFVDefault素数。然而,对于性能测试,BFVDefault素数已经足够好了”。在 CKKS 中也提到了 “以特定方式选择 coeff_modulus 可能非常重要。”
        足以可见参数设置的重要性,当然三个参数关系中:poly_modulus_degree 限制了 coeff_modulus 的上限,scale 要和 coeff_modulus 相适应。故接下来针对 coeff_modulus 进行具体测试和说明。


1.1 参数说明

        先说上限的问题,poly_modulus_degree 的配置会确定 coeff_modulus 配置的上限(即几个位置加起来的比特数总和)。当然,poly_modulus_degree 的选择会影响槽的数量和带来较大性能差异,所以在设计之初就得确定,影响也是最大的。基本根据算法的设置就能选定一个性能最优的,并不需要过多抉择。

        poly_modulus_degree 选定后,虽然能确定 coeff_modulus 的上限,但是具体怎么设置是个问题,咱们先看通过 Default 函数自动生成的效果:

        虽然不确定函数内部依据何种原则生成的,但是都是顶着上限在生成的(可能会浪费),而且每位都是基本相同(这个有问题)。故所以官方不建议用此,那咱们接下来具体实验。


1.2 参数配置

输入准备:(后面测试中,主要改变的也是 coeff_modulus 和 scale )

EncryptionParameters parms(scheme_type::ckks);
size_t poly_modulus_degree = 8192;
parms.set_poly_modulus_degree(poly_modulus_degree);
parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 60,40,60 }));
double scale = pow(2.0, 40);
SEALContext context(parms);

KeyGenerator keygen(context);
auto secret_key = keygen.secret_key();
PublicKey public_key;
keygen.create_public_key(public_key);
Encryptor encryptor(context, public_key);
Evaluator evaluator(context);
Decryptor decryptor(context, secret_key);
CKKSEncoder encoder(context);
size_t slot_count = encoder.slot_count();

1.3 输入编码和加密

        测试会从编码一个数组,然后备用几个常数来依次做乘法(加法基本没影响,且不同深度的乘法影响较大),观察其密文容量、模数链位置和 scale 的变化。

vector<double> the_input;
the_input.reserve(slot_count);
for (size_t i = 0; i < slot_count; i++){
    the_input.push_back((double)i);
}
std::cout << "Print the Input vector: " << endl;
Plaintext the_input_plain;
encoder.encode(the_input, scale, the_input_plain);
Ciphertext the_input_enc;
encryptor.encrypt(the_input_plain, the_input_enc);

Plaintext the_constant_plain_1, the_constant_plain_2, the_constant_plain_3;
encoder.encode(3.14, scale, the_constant_plain_1);
encoder.encode(3.14, scale, the_constant_plain_2);
encoder.encode(3.14, scale, the_constant_plain_3);

1.4 连乘要注意的问题

        之前说过算加法的时候,参数要匹配,后来发现乘法也需要,即 param_id 和 scale的确切值 要相同
        补充:之前在BFV的时候,可以通过 decryptor.invariant_noise_budget() 来查看噪声预算,实测这个函数在 CKKS 里面用不了,所以很多时候虽然可以解密不报错,但是结果是错误的,故参数的设置要自己注意!

Ciphertext the_input_enc;
encryptor.encrypt(the_input_plain, the_input_enc);

evaluator.multiply_plain_inplace(the_input_enc, the_constant_plain_1);
evaluator.rescale_to_next_inplace(the_input_enc);

evaluator.multiply_plain_inplace(the_input_enc, the_constant_plain_2);

代码设计如上(中间输出的代码省略了),运行结果如下:

        可以发现,乘法后 param_id 没变,但是 scale 翻倍了;Rescale 后,param_id 左移,scale 恢复了。这时候进行第二次乘法会报错,因为一开始编码的 the_constant_plain_2 的 param_id 是 初始的2,scale 也是标准的 2^40 (rescale 后的 the_input_enc 只是近似,确切值不同),故会报错说不匹配

这里修改匹配就行:

  1. 把 明文 的 param_id 向下调,和密文一样即可;但是不能调密文的,因为不能向上;
  2. 模数互相调整都行,因为密文也是近似于 2^40 次方,调整不会有大影响(但是你数字本身太大影响就能看出来了!)
evaluator.mod_switch_to_inplace(the_constant_plain_2, the_input_enc.parms_id());
the_constant_plain_2.scale() = the_input_enc.scale();

        如果第二次不是乘法,是加法。那这里就有另一种情况了,即如果不进行 rescale 呢?(因为如果一开始就打算只乘一次),那 param_id 其实是一样的,不用调整。但是明文要注意!明文编码的时候用的是 2^40 次方,如果现在强行改成 2^80 次方就会出错!
        
这时候我试过一个方法,即直接在明文编码的时候就用 2^80 次方即可,这里只需再改一下确切值,就没问题了。(注意,是乘完了再加一次!当然情况比较特殊,大家做个参考即可)

encoder.encode(3.14, pow(scale,2), the_constant_plain_2);

Ciphertext the_input_enc;
encryptor.encrypt(the_input_plain, the_input_enc);

evaluator.multiply_plain_inplace(the_input_enc, the_constant_plain_1);

the_constant_plain_2.scale() = the_input_enc.scale();
evaluator.add_plain_inplace(the_input_enc, the_constant_plain_2);

         输出如上,是正确的。因为 rescale 本身也是需要时间代价的但是 scale 翻倍对解密是没有影响的,故如果过程类似的可以参考下。当然通过上面也能说明,加法是不改变容量、param_id 和 scale 的。


        这里补充一下:这里没有输出密文的大小(size),因为经过测试过明文乘法和加法并不会改变密文大小,所以不在此处进行讨论(下一篇密文乘法的时候会讨论)。这里对容量进行了输出,虽然不清楚具体含义,但是 Rescale 会引起容量的变化,放在这里便于大家对比。


二、Coeff_modulus 和 Scale 的关系

        按照之前的解释,coeff_modulus 的最后一位是用来生成密钥的,要大于等于其他的值;第一位是用来解密的,也是要适当的比较大;中间的要和 scale 相近。所以之前例子中,官方采用{ 60, 40, 60} 这种配置。
咱们先看和 scale 的关系,将中间和 scale 设置成不相同的,观察变化:
scale = 30,coeff_modulus = 180 (50 + 40 + 40 + 50) bits

        这里我们发现,因为都是拿 2^30 编码的,所以乘完正常翻倍至 60 bits;但是因为中间设置的是 40,这里 rescale 后直接变成 20 了(即 60 - 40 = 20)!直接解密发现虽然近似值差不多,但是明显误差变大了,即 scale 影响了结果的精度!
        故最好将中间的数设置为和 scale 一样,这样才能稳定中间结果


三、Scale 对精度的影响

        示例中只是简单提到了大约位数,但是无法推测出具体的精确程度。故做实验对比下:
scale = 20,coeff_modulus = 120 (40 + 20 + 20 + 40) bits

        第二位的精确结果是 9.8596,第三位是 19.7192,最后一位是 40375.062,可以发现数字越大,误差也就越大说明精度不是到具体位数的,而是跟数字本身有关的


scale = 40,coeff_modulus = 200 (60 + 40 + 40 + 60) bits

         可以发现,哪怕是最后一位的 40375.062,也得到了精确结果。(但是后面的测试会发现,模数链是跟乘法深度匹配的,故如果scale大了,就无法进行深度的计算了,需要一定的取舍
 

四、加密参数对深度明文乘法的影响

        模数链限制了乘法的深度,因为当 param_id 处于最底的时候,再 rescale 就会报错。这个理解没什么问题,但是后续在实验的时候发现了一个现象,模数处于底部的时候,是一个比较特殊的状态。

4.1 模数底部的特殊性

scale = 20,coeff_modulus = 120 (40 + 20 + 20 + 40) bits

 这里想去乘第三次的时候,会报错说:scale out of bounds !(第二次结果也有误)

        因为我是把密文的 scale 赋值给明文的,所以第三次乘法的 scale 应该是  (20.4605)^2确实这超过了 coeffee_modulus 的第一位 40,但是第二次乘法结果的 scale 也超过了,为什么没问题?


所以我猜测是因为此时已经处于了模数链的最底层,所以比较特殊?验证不是底层的情况:
scale = 20,coeff_modulus = 140 (40 + 20 + 20 + 20 + 40) bits

        果然,因为模数练处于底层的特殊性。当然此时结果是错的,第二位的精确结果是30.9591,按照之前结论,此时确实精度不够,但是不会报错,故先探究报错原因。
通过多次尝试发现: 

scale = 20,coeff_modulus = 121 (41 + 20 + 20 + 40) bits

        即只要第 coeff_modulus 第一位大于乘法结果的 scale 即可虽然可以运行,但是解密结果是错误的!故继续尝试:coeff_modulus = 140 (50 + 20 + 20 + 50) bits 仍然错误!
一直尝试到:coeff_modulus = 160 (60 + 20 + 20 + 60) bits(最大只到60):

发现能解密了,但是精度根本不够,不过探究出了报错的原因。


4.2 提高精度的参数设置

接下来拉高精度:
        coeff_modulus = 200 (60 + 40 + 40 + 60),报错 scale out of bounds !证明刚才的结论是正确的,即模数链底层比较特殊,这里的第一位 60 达不到要求
        那么按照要求极限设置: coeff_modulus = 178 (60 + 29 + 29 + 60) bits (29+29 < 60):


果然没有报错,但是解密结果感人。当然此时也能总结出规律,加模数链


scale = 30,coeff_modulus = 190 (50 + 30 + 30 + 30 + 50) bits

        第三位的精确值是61.918288 ,后面第一位的精确值是:126715.7763,看得出来也差不多,但是再往后就不行了。故这种配置就是针对这个算法最优的。


有趣的是,当我继续想拉高精度的时候,即尝试了:

  1. scale = 40,coeff_modulus = 200 (40 + 40 + 40 + 40 + 40) bits :
    报错!scale out of bounds
  2. scale = 40,coeff_modulus = 218 (49 + 40 + 40 + 40 + 49) bits:
    拉满了218,不报错,但是精度不如上面的 190 (50 + 30 + 30 + 30 + 50) bits

故模数链得够长,而且第一个数和最后一个数也得够大!


4.3 本例总结

上面进行了 三次乘法 和 两次 Rescale:
        
如果模数链只给四位数(最后的为密钥的特殊素数,其他三位是给密文用的),需要注意最后的大小问题,不然会报错 scale out of bounds(补充:此时不能再进行第三次 Rescale,会报错)此时精度也不理想。
        如果模数链给五位数,则精度会提升,但是第一和最后位的大小要尽量大于其他。[ 即:190 (50 + 30 + 30 + 30 + 50) 的精度要大于 218 (49 + 40 + 40 + 40 + 49) ]。(此时可以进行第三次Rescale 再解密,但是我尝试过精度差不多,所以意义可能不大)
        另外,上面提到的精度,均与数字大小有关,并不是指可以精确到的位数
 


五、本篇总结

本篇探究了如下情况:

  1. 连乘时,要注意的参数匹配问题;
  2. Coeff_modulus 的中间数 和 Scale 的关系;
  3. Scale 对精度的影响;
  4. 模数链长度对乘法深度,准确说对 Rescale 次数 的影响;
  5. 报错 scale out of bounds 的具体情况;
  6. 想提高精度,比较合适的参数设置;

        叠个甲:很多结果都是测试得出的结论,不一定准确,毕竟不是看源码分析而来的。但是具有一定的参考价值,也算是帮大家踩过坑了。
        下一篇打算继续探究 密文深度乘法情况 和 参数设置对内存占用的影响
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2045959.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

准大学生电脑应该怎么选?

随着夏日的尾声悄然临近&#xff0c;各位准大学生们是不是已经迫不及待想要翻开大学生活的崭新篇章了呢&#xff1f;作为准大学生&#xff0c;选择一台称心如意的电脑绝对是大家最近最头疼的事情&#xff0c;那我们应该怎么选择适合自己的电脑呢&#xff1f; 01 处理器&#x…

井字棋游戏(HTML+CSS+JavaScript)

&#x1f30f;个人博客主页&#xff1a;心.c 前言&#xff1a;这两天在写植物大战僵尸&#xff0c;写不动了&#xff0c;现在和大家分享一下之前我写的一个很简单的小游戏井字棋&#xff0c;这个没有AI&#xff0c;可以两个人一起玩&#xff0c;如果大家觉得我哪里写的有一些问…

【Redis】Linux CentOS Redis 的安装—(一)

Redis 一、获取源二、解压编译 一、获取源 //redis-stable是最新稳定版 wget https://download.redis.io/redis-stable.tar.gz二、解压编译 //我指定目录/app tar -xzvf redis-stable.tar.gz -C /appcd /app/redis-stablemake && make install##三 、修改配置启动 …

重复的子字符串 | LeetCode-459 | 字符串匹配 | KMP | 双指针

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 &#x1f579;️KMP练习题 &#x1f4cc;LeetCode链接&#xff1a;459. 重复的子字符串 文章目录 1.题目描述&#x1f34d;2.题解&#x1fad0;2.1 暴力解法&#x1…

enhanced Input Action IA_Look中Action value引脚没有分割结构体引脚的选项

UE5系列文章目录 文章目录 UE5系列文章目录前言二、使用步骤解决办法 前言 据说&#xff0c;unreal engine5中准备废弃“项目设置”中“输入”&#xff0c;操作映射&#xff0c;轴映射。取而代之的是&#xff1a; 使用增强的输入动作&#xff08;Enhanced Input Actions&#…

【QT】Qt SDK的下载,安装和环境配置

目录 一&#xff0c;Qt SDK的下载二&#xff0c;Qt SDK的安装三&#xff0c;验证Qt SDK安装是否成功四&#xff0c;Qt环境变量配置 一&#xff0c;Qt SDK的下载 进入下面两个网站都可以进行下载&#xff1a; Qt 下载官⽹ 国内清华源 进⼊官⽹&#xff0c;按如下图⽰进⾏相应…

Allegro如何导入DXF结构文件并生成板框(1)?

在用Allegro进行PCB设计时,需要导入DXF结构文件,由此来生成PCB的板框。 本节先讲Allegro如何导入DXF结构文件?下节讲如何利用导入的DXF结构文件生成OUTLINE板框。 Allegro如何导入DXF结构文件并生成板框(2)?-CSDN博客 详细操作方法如下: 1、选择菜单栏File 选择Import…

【EI会议】第三届环境工程与可持续能源国际会议征稿开启

第三届环境工程与可持续能源国际会议&#xff08;EESE 2024&#xff09;将于2024年12月20日至21日在湖南长沙召开&#xff0c;诚挚邀请相关领域学者、专家加入会议&#xff0c;开展学术讨论和研究&#xff0c;共同助推环境工程与可持续能源产学研领域的进步&#xff01; 征稿主…

SDK does not contain ‘libarclite‘ at the path

Xcode15运行报错:SDK does not contain libarclite at the path /Applications/Xcode.app/Contents/ Developer/Toolchains/XcodeDefault.xctoolchain/us/lib/arc/libarclite_iphoneos.a 如下图: 阅读报错信息,它的意思是 SDK没有包含 libarclite 这个文件,这个文件的路径是: …

基于 face_recognition 的人脸识别的小工具

使用 face_recognition 和 pyside2&#xff0c;开发了一个小工具&#xff0c;识别指定的人脸照片&#xff0c;保存到指定的文件夹。 源码如下&#xff1a; import sys import os import shutil import face_recognition import logging from PySide2.QtWidgets import QApplic…

PDF文件转换为HTML文件

推荐使用 pdf2htmlEX&#xff08;因为确实做的比较全&#xff09; pdf2htmlEX 是一个开源工具&#xff0c;可以将PDF文件转换为HTML文件。你需要先安装pdf2htmlEX工具&#xff0c;并确保它在你的系统路径中可用。&#xff08;花时间最多就是找包&#xff09; 安装 pdf2htmlEX …

API以及添加学生信息练习

API:应用程序编程接口 简单理解&#xff1a;API就是别人已经写好的东西&#xff0c;我们不需要自己编写&#xff0c;直接使用即可 Java API&#xff1a;指的就是jdk中提供的各种功能的Java类&#xff0c;这些类将底层的实现封装起来&#xff0c;我们不需关心这些类是如何实现的…

什么是神中神公司?发表内卷言论,分分钟要你道歉...

谷歌 海的那边&#xff0c;这几天最乐的新闻&#xff0c;是谷歌前 CEO 批评员工不拼命工作后道歉。 今年 4 月&#xff0c;谷歌前 CEO 埃里克施密特&#xff08;Eric Schmidt&#xff09;在斯坦福大学的一次演讲中&#xff0c;被问及 OpenAI 和 Anthropic 等初创公司目前在人工…

【全面解析】芯片采购渠道策略:原厂直采VS代理VS现货市场

芯片作为现代科技的基石&#xff0c;其重要性不言而喻。无论是智能手机、汽车电子、物联网设备还是高性能计算领域&#xff0c;都离不开芯片的支持。随着5G、AI、大数据等前沿技术的飞速发展&#xff0c;对芯片的需求量持续攀升&#xff0c;如何确保稳定、高效的芯片供应链成为…

A3VLM: Actionable Articulation-Aware Vision Language Model

发表时间&#xff1a;13 Jun 2024 作者单位&#xff1a;SJTU Motivation&#xff1a;以往的机器人VLM如RT-1[4]、RT-2[3]和ManipLLM[21]都专注于直接学习以机器人为中心的动作。这种方法需要收集大量的机器人交互数据&#xff0c;这在现实世界中非常昂贵。 解决方法&#xf…

数据中台之数据开发-离线开发和实时开发

目录 一、离线开发 1.1 概述 1.2 作业调度 1.3 基线控制 1.4 异构存储 1.5 代码校验 1.6 多环境级联 1.7 推荐依赖 1.8 数据权限 二、实时开发 2.1 概述 2.2 实时计算的特点 2.2.1 实时且无界(unbounded)的数据流 2.2.2 持续且高效的计算 2.2.3 流式且实时的数据…

go,gin封装gorm使用,增删改查

1、主 package mainimport ("fmt""wbGo/configs" )type Dades struct {Id intName stringAge int }func main() {//连接数据库configs.BaseName("wbrj_sample")var data []Dades//查询configs.Db.Raw("select * from dade where id>…

机器学习/深度学习——关于分类任务的机器学习、深度学习模型的评估指标详解

机器学习/深度学习——模型的评估详解 搭配以下文章进行学习&#xff1a; 卷积神经网络&#xff1a; 深度学习——卷积神经网络&#xff08;convolutional neural network&#xff09;CNN详解&#xff08;一&#xff09;——概述. 步骤清晰0基础可看 深度学习——卷积神经网…

Ciallo~(∠・ω・ )⌒☆第十七篇 Ubuntu基础使用 其一

Ubuntu是一种基于Linux的操作系统&#xff0c;它是开源的、免费的&#xff0c;并且具有广泛的用户群体。 基本文件操作&#xff1a;Ubuntu使用命令行工具来进行文件操作。以下是一些常用的命令&#xff1a; 切换到用户主目录&#xff1a; cd ~ 切换到上级目录&#xff1a; cd .…

QT 数据导出到Excel

原创&#xff1a;QT 数据导出到Excel 在Qt自带的axcontainer模块中&#xff0c;我们可以使用QAxObject类来将数据保存到Excel中。Qt中将数据保存到Excel通常有两种方式&#xff1a;一种是以Excel格式导出&#xff0c;需要电脑上安装Office软件&#xff1b;另一种是以CSV格式导出…