TenSEAL学习笔记二

2023-10-27

Training and Evaluation of Logistic Regression on Encrypted Data

Download the coronary heart disease dataset

使用同态加密和Logistic Regression对冠心病(coronary heart disease ,CHD)进行预测
数据集使用的是Kaggle的数据集,可以点击here进行下载。
另外,实验的目的是探究HE密文训练与明文训练的差异,为了减少训练的计算量,会对数据及计算过程进行一些取舍。如果不想用CHD的数据,也可以用随机数来测试。
CHD数据集的格式如下:

male age education currentSmoker cigsPerDay cigsPerDay BPMeds prevalentStroke prevalentHyp diabetes totChol sysBP diaBP BMI heartRate glucose TenYearCHD
1 39 4 0 0 0 0 0 0 195 106 70 26 97 80 77 0

Initialize dataset

这里采用了CHD的数据进行测试,但是也提供了随机数的实现,只需要改变注释的代码即可。

import torch
import tenseal as ts
import pandas as pd
import random
from time import time

# those are optional and are not necessary for training
import numpy as np
import matplotlib.pyplot as plt

#设置随机种子,用来初始化模型权重
torch.random.manual_seed(73)
random.seed(73)


def split_train_test(x, y, test_ratio=0.3):
    #拆分训练集和测试集
    idxs = [i for i in range(len(x))]
    random.shuffle(idxs)
    # delimiter between test and train data
    delim = int(len(x) * test_ratio)
    test_idxs, train_idxs = idxs[:delim], idxs[delim:]
    return x[train_idxs], y[train_idxs], x[test_idxs], y[test_idxs]


def heart_disease_data():
    data = pd.read_csv("./data/framingham.csv")
    # 删除有空值的样本
    data = data.dropna()
    # 删除"education", "currentSmoker", "BPMeds", "diabetes", "diaBP", "BMI"这些特征
    data = data.drop(columns=["education", "currentSmoker", "BPMeds", "diabetes", "diaBP", "BMI"])
    # balance data
    grouped = data.groupby('TenYearCHD')
    data = grouped.apply(lambda x: x.sample(grouped.size().min(), random_state=73).reset_index(drop=True))
    # 提取标签
    y = torch.tensor(data["TenYearCHD"].values).float().unsqueeze(1)
    data = data.drop("TenYearCHD", 'columns')
    # 数据归一化
    data = (data - data.mean()) / data.std()
    x = torch.tensor(data.values).float()
    return split_train_test(x, y)


def random_data(m=1024, n=2):
    # data separable by the line `y = x`
    x_train = torch.randn(m, n)
    x_test = torch.randn(m // 2, n)
    y_train = (x_train[:, 0] >= x_train[:, 1]).float().unsqueeze(0).t()
    y_test = (x_test[:, 0] >= x_test[:, 1]).float().unsqueeze(0).t()
    return x_train, y_train, x_test, y_test


# You can use whatever data you want without modification to the tutorial
# x_train, y_train, x_test, y_test = random_data()
x_train, y_train, x_test, y_test = heart_disease_data()

print("############# Data summary #############")
print(f"x_train has shape: {x_train.shape}")
print(f"y_train has shape: {y_train.shape}")
print(f"x_test has shape: {x_test.shape}")
print(f"y_test has shape: {y_test.shape}")
print("#######################################")

输出如下

############# Data summary #############
x_train has shape: torch.Size([780, 9])
y_train has shape: torch.Size([780, 1])
x_test has shape: torch.Size([334, 9])
y_test has shape: torch.Size([334, 1])
#######################################

Training a Logistic Regression Model

没什么需要注意的点,就是一个简单的logistic回归的过程。

class LR(torch.nn.Module):

    def __init__(self, n_features):
        super(LR, self).__init__()
        self.lr = torch.nn.Linear(n_features, 1)
        
    def forward(self, x):
        out = torch.sigmoid(self.lr(x))
        return out

n_features = x_train.shape[1]
model = LR(n_features)
# use gradient descent with a learning_rate=1
optim = torch.optim.SGD(model.parameters(), lr=1)
# use Binary Cross Entropy Loss
criterion = torch.nn.BCELoss()

# define the number of epochs for both plain and encrypted training
EPOCHS = 5

def train(model, optim, criterion, x, y, epochs=EPOCHS):
    for e in range(1, epochs + 1):
        optim.zero_grad()
        out = model(x)
        loss = criterion(out, y)
        loss.backward()
        optim.step()
        print(f"Loss at epoch {e}: {loss.data}")
    return model

model = train(model, optim, criterion, x_train, y_train)
def accuracy(model, x, y):
    out = model(x)
    correct = torch.abs(y - out) < 0.5
    return correct.float().mean()

plain_accuracy = accuracy(model, x_test, y_test)
print(f"Accuracy on plain test_set: {plain_accuracy}")

def accuracy(model, x, y):
    out = model(x)
    correct = torch.abs(y - out) < 0.5
    return correct.float().mean()

plain_accuracy = accuracy(model, x_test, y_test)
print(f"Accuracy on plain test_set: {plain_accuracy}")

最后的正确率在70.35%,现在我们用HE加密训练来测试测试一下。

Encrypted Evaluation

采用同态加密的方式来对模型进行评估。
评估方式伪码如下
明文方式:
model(x_test) compare with y_test

HE方式:
model.weight.decrypt()
model.bias.decrypt()
x_test = x_test.decrypt()
y_test = y_test.decrypt()
model(x_test) compare with y_test
具体代码

def encrypted_evaluation(model, enc_x_test, y_test):
    t_start = time()
    
    correct = 0
    for enc_x, y in zip(enc_x_test, y_test):
        # encrypted evaluation
        enc_out = model(enc_x)
        # plain comparaison
        out = enc_out.decrypt()
        out = torch.tensor(out)
        out = torch.sigmoid(out)
        if torch.abs(out - y) < 0.5:
            correct += 1
    
    t_end = time()
    print(f"Evaluated test_set of {len(x_test)} entries in {int(t_end - t_start)} seconds")
    print(f"Accuracy: {correct}/{len(x_test)} = {correct / len(x_test)}")
    return correct / len(x_test)
    

encrypted_accuracy = encrypted_evaluation(eelr, enc_x_test, y_test)
diff_accuracy = plain_accuracy - encrypted_accuracy
print(f"Difference between plain and encrypted accuracies: {diff_accuracy}")
if diff_accuracy < 0:
    print("Oh! We got a better accuracy on the encrypted test-set! The noise was on our side...")

最后的正确率在62.57%,相差不大,可以认为同态加密对模型的保护较好。

Training an Encrypted Logistic Regression Model on Encrypted Data

通过加密模型进行评估的方式,验证了HE在加密模型中进行运算的可能性。现在只是使用HE对训练数据进行即加密训练,进行模型效果评估。
明文方式:
pred = model(x_train)
loss = loss(pred ,y_test)
loss.back()
model.updataParm()
acc = model(x_test) compare with y_test
密文方式
model.encrypt()
pred = model(enc_x_test)
loss = loss(predm,enc_y_test)
loss.back()
model.updataParm()
model.decrypt()
acc = model(x_test) compare with y_test
代码:

import torch
import tenseal as ts
import pandas as pd
import random
from time import time

# those are optional and are not necessary for training
import numpy as np
import matplotlib.pyplot as plt

#设置随机种子,用来初始化模型权重
torch.random.manual_seed(73)
random.seed(73)


def split_train_test(x, y, test_ratio=0.3):
    #拆分训练集和测试集
    idxs = [i for i in range(len(x))]
    random.shuffle(idxs)
    # delimiter between test and train data
    delim = int(len(x) * test_ratio)
    test_idxs, train_idxs = idxs[:delim], idxs[delim:]
    return x[train_idxs], y[train_idxs], x[test_idxs], y[test_idxs]


def heart_disease_data():
    data = pd.read_csv("./data/framingham.csv")
    # 删除有空值的样本
    data = data.dropna()#
    # 数据归一化
    data = (data - data.mean()) / data.std()
    x = torch.tensor(data.values).float()
    return split_train_test(x, y)


def random_data(m=1024, n=2):
    # data separable by the line `y = x`
    x_train = torch.randn(m, n)
    x_test = torch.randn(m // 2, n)
    y_train = (x_train[:, 0] >= x_train[:, 1]).float().unsqueeze(0).t()
    y_test = (x_test[:, 0] >= x_test[:, 1]).float().unsqueeze(0).t()
    return x_train, y_train, x_test, y_test


# You can use whatever data you want without modification to the tutorial
# x_train, y_train, x_test, y_test = random_data()
x_train, y_train, x_test, y_test = heart_disease_data()

print("############# Data summary #############")
print(f"x_train has shape: {x_train.shape}")
print(f"y_train has shape: {y_train.shape}")
print(f"x_test has shape: {x_test.shape}")
print(f"y_test has shape: {y_test.shape}")
print("#######################################")

class LR(torch.nn.Module):

    def __init__(self, n_features):
        super(LR, self).__init__()
        self.lr = torch.nn.Linear(n_features, 1)
        
    def forward(self, x):
        out = torch.sigmoid(self.lr(x))
        return out

n_features = x_train.shape[1]
model = LR(n_features)
# use gradient descent with a learning_rate=1
optim = torch.optim.SGD(model.parameters(), lr=1)
# use Binary Cross Entropy Loss
criterion = torch.nn.BCELoss()

# define the number of epochs for both plain and encrypted training
EPOCHS = 5

def train(model, optim, criterion, x, y, epochs=EPOCHS):
    for e in range(1, epochs + 1):
        optim.zero_grad()
        out = model(x)
        loss = criterion(out, y)
        loss.backward()
        optim.step()
        print(f"Loss at epoch {e}: {loss.data}")
    return model

model = train(model, optim, criterion, x_train, y_train)
def accuracy(model, x, y):
    out = model(x)
    correct = torch.abs(y - out) < 0.5
    return correct.float().mean()

plain_accuracy = accuracy(model, x_test, y_test)
print(f"Accuracy on plain test_set: {plain_accuracy}")

def accuracy(model, x, y):
    out = model(x)
    correct = torch.abs(y - out) < 0.5
    return correct.float().mean()

plain_accuracy = accuracy(model, x_test, y_test)
print(f"Accuracy on plain test_set: {plain_accuracy}")

class EncryptedLR:
    
    def __init__(self, torch_lr):
        self.weight = torch_lr.lr.weight.data.tolist()[0]
        self.bias = torch_lr.lr.bias.data.tolist()
        # we accumulate gradients and counts the number of iterations
        self._delta_w = 0
        self._delta_b = 0
        self._count = 0
        
    def forward(self, enc_x):
        enc_out = enc_x.dot(self.weight) + self.bias
        enc_out = EncryptedLR.sigmoid(enc_out)
        return enc_out
    
    def backward(self, enc_x, enc_out, enc_y):
        out_minus_y = (enc_out - enc_y)
        self._delta_w += enc_x * out_minus_y
        self._delta_b += out_minus_y
        self._count += 1
        
    def update_parameters(self):
        if self._count == 0:
            raise RuntimeError("You should at least run one forward iteration")
        # update weights
        # We use a small regularization term to keep the output
        # of the linear layer in the range of the sigmoid approximation
        self.weight -= self._delta_w * (1 / self._count) + self.weight * 0.05
        self.bias -= self._delta_b * (1 / self._count)
        # reset gradient accumulators and iterations count
        self._delta_w = 0
        self._delta_b = 0
        self._count = 0
    
    @staticmethod
    def sigmoid(enc_x):
        # We use the polynomial approximation of degree 3
        # sigmoid(x) = 0.5 + 0.197 * x - 0.004 * x^3
        # from https://eprint.iacr.org/2018/462.pdf
        # which fits the function pretty well in the range [-5,5]
        return enc_x.polyval([0.5, 0.197, 0, -0.004])
    
    def plain_accuracy(self, x_test, y_test):
        # evaluate accuracy of the model on
        # the plain (x_test, y_test) dataset
        w = torch.tensor(self.weight)
        b = torch.tensor(self.bias)
        out = torch.sigmoid(x_test.matmul(w) + b).reshape(-1, 1)
        correct = torch.abs(y_test - out) < 0.5
        return correct.float().mean()    
    
    def encrypt(self, context):
        self.weight = ts.ckks_vector(context, self.weight)
        self.bias = ts.ckks_vector(context, self.bias)
        
    def decrypt(self):
        self.weight = self.weight.decrypt()
        self.bias = self.bias.decrypt()
        
    def __call__(self, *args, **kwargs):
        return self.forward(*args, **kwargs)

        

# parameters
poly_mod_degree = 8192
coeff_mod_bit_sizes = [40, 21, 21, 21, 21, 21, 21, 40]
# create TenSEALContext
ctx_training = ts.context(ts.SCHEME_TYPE.CKKS, poly_mod_degree, -1, coeff_mod_bit_sizes)
ctx_training.global_scale = 2 ** 21
ctx_training.generate_galois_keys()

t_start = time()
enc_x_train = [ts.ckks_vector(ctx_training, x.tolist()) for x in x_train]
enc_y_train = [ts.ckks_vector(ctx_training, y.tolist()) for y in y_train]
t_end = time()
print(f"Encryption of the training_set took {int(t_end - t_start)} seconds")

normal_dist = lambda x, mean, var: np.exp(- np.square(x - mean) / (2 * var)) / np.sqrt(2 * np.pi * var)

def plot_normal_dist(mean, var, rmin=-10, rmax=10):
    x = np.arange(rmin, rmax, 0.01)
    y = normal_dist(x, mean, var)
    fig = plt.plot(x, y)
    
# plain distribution
lr = LR(n_features)
data = lr.lr(x_test)
mean, var = map(float, [data.mean(), data.std() ** 2])
plot_normal_dist(mean, var)
print("Distribution on plain data:")
plt.show()

# encrypted distribution
def encrypted_out_distribution(eelr, enc_x_test):
    w = eelr.weight
    b = eelr.bias
    data = []
    for enc_x in enc_x_test:
        enc_out = enc_x.dot(w) + b
        data.append(enc_out.decrypt())
    data = torch.tensor(data)
    mean, var = map(float, [data.mean(), data.std() ** 2])
    plot_normal_dist(mean, var)
    print("Distribution on encrypted data:")
    plt.show()

eelr = EncryptedLR(lr)
eelr.encrypt(ctx_training)
encrypted_out_distribution(eelr, enc_x_train)

eelr = EncryptedLR(LR(n_features))
accuracy = eelr.plain_accuracy(x_test, y_test)
print(f"Accuracy at epoch #0 is {accuracy}")

times = []
for epoch in range(EPOCHS):
    eelr.encrypt(ctx_training)
    
    # if you want to keep an eye on the distribution to make sure
    # the function approxiamation is still working fine
    # WARNING: this operation is time consuming
    # encrypted_out_distribution(eelr, enc_x_train)
    
    t_start = time()
    for enc_x, enc_y in zip(enc_x_train, enc_y_train):
        enc_out = eelr.forward(enc_x)
        eelr.backward(enc_x, enc_out, enc_y)
    eelr.update_parameters()
    t_end = time()
    times.append(t_end - t_start)
    
    eelr.decrypt()
    accuracy = eelr.plain_accuracy(x_test, y_test)
    print(f"Accuracy at epoch #{epoch + 1} is {accuracy}")

print(f"\nAverage time per epoch: {int(sum(times) / len(times))} seconds")
print(f"Final accuracy is {accuracy}")

diff_accuracy = plain_accuracy - accuracy
print(f"Difference between plain and encrypted accuracies: {diff_accuracy}")
if diff_accuracy < 0:
    print("Oh! We got a better accuracy when training on encrypted data! The noise was on our side...")

迭代训练5次后,在明文训练中的准确率为0.703592836856842,在密文训练中的准确率为0.667664647102356,因为训练次数较少,所以两者的差异可以接受。
明文训练时间为5秒,密文训练时间为31秒,密文在保证安全性的同时加大了训练时间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TenSEAL学习笔记二 的相关文章

  • 检查 PyTorch 张量在 epsilon 内是否相等

    如何检查两个 PyTorch 张量在语义上是否相等 考虑到浮点错误 我想知道元素是否仅相差一个小的 epsilon 值 在撰写本文时 这是最新稳定版本 0 4 1 中的一个未记录的函数 但文档位于master unstable branch
  • Pytorch 分析器显示两个不同网络的卷积平均执行时间不同

    我有两个网络 我正在对它们进行分析以查看哪些操作占用了大部分时间 我注意到CUDA time avg为了aten conv2d不同网络的操作有所不同 这也增加了一个数量级 在我的第一个网络中 它是22us 而对于第二个网络则是3ms 我的第
  • RuntimeError:维度指定为 0 但张量没有维度

    我试图使用 MNIST 数据集实现简单的 NN 但我不断收到此错误 将 matplotlib pyplot 导入为 plt import torch from torchvision import models from torchvisi
  • 预训练 Transformer 模型的配置更改

    我正在尝试为重整变压器实现一个分类头 分类头工作正常 但是当我尝试更改配置参数之一 config axis pos shape 即模型的序列长度参数时 它会抛出错误 Reformer embeddings position embeddin
  • 查找张量中沿轴的非零元素的数量

    我想找到沿特定轴的张量中非零元素的数量 有没有 PyTorch 函数可以做到这一点 我尝试使用非零 http pytorch org docs master torch html highlight nonzero torch nonzer
  • 如何平衡 GAN 中生成器和判别器的性能?

    这是我第一次使用 GAN 我面临着判别器多次优于生成器的问题 我正在尝试重现PA模型来自本文 http openaccess thecvf com content ICCV 2017 papers Sajjadi EnhanceNet Si
  • 为什么我在这里遇到被零除的错误?

    所以我正在关注这个文档中的教程 https pytorch org tutorials beginner data loading tutorial html在自定义数据集上 我使用的是 MNIST 数据集 而不是教程中的奇特数据集 这是D
  • 一次热编码期间出现 RunTimeError

    我有一个数据集 其中类值以 1 步从 2 到 2 i e 2 1 0 1 2 其中 9 标识未标记的数据 使用一种热编码 self one hot encode labels 我收到以下错误 RuntimeError index 1 is
  • LSTM 错误:AttributeError:“tuple”对象没有属性“dim”

    我有以下代码 import torch import torch nn as nn model nn Sequential nn LSTM 300 300 nn Linear 300 100 nn ReLU nn Linear 300 7
  • 尝试理解 Pytorch 的 LSTM 实现

    我有一个包含 1000 个示例的数据集 其中每个示例都有5特征 a b c d e 我想喂7LSTM 的示例 以便它预测第 8 天的特征 a 阅读 nn LSTM 的 Pytorchs 文档 我得出以下结论 input size 5 hid
  • PyTorch 中复数矩阵的行列式

    有没有办法在 PyTorch 中计算复矩阵的行列式 torch det未针对 ComplexFloat 实现 不幸的是 目前尚未实施 一种方法是实现您自己的版本或简单地使用np linalg det 这是一个简短的函数 它计算我使用 LU
  • 将 Keras (Tensorflow) 卷积神经网络转换为 PyTorch 卷积网络?

    Keras 和 PyTorch 使用不同的参数进行填充 Keras 需要输入字符串 而 PyTorch 使用数字 有什么区别 如何将一个转换为另一个 哪些代码在任一框架中获得相同的结果 PyTorch 还采用参数 in channels o
  • pytorch 的 IDE 自动完成

    我正在使用 Visual Studio 代码 最近尝试了风筝 这两者似乎都没有 pytorch 的自动完成功能 这些工具可以吗 如果没有 有人可以推荐一个可以的编辑器吗 谢谢你 使用Pycharmhttps www jetbrains co
  • 如何从已安装的云端硬盘文件夹中永久删除?

    我编写了一个脚本 在每次迭代后将我的模型和训练示例上传到 Google Drive 以防发生崩溃或任何阻止笔记本运行的情况 如下所示 drive path drive My Drive Colab Notebooks models if p
  • PyTorch 中的连接张量

    我有一个张量叫做data形状的 128 4 150 150 其中 128 是批量大小 4 是通道数 最后 2 个维度是高度和宽度 我有另一个张量叫做fake形状的 128 1 150 150 我想放弃最后一个list array从第 2 维
  • 如何计算cifar10数据的平均值和标准差

    Pytorch 使用以下值作为 cifar10 数据的平均值和标准差 变换 Normalize 0 5 0 5 0 5 0 5 0 5 0 5 我需要理解计算背后的概念 因为这些数据是 3 通道图像 我不明白什么是相加的 什么是除什么的等等
  • 样本()和r样本()有什么区别?

    当我从 PyTorch 中的发行版中采样时 两者sample and rsample似乎给出了类似的结果 import torch seaborn as sns x torch distributions Normal torch tens
  • PyTorch 给出 cuda 运行时错误

    我对我的代码做了一些小小的修改 以便它不使用 DataParallel and DistributedDataParallel 代码如下 import argparse import os import shutil import time
  • PyTorch:如何批量进行推理(并行推理)

    如何在PyTorch中批量进行推理 如何并行进行推理以加快这部分代码的速度 我从进行推理的标准方法开始 with torch no grad for inputs labels in dataloader predict inputs in
  • 使用 PyTorch 分布式 NCCL 连接失败

    我正在尝试使用 torch distributed 将 PyTorch 张量从一台机器发送到另一台机器 dist init process group 函数正常工作 但是 dist broadcast 函数中出现连接失败 这是我在节点 0

随机推荐

  • Redis使用总结(四、处理延时任务)

    引言 在开发中 往往会遇到一些关于延时任务的需求 例如 生成订单30分钟未支付 则自动取消 生成订单60秒后 给用户发短信 对上述的任务 我们给一个专业的名字来形容 那就是延时任务 那么这里就会产生一个问题 这个延时任务和定时任务的区别究竟
  • vue router进行路由跳转并携带参数(params/query)

    在使用 router push 进行路由跳转到另一个组件时 可以通过 params 或 query 来传递参数 1 使用 params 传参 在路由跳转时传递参数 router push name targetComponent param
  • 元宇宙通证-八、人类科技发展史全景长图

    八 人类科技发展史全景长图 人类科技发展史是人类认识自然 改造自然的历史 也是人类文明史的重要组成部分 科技在人类文明进程中起着至关重要的作用 制造和使用工具以及技术的传承 是人类生存的模式 是被人类社会所实践的 人类自身的进化成功很大程度
  • Java language

    Java Java is a high level general purpose object oriented programming language The main design goals of the language wer
  • qt连接oracle数据库经验总结

    利用qt连接oracle数据库实战经验 之前公司用qt开发的产品中 使用的数据库为mysql和sql server 并未用qt连接过 oracle数据库 因此 只能通过百度查资料的方式解决问题 注意 使用qt连接oracle数据库 即使远程
  • 启元世界内推招聘(对标阿里P6-P7)

    推荐系统架构师 岗位职责 负责游戏推荐系统的需求分析 系统设计 负责应用系统平台的可行技术设计 方案 指导和优化技术选型 负责推荐算法策略线上化 系统化实现在线服务 优化平台线上性能 负责线上平台的稳定性保障 负责推动应用系统的技术升级与研
  • 懂编译真的可以为所欲为

    作者 闲鱼技术 玉缜 背景 整个前端领域在这几年迅速发展 前端框架也在不断变化 各团队选择的解决方案都不太一致 此外像小程序这种跨端场景和以往的研发方式也不太一样 在日常开发中往往会因为投放平台的不一样需要进行重新编码 前段时间我们需要在淘
  • SAE安装第三方插件

    参考官网 http sae sina com cn doc python tools html saecloud 首先要安装sae python dev 1 3 2 tar gz 然后把官网的原话copy上来 在应用目录中执行下面的命令安装
  • 点云密度计算方法matlab,点云中的几何计算及matlab源码

    1 计算法向量 2 计算曲率 曲线的曲率 curvature 就是针对曲线上某个点的切线方向角对弧长的转动率 通过微分来定义 表明曲线偏离直线的程度 数学上表明曲线在某一点的弯曲程度的数值 曲率越大 表示曲线的弯曲程度越大 曲率的倒数就是曲
  • jdbc:mysql:replication_使用Mysql的Replication功能实现数据库同步

    本文档仅在于实验Mysql的Replication功能 没有考虑权限等其他问题 用于实验的服务器和客户机请使用没有安装过Mysql的计算机 如果安装过Mysql请卸载 请按照下面的顺序依次进行 改变顺序可能导致实验失败 1 在下面地址下载免
  • 会议OA项目---我的审批(审批&会议签字)

    目录 一 会议审批 二 会议签字 三 签名裁剪 一 会议审批 我的审批 实体类MeetingAudit package com zking entity import java io Serializable import java uti
  • C语言经典例题-贷款余额

    编程计算第一 第二 第三个月还贷后剩余的贷款金额 include
  • Revit二次开发——选集

    选集 选集 用户选集 过滤的用户选集 选集 选择图元后运行外部命令获取选择的内容 Revit API中定义了单选 多选 框选等方式的用户选集 用户可以十分方便的使用鼠标和键盘完成这三种方式的图元选择 Revit API根据三种用户选集各自的
  • 设系统中有三种类型的资源(A,B,C)的五个进程(P1,P2,P3,P4,P5)。A资源的数量为17,B资源的数量为5,C资源的数量为20。在T0时刻系统状态如表所示。

    银行算法应用 题目 设系统中有三种类型的资源 A B C 的五个进程 P1 P2 P3 P4 P5 A资源的数量为17 B资源的数量为5 C资源的数量为20 在T0时刻系统状态如表所示 系统采用银行家算法实施死锁避免策略 试问 1 T0时刻
  • centos7启动服务uthorization not available. Check if polkit service is running or see debug message for

    事件经过 有一次远程帮助别人解决的一个问题 当时那个人给发了一个samba服务启动报错的截图 还有一个翻译图 报错信息中提到了一个polkit服务 下面先普及一下关于这个服务的知识 polkit是一个应用程序级别的工具集 通过定义和审核权限
  • 浅析存储引擎(3)-B-tree

    浅析日志结构的存储引擎 1 bitcask浅析日志结构的存储引擎 2 SSTable和LSM Tree 前面两篇文章介绍了比较好理解的日志结构引擎LSM Tree 但它们不是最常见的索引类型 目前最广泛使用的索引结构是B tree B tr
  • input函数和int函数的使用

    第一 input函数接受一个标准输入数据 返回str类型 第二 int函数可以把str强制转换为整形 第三 int input ps 最近搞深度学习的视频 但是依然需要实操
  • 2023华为OD机试真题-寻找关键钥匙(JAVA、Python、C++)

    题目描述 小强正在参加 密室逃生 游戏 当前关卡要求找到符合给定 密码K 升序的不重复小写字母组成 的箱子 并给出箱子编号 箱子编号为1 N 每个箱子中都有一个字符串s 字符串由大写字母 小写字母 数字 标点符号 空格组成 需要在这些字符串
  • Webview setLayoutAlgorithm

    表示这个东西还是不用的为好 前端工程师会为自己的弹出框设置好位置 不必要手机端再来做弹出框的设置 要不就直接弹出原生弹出框 第一种 java WebSettings settings webView getSettings settings
  • TenSEAL学习笔记二

    文章目录 Training and Evaluation of Logistic Regression on Encrypted Data Download the coronary heart disease dataset Initia