Amazon SageMaker使用自编码器完成人脸生成_输入大小64*64自编码器-程序员宅基地

技术标签: 机器学习  深度学习  人工智能  

一、前言

最近受邀参与了亚马逊云科技【云上探索实验室】活动,体验了一下Amazon SageMaker平台,训练了一个人脸的自编码器。对比本地的训练时间,速度提升比较明显。本文将围绕Amazon SageMaker和自编码器进行。

自编码器是一个非常简单的网络,早在上世纪90年代就提出了自编码器的概念。当时使用受限的玻尔兹曼机分层训练,在硬件强大的今天可以实现端到端的训练。自编码器有许多变种,比如变分自编码器、去噪自编码器、正则自编码器等。由于自编码器采用的是自监督学习,因此使用自编码器可以使用较低成本得到较好的效果。

今天我们将训练一个自编码器。自编码器训练完成后可以进行各种有趣的实验,像编辑一个人的表情、让人脸A渐渐变成人脸B、让一个人从小慢慢变老、生成人脸等。

在本文我们会做一部分实验,实现人脸渐变和生成人脸的操作。

1.1 什么是Amazon SageMaker

Amazon SageMaker是一个完全托管的机器学习服务平台,包含了机器学习的各个流程,从标注到部署。开发人员可以快速构建模型并训练,还可以部署到托管环境。Amazon SageMaker提供了Jupyter笔记本,而且可以执行各种流行框架,不止是MXNet,还可以使用PyTorch、TensorFlow等主流框架。

1.2 有什么特别的

在数据标注时,Ground Truth可以用来团队标注,在标注一定数据后,Ground Truth可以自动标注,当对标注不确定时才会让人工进行标注。

Amazon SageMaker提供了数据存储,模型部署等服务,完成这些操作都可以一键式完成。

同时Amazon SageMaker提供了许多高阶API,可以使用Amazon Auto Pilot自动训练模型与调优模型。同时还可以对模型的情况进行监控,以便更好地改善模型。

二、机器学习流程

2.1 机器学习整体流程

在开始使用Amazon SageMaker完成机器学习任务前,先熟悉一下机器学习的流程。机器学习的流程分为一下几个步骤:

  1. 获取数据
  2. 数据清洗
  3. 将数据处理成模型的输入
  4. 训练模型
  5. 评估模型
  6. 部署模型
  7. 监控、收集数据、评估模型

上述步骤整体是一条直线,但是经常会回到前面几个步骤重新往下执行。如下图所示:
在这里插入图片描述

(1)数据处理

1-3为数据处理部分,主要是数据从无到有、从杂乱到规范,在此步骤中,我们会用到诸如爬虫、正则、归一化、标准化等技术。处理后的数据通常表示为一个张量(多维数组),不同类型的数据的形状有所不同。图像数据通常为n_sample × channel × height × width,各维度含义分别为样本数、通道数、高、宽,有时候通道数会放在最后一个维度。表格数据被处理为n_sample × n_feature,分别为样本数、特征数。文本数据则是n_sample × sequence_len × 1,分别为样本数和文本长度。还有时间序列、视频、立体图片等数据都会处理成固定形状的张量。

数据处理成张量后还可以做一些特征工程,比如特征选择、标准化、归一化等。这一步操作有利于模型训练。

(2)训练模型

4-5为训练评估部分,在处理好数据后就可以开始训练模型了。训练模型需要我们确定几样东西,分别是模型结构(选取上面算法)、对应的超参数、优化器等。在此过程通常会训练多个模型,选取一个最优模型作为最终模型。

为了选择较优的超参数,会使用到网格搜索交叉验证。在sklearn模块中,提供了对应的实现。SageMaker中也有类似更强的功能,后面有具体体验。

(3)部署及维护

当选取一个最优模型后,既可以将模型部署上线,模型的部署可以作为API、Web、小程序、APP等。在部署上线后,模型可能会出现各种问题,也会慢慢落后,因此还需要对模型进行监控维护。在上线后,可以继续收集一些用户授权的数据,然后把这些数据重复之前的步骤,对模型进行迭代优化。

2.2 SageMaker中机器学习流程

SageMaker中机器学习流程于上面一致,下面我们来实际看看各个步骤如何操作。

(1)数据处理

Amazon SageMaker中可以创建Jupyter Notebook,创建的Notebook可以执行pip、wget等指令。我们可以使用以往使用的所有方式处理数据,也可以使用SageMaker自带的SDK。在SageMaker中有一个sklearn子模块,可以用来处理数据。

SKLearnProcessor可以执行sklearn脚本来处理数据,首先需要创建SKLearnProcessor对象,然后调用run方法对数据进行处理,示例代码如下:

from sagemaker import get_execution_role
from sagemaker.sklearn.processing import SKLearnProcessor
from sagemaker.processing import ProcessingInput, ProcessingOutput

role = get_execution_role()
sklearn_processor = SKLearnProcessor(
    framework_version="0.20.0", role=role, instance_type="ml.t3.medium", instance_count=1
)
sklearn_processor.run(
    code="preprocessing.py",
    inputs=[
        ProcessingInput(source="s3://your-bucket/path/to/your/data", destination="/opt/ml/processing/input"),
    ],
    outputs=[
        ProcessingOutput(output_name="train_data", source="/opt/ml/processing/train"),
        ProcessingOutput(output_name="test_data", source="/opt/ml/processing/test"),
    ],
    arguments=["--train-test-split-ratio", "0.2"],
)
preprocessing_job_description = sklearn_processor.jobs[-1].describe()

在创建调用run方法时,需要先创建好用于处理数据的preprocessing.py文件,对应code参数。preprocessing.py命令行参数由arguments给出。

preprocessing.py可以用sklearn来做具体处理。处理完成后,处理结果等信息保存在preprocessing_job_description中,可以通过preprocessing_job_description[‘Outputs’]拿到处理结果。

(2)训练模型

模型的训练与处理数据一样,需要准备好对应的训练脚本train.py。处理好数据并准备好train.py脚本后,使用下面的代码就可以进行训练了,这里的实例类型要和数据处理的实例类型一致。

from sagemaker.sklearn.estimator import SKLearn

sklearn = SKLearn(
    entry_point="train.py", framework_version="0.20.0", instance_type="ml.t3.medium", role=role
)
sklearn.fit({
    "train": preprocessed_training_data})
training_job_description = sklearn.jobs[-1].describe()
model_data_s3_uri = "{}{}/{}".format(
    training_job_description["OutputDataConfig"]["S3OutputPath"],
    training_job_description["TrainingJobName"],
    "output/model.tar.gz",
)

评估模型的代码也是一样的风格:

sklearn_processor.run(
    code="evaluation.py",
    inputs=[
        ProcessingInput(source=model_data_s3_uri, destination="/opt/ml/processing/model"),
        ProcessingInput(source=preprocessed_test_data, destination="/opt/ml/processing/test"),
    ],
    outputs=[ProcessingOutput(output_name="evaluation", source="/opt/ml/processing/evaluation")],
)
evaluation_job_description = sklearn_processor.jobs[-1].describe()

(3)部署

构建和训练模型后,您可以将模型部署至终端节点,以中获取预测推理结果。部署使用下面代码即可完成:

predictor = estimator.deploy(initial_instance_count=1, instance_type="ml.m4.xlarge")

可以根据任务要求选择实例类型。

2.3 实战

三、自编码器

下面使用SageMaker完成自编码相关的实验。

3.1 自编码器介绍

自编码器是一个非常简单网络,通常由编码器和解码器两个部分组成。编码器解码器的结构可以用全连接,也可以用卷积,或者其它一些网络。在早期自编码器的编码器解码器需要分开训练,而现在通常是端到端的训练。

编码器部分会将输入逐步降维,最后得到一个固定长度的向量,这个向量可以作为输入数据的编码。解码器部分接收编码器的输出,结果解码器会得到一个形状与编码器输入一样的数据。自编码器训练的目的就是输出与数据尽可能接近。

整体上看自编码器使用的是监督学习方法,但是目标值和特征值是一样的,像这种标签由数据自身给出的学习方法又被称为自监督学习。

自编码器结构简单,但是有一些非常好的性质。比如训练简单,不需要人工标记数据等。使用自编码器可以对数据进行降维,创建新数据等。假设对人脸图像数据进行编码,编码器会得到1024维的向量。那么编码器得到的这个向量每一个维度可能代表着一种特征,比如第n个维度可能代表表情、第k个维度可能代表性别等。如果能知道这些信息,就可以做一些有趣的事情。

3.2 环境准备

这里使用Amazon SageMaker的笔记本实例进行实验,创建笔记本实例,创建时使用默认选项即可。在创建时需要记住使用的实例类型,后续训练需要对应正确的类型。

创建好环境后,可以在笔记本中运行下面代码获取当前角色以及S3桶:

import sagemaker
import os
sess = sagemaker.Session()
role = sagemaker.get_execution_role()
bucket = sagemaker_session.default_bucket()

下面就可以开始数据的准备了。

3.3 数据处理

这里使用PyTorch完成数据的处理和训练,下面是需要用到的一些模块:

from torch import nn
from torch import optim
from torch.utils.data import Dataset, DataLoader
from torchvision import datasets
from torchvision import transforms

本实验使用的是CelebA Dataset,可以在http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html下载。数据集里面包含了10万修正好的人脸图片。将图片下载到电脑上后,再把数据上传到笔记本中。为了方便加载,创建一个Dataset类,完成数据的加载:

class FaceDataset(Dataset):
    def __init__(self, data_dir="./datasets/img_align_celeba", image_size=64):
        self.image_size = image_size
        self.trans = transforms.Compose([
            transforms.Resize(image_size),
            transforms.CenterCrop(image_size),
            transforms.ToTensor(),
            transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
        ])
        self.image_paths = []
        if os.path.isdir(data_dir):
            for root, dirs, files in os.walk(data_dir):
                for file in files:
                    self.image_paths.append(os.path.join(root, file))
        elif os.path.isfile(data_dir):
            with open(data_dir, encoding='utf-8') as f:
                self.image_paths = f.read().strip().split()

    def __getitem__(self, item):
        return self.trans(Image.open(self.image_paths[item]))

    def __len__(self):
        return len(self.image_paths)

下面创建DataLoader用于加载数据:

dataset = FaceDataset(data_dir="./datasets/img_align_celeba")
dataloader = DataLoader(dataset, 64)

另外,可以通过下面代码将数据上传至S3桶:

inputs = sagemaker_session.upload_data(path="datasets/img_align_celeba", bucket=bucket, key_prefix='sagemaker/img_align_celeba')

数据准备好后,需要编写模型以及训练脚本。

3.2 模型训练

本文以人脸数据训练一个自编码器,而后用这个自编码器做一些其它事情,首先训练一个自编码器。网络结构由卷积和转置卷积组成,代码如下:

class FaceAutoEncoder(nn.Module):
    def __init__(self, encoded_dim=1024):
        super(FaceAutoEncoder, self).__init__()
        # [b, 3, 64, 64] --> [b, 1024, 1, 1]
        self.encoder = nn.Sequential(
            nn.Conv2d(3, 64, 4, 2, 1, bias=False),
            nn.LeakyReLU(0.2, inplace=True),

            nn.Conv2d(64, 64 * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(64 * 2),
            nn.LeakyReLU(0.2, inplace=True),

            nn.Conv2d(64 * 2, 64 * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(64 * 4),
            nn.LeakyReLU(0.2, inplace=True),

            nn.Conv2d(64 * 4, 64 * 8, 4, 2, 1, bias=False),
            nn.BatchNorm2d(64 * 8),
            nn.LeakyReLU(0.2, inplace=True),

            nn.Conv2d(64 * 8, encoded_dim, 4, 1, 0, bias=False),
            nn.LeakyReLU(0.2, inplace=True)
        )
        # [b, 1024, 1, 1] - > [b, 3, 64, 64]
        self.decoder = nn.Sequential(
            nn.ConvTranspose2d(encoded_dim, 64 * 8, 4, 1, 0, bias=False),
            nn.BatchNorm2d(64 * 8),
            nn.ReLU(True),

            nn.ConvTranspose2d(64 * 8, 64 * 4, 4, 2, 1, bias=False),
            nn.BatchNorm2d(64 * 4),
            nn.ReLU(True),

            nn.ConvTranspose2d(64 * 4, 64 * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(64 * 2),
            nn.ReLU(True),

            nn.ConvTranspose2d(64 * 2, 64, 4, 2, 1, bias=False),
            nn.BatchNorm2d(64),
            nn.ReLU(True),
            nn.ConvTranspose2d(64, 3, 4, 2, 1, bias=True),
            nn.Tanh()
        )

    def forward(self, x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x

编码器部分将64×64的图片转换成1024维的向量,而解码器则是利用转置卷积将1024维的向量转换成64×64的图像。现在我们的目标是模型输入与数据越接近越好,所有可以用均方误差作为损失函数,同时输入和目标为同一批数据。下面编写一个训练脚本autoencoder.py,代码如下:

def train(args):
    device = "cuda" if torch.cuda.is_available() else "cpu"
    dataset = FaceDataset()
    dataloader = DataLoader(dataset, 64)
    model = FaceAutoEncoder().to(device)
    optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=0.9)

    for epoch in range(1, args.epochs + 1):
        model.train()
        for batch_idx, data in enumerate(dataloader, 1):
            data = data.to(device)
            optimizer.zero_grad()
            output = model(data)
            loss = F.mse_loss(output, data)
            loss.backward()
            optimizer.step()
    save_model(model, args.model_dir)


def model_fn(model_dir):
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = torch.nn.DataParallel(AutoEncoder())
    with open(os.path.join(model_dir, "model.pth"), "rb") as f:
        model.load_state_dict(torch.load(f))
    return model.to(device)


def save_model(model, model_dir):
    path = os.path.join(model_dir, "model.pth")
    torch.save(model.decoder.cpu().state_dict(), path)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--epochs",
        type=int,
        default=10,
        metavar="N",
        help="number of epochs to train (default: 10)",
    )
    parser.add_argument(
        "--lr", type=float, default=0.01, metavar="LR", help="learning rate (default: 0.01)"
    )
    train(parser.parse_args())

我们可以使用argparse设置一些参数。脚本准备好后,可以开始进行训练,因为使用的是PyTorch,所以要改用sagemaker.pytorch中的PyTorch来进行训练,代码如下:

from sagemaker.pytorch import PyTorch

estimator = PyTorch(
    entry_point="autoencoder.py",
    role=role,
    py_version="py38",
    framework_version="1.11.0",
    instance_count=1,
    instance_type="ml.c5.2xlarge",
    hyperparameters={
    "epochs": 4},
)
estimator.fit({
    "training": inputs})

其中entry_point就是前面的训练脚本。然后等待模型训练,训练完成后可以得到模型文件model.pth,这里只包含decoder部分。下面是输出的结果:

在这里插入图片描述

训练完成后使用下面一句就可以对模型进行部署:

predictor = estimator.deploy(initial_instance_count=1, instance_type="ml.m4.xlarge")

不过自编码器本身只是还原原有数据而已,要生成人脸需要使用Decoder部分,进行推理。

四、使用自编码器实现人脸渐变

4.1 人脸渐变原理

在前面提到自编码器的一个优点就是可以把对输入的操作改为对编码的操作,现在我们训练了一个人脸的自编码。假设人脸A被编码成z1,人脸B被编码成z2,现在想让人脸由A到B渐变。现在可以把这个问题转换为向量z1和z2之间的渐变,向量的渐变可以直接使用插值算法,我们在两个向量见插入n个向量,再把这些向量输入解码器,得到的人脸图像就是介于A和B之间的人脸。现在人脸渐变就变为了插值。

4.2 人脸渐变的实现

首先实现插值算法,插值的实现很简单,具体代码如下:

def interpolate(x1, x2, num):
    result = torch.zeros((num, *x1.shape))
    step = (x2 - x1) / (num - 1)
    for i in range(num):
        result[i] = x1 + step * i
    return result

上面函数输入两个长度一样的向量,输出num个向量。这num个向量将作为Decoder的输入。接下来使用Decoder部分进行推理:

# 加载数据集
dataloader = DataLoader(
    FaceDataset(data_dir='/home/zack/Files/datasets/img_align_celeba', image_size=64),
    batch_size=2
)
model = FaceAutoEncoder()
model.load_state_dict(torch.load('../outputs/face_auto_encoder.pth'))

model.eval()
with torch.no_grad():
    for idx, data in enumerate(dataloader):
        # 对人脸编码
        encoded1 = model.encoder(data[0].reshape((1, 3, 64, 64)))
        encoded2 = model.encoder(data[1].reshape((1, 3, 64, 64)))
        # 对人脸编码进行插值
        encoded = interpolate(encoded1[0], encoded2[0], 64)
        # 解码成人脸
        outputs = model.decoder(encoded).reshape((64, 3, 64, 64))
        outputs = make_grid(outputs, normalize=True)
        plt.imshow(outputs.numpy().transpose((1, 2, 0)))
        plt.show()

下面是实现的效果:

在这里插入图片描述
可以看到人脸转变的很自然。现在可以将这一部分部署,部署代码如下:

from sagemaker.pytorch import PyTorchModel
pytorch = PyTorchModel(
    model_data=model_data,
    role=role,
    entry_point="inference.py",
    source_dir="code",
    framework_version="1.3.1",
    py_version="py3",
    sagemaker_session=sagemaker_session,
)
predictor = pytorch.deploy(
    initial_instance_count=1,
    instance_type='ml.m5.large',
    endpoint_name=endpoint_name,
    wait=True,
)

其中inference.py是推理脚本,具体代码如下:

def predict_fn(input_data, model):
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    input_data = input_data.to(device)
    with torch.no_grad():
        inputs = interpolate(input_data[:, 0], input_data[:, 1])
        return model.decoder.forward(inputs)


def model_fn(model_dir="model.pth"):
    loaded_model = torch.jit.load(model_dir, map_location=torch.device("cpu"))
    loaded_model = loaded_model.eval()
    return loaded_model

然后使用predictor.predict传入2 × 3 × 64 × 64的张量就可以完成模型的推理,返回插值后的人脸图像。

五、自编码器生成人脸

自编码器除了实现人脸渐变外,还可以用来生成人脸,关键点依然在编码部分。

5.1 人脸分布

自编码器生成人脸的原理比较简单,在训练自编码器时,把人脸编码成一个长度为1024维的向量。现在我们假设人脸服从高斯分布,如果能求出均值和方差,就可以知道这个高斯分布的具体样子。在知道高斯分布的具体表达式后,就可以对从中采样人脸向量,把这个向量交给decoder就可以生成人脸。

均值和方差可以用统计的方式获取,具体代码如下,把结果保存为一个npz文件:

mean = np.zeros((zdim,), dtype=np.float32)
cov = np.zeros((zdim, zdim), dtype=np.float32)

device = "cuda" if torch.cuda.is_available() else "cpu"
model.eval()
model = model.to(device)
with torch.no_grad():
    for idx, data in enumerate(dataloader):
        try:
            data = data.to(device)
            encoded = model.encoder(data).view(128, -1)
            mean += encoded.mean(axis=0).cpu().numpy()
            cov += np.cov(encoded.cpu().numpy().T)
            if idx % 50 == 0:
                print(f"\ridx: {
      idx}/{
      len(dataloader)}", end="")
        except Exception as e:
            pass
    mean /= (idx + 1)
    cov /= (idx + 1)
np.savez('face_distribution.npz', mean, cov)

5.2 生成人脸

生成人脸的操作就是从前面的高斯分布中进行采样,然后把采样的向量交给decoder进行编码即可。具体代码:

# 加载人脸分布
distribution = np.load('face_distribution.npz')
mean = distribution['arr_0']
cov = distribution['arr_1']
# 生成编码向量
batch_size = 64
z = np.random.multivariate_normal(
    mean,
    cov,
    batch_size
).astype(np.float32)
# 解码
with torch.no_grad():
    encoded = torch.from_numpy(z).view(batch_size, 1024, 1, 1)
    outputs = model.decoder(encoded)
    outputs = torch.clamp(outputs, 0, 255)
    grid = make_grid(outputs).numpy().transpose((1, 2, 0))
    plt.imshow(grid)
    plt.show()

下面是生成的一些人脸,五官部分可以看的很清楚,但是背景部分有一些模糊。

在这里插入图片描述
现在前面Amazon SageMaker部署的代码可以复用,只需要修改推理的代码即可。把inference.py中predict_fn函数修改成下面的样子:

def predict_fn(input_data, model):
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    z = torch.randn(1, 1024, 1, 1).to(device)
    with torch.no_grad():
        return model.decoder.forward(z)

5.3 生成相关的模型

在前面,我们使用Amazon SageMaker,围绕自编码器实现了人脸渐变和人脸生成的实验。自编码器并非主流的生成模型,对于图像生成,现在更流行Stable Diffusion模型,相比之下Stable Diffusion的能力更强,生成的图像更逼真。Amazon官方给出了Stable Diffusion相关实验:https://catalog.us-east-1.prod.workshops.aws/workshops/3b86fa89-da3a-4e5f-8e77-b45fb11adf4a/zh-CN。我们可以使用Amazon SageMaker直接运行,详细的实践可以参考实验手册,下面给出跑出来的一些示例图片。

比如文本输入:拿着长剑的猫,可以得到下面的图片

https://img-blog.csdnimg.cn/c305e7dbaf6e4c2f80e4d1588277e603.png#pic_center

或者:梵高星空,可以得到下面图片

https://img-blog.csdnimg.cn/5d897bbb097547e8971eb02fa87812c9.png#pic_center

每次生成的图片是不一样的,大家可以多尝试一些有趣的东西。

六、总结

6.1 算法总结

自编码器的结构非常简单,训练起来相比GAN等要更容易,但是功能特别强大。在前面的实验中,我们都是把对结果的调整转为对编码的处理。在自编码器中有一个非常理想的设想,就是每个维度控制一个特征,但是实际上没有这么简单。自编码器还有一些其它变形,比如变分自编码器,ALAE等,可以实现更加强大的功能,甚至可以媲美StyleGAN,生成逼真的网络。

除了直接使用自编码器,在其它网络中也可以插入与自编码器类似的结构,比如Stable Diffusion中就有Unet网络,也是一种编码解码结构。

6.2 Amazon SageMaker总结

用于机器学习的平台有很多,Amazon SageMaker是比较全面,且面向应用的一个。在Amazon SageMaker中包括了机器学习的各个流程,在以往Python中的开发习惯可以在Amazon SageMaker中完全适用,另外Amazon SageMaker提供了更高阶的API,可以让用户更专注于算法的研究。

Amazon SageMaker支持Sklearn、PyTorch、TensorFlow、Hugging Face等,对这些主流模块和框架都有相应的封装。另外Amazon SageMaker提供了非常便捷的部署方式。

为了方便训练模型,Amazon SageMaker中提供了Amazon AutoPilot可以自动对各种模型以及各组超参数进行搜索,训练最优模型。

关于云上探索实验室的活动可以参考https://dev.amazoncloud.cn/experience?trk=cndc-detail&sc_medium=corecontent&sc_campaign=product&sc_channel=csdn,里面有许多有趣的实验案例。通过云上探索实验室,开发者可以学习实践云上技术,同时将自己的技术心得分享给其他开发者小伙伴。一同创造分享,互助启发,玩转云上技术。云上探索实验室不仅是体验的空间,更是分享的平台”

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ZackSock/article/details/129745320

智能推荐

从零开始搭建Hadoop_创建一个hadoop项目-程序员宅基地

文章浏览阅读331次。第一部分:准备工作1 安装虚拟机2 安装centos73 安装JDK以上三步是准备工作,至此已经完成一台已安装JDK的主机第二部分:准备3台虚拟机以下所有工作最好都在root权限下操作1 克隆上面已经有一台虚拟机了,现在对master进行克隆,克隆出另外2台子机;1.1 进行克隆21.2 下一步1.3 下一步1.4 下一步1.5 根据子机需要,命名和安装路径1.6 ..._创建一个hadoop项目

心脏滴血漏洞HeartBleed CVE-2014-0160深入代码层面的分析_heartbleed代码分析-程序员宅基地

文章浏览阅读1.7k次。心脏滴血漏洞HeartBleed CVE-2014-0160 是由heartbeat功能引入的,本文从深入码层面的分析该漏洞产生的原因_heartbleed代码分析

java读取ofd文档内容_ofd电子文档内容分析工具(分析文档、签章和证书)-程序员宅基地

文章浏览阅读1.4k次。前言ofd是国家文档标准,其对标的文档格式是pdf。ofd文档是容器格式文件,ofd其实就是压缩包。将ofd文件后缀改为.zip,解压后可看到文件包含的内容。ofd文件分析工具下载:点我下载。ofd文件解压后,可以看到如下内容: 对于xml文件,可以用文本工具查看。但是对于印章文件(Seal.esl)、签名文件(SignedValue.dat)就无法查看其内容了。本人开发一款ofd内容查看器,..._signedvalue.dat

基于FPGA的数据采集系统(一)_基于fpga的信息采集-程序员宅基地

文章浏览阅读1.8w次,点赞29次,收藏313次。整体系统设计本设计主要是对ADC和DAC的使用,主要实现功能流程为:首先通过串口向FPGA发送控制信号,控制DAC芯片tlv5618进行DA装换,转换的数据存在ROM中,转换开始时读取ROM中数据进行读取转换。其次用按键控制adc128s052进行模数转换100次,模数转换数据存储到FIFO中,再从FIFO中读取数据通过串口输出显示在pc上。其整体系统框图如下:图1:FPGA数据采集系统框图从图中可以看出,该系统主要包括9个模块:串口接收模块、按键消抖模块、按键控制模块、ROM模块、D.._基于fpga的信息采集

微服务 spring cloud zuul com.netflix.zuul.exception.ZuulException GENERAL-程序员宅基地

文章浏览阅读2.5w次。1.背景错误信息:-- [http-nio-9904-exec-5] o.s.c.n.z.filters.post.SendErrorFilter : Error during filteringcom.netflix.zuul.exception.ZuulException: Forwarding error at org.springframework.cloud..._com.netflix.zuul.exception.zuulexception

邻接矩阵-建立图-程序员宅基地

文章浏览阅读358次。1.介绍图的相关概念  图是由顶点的有穷非空集和一个描述顶点之间关系-边(或者弧)的集合组成。通常,图中的数据元素被称为顶点,顶点间的关系用边表示,图通常用字母G表示,图的顶点通常用字母V表示,所以图可以定义为:  G=(V,E)其中,V(G)是图中顶点的有穷非空集合,E(G)是V(G)中顶点的边的有穷集合1.1 无向图:图中任意两个顶点构成的边是没有方向的1.2 有向图:图中..._给定一个邻接矩阵未必能够造出一个图

随便推点

MDT2012部署系列之11 WDS安装与配置-程序员宅基地

文章浏览阅读321次。(十二)、WDS服务器安装通过前面的测试我们会发现,每次安装的时候需要加域光盘映像,这是一个比较麻烦的事情,试想一个上万个的公司,你天天带着一个光盘与光驱去给别人装系统,这将是一个多么痛苦的事情啊,有什么方法可以解决这个问题了?答案是肯定的,下面我们就来简单说一下。WDS服务器,它是Windows自带的一个免费的基于系统本身角色的一个功能,它主要提供一种简单、安全的通过网络快速、远程将Window..._doc server2012上通过wds+mdt无人值守部署win11系统.doc

python--xlrd/xlwt/xlutils_xlutils模块可以读xlsx吗-程序员宅基地

文章浏览阅读219次。python–xlrd/xlwt/xlutilsxlrd只能读取,不能改,支持 xlsx和xls 格式xlwt只能改,不能读xlwt只能保存为.xls格式xlutils能将xlrd.Book转为xlwt.Workbook,从而得以在现有xls的基础上修改数据,并创建一个新的xls,实现修改xlrd打开文件import xlrdexcel=xlrd.open_workbook('E:/test.xlsx') 返回值为xlrd.book.Book对象,不能修改获取sheett_xlutils模块可以读xlsx吗

关于新版本selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘等问题_unresolved attribute reference 'find_element_by_id-程序员宅基地

文章浏览阅读8.2w次,点赞267次,收藏656次。运行Selenium出现'WebDriver' object has no attribute 'find_element_by_id'或AttributeError: 'WebDriver' object has no attribute 'find_element_by_xpath'等定位元素代码错误,是因为selenium更新到了新的版本,以前的一些语法经过改动。..............._unresolved attribute reference 'find_element_by_id' for class 'webdriver

DOM对象转换成jQuery对象转换与子页面获取父页面DOM对象-程序员宅基地

文章浏览阅读198次。一:模态窗口//父页面JSwindow.showModalDialog(ifrmehref, window, 'dialogWidth:550px;dialogHeight:150px;help:no;resizable:no;status:no');//子页面获取父页面DOM对象//window.showModalDialog的DOM对象var v=parentWin..._jquery获取父window下的dom对象

什么是算法?-程序员宅基地

文章浏览阅读1.7w次,点赞15次,收藏129次。算法(algorithm)是解决一系列问题的清晰指令,也就是,能对一定规范的输入,在有限的时间内获得所要求的输出。 简单来说,算法就是解决一个问题的具体方法和步骤。算法是程序的灵 魂。二、算法的特征1.可行性 算法中执行的任何计算步骤都可以分解为基本可执行的操作步,即每个计算步都可以在有限时间里完成(也称之为有效性) 算法的每一步都要有确切的意义,不能有二义性。例如“增加x的值”,并没有说增加多少,计算机就无法执行明确的运算。 _算法

【网络安全】网络安全的标准和规范_网络安全标准规范-程序员宅基地

文章浏览阅读1.5k次,点赞18次,收藏26次。网络安全的标准和规范是网络安全领域的重要组成部分。它们为网络安全提供了技术依据,规定了网络安全的技术要求和操作方式,帮助我们构建安全的网络环境。下面,我们将详细介绍一些主要的网络安全标准和规范,以及它们在实际操作中的应用。_网络安全标准规范