第二次作业:卷积神经网络 part 1

视频学习

数学基础

受结构限制严重,生成式模型效果往往不如判别式模型。

RBM:数学上很漂亮,且有统计物理学支撑,但主流深度学习平台不支持RBM和预训练。

自编码器:正则自编码器、稀疏自编码器、去噪自编码器和变分自编码器。

  • 概率/函数形式统一:

  • 欠拟合、过拟合解决方案:

    • 欠拟合:提高模型复杂度

      • 决策树:拓展分支
      • 神经网络:增加训练轮数
    • 过拟合1:降低模型复杂度
      • 优化目标加正则项
      • 决策树:剪枝
      • 神经网络:early stop、dropout
    • 过拟合2:数据增广(训练集越大,越不容易过拟合)
      • 计算机视觉:图像旋转、缩放、剪切
      • 自然语言处理:同义词替换
      • 语音识别:添加随机噪声
  • 交叉熵与对数损失函数关系:如果把所有样本取均值就把交叉熵转化成了对数损失函数。

平方损失函数假设高斯分布,而分类问题是二项/多项分布,对数损失与二项/多项分布下的最大似然等价。

  • 频率学派:参数估计只依赖观测数据
  • 贝叶斯学派:参数估计同时依赖观测数据和先验知识

卷积神经网络CNN

  • 基本应用:分类、检索、检测、分割、人脸识别、图像生成、风格转化、自动驾驶

  • 深度学习三部曲:搭建神经网络、损失函数、优化函数

  • 全连接网络处理图像问题:参数太多:权重矩阵的参数太多 -> 过拟合

  • 卷积神经网络的解决方法:局部关联,参数共享

  • CNN组成:CONV layer卷积层、RELU layer激活层、POOL layer池化层、FC layer全连接层

  • 卷积操作:

kernel/filter:卷积核/滤波器

stride:步长

weights:权重

receptive field:感受野

activation map 或 feature map:特征图

padding :填充

depth/channel:深度/通道

  • 特征图大小计算公式:(N-F+padding*2)/stride+1,输入为N×N,卷积核为F×F

  • 池化(pooling):保留了主要特征的同时减少了参数和计算量,防止过拟合,提高模型泛化能力

    • Max pooling:最大值池化
    • Average pooling:平均值池化

ps:池化层无参数,且不改变通道个数

缩小图像(或称为下采样(subsampled)或降采样(downsampled))

原理:对于一幅图像I尺寸为MN,对其进行s倍下采样,即得到(M/s)(N/s)尺寸的得分辨率图像,当然s应该是M和N的公约数才行,如果考虑的是矩阵形式的图像,就是把原始图像s*s窗口内的图像变成一个像素,这个像素点的值就是窗口内所有像素的均值。

目的:1.使得图像符合显示区域的大小。2.生成对应图像的缩略图。

放大图像(或称为上采样(upsampling)或图像插值(interpolating))

原理:图像放大几乎都是采用内插值方法,即在原有图像像素的基础上在像素点之间采用合适的插值算法插入新的元素。

目的:放大原图像,从而可以显示在更高分辨率的显示设备上。

  • 全连接(Fully Connected):

    • 两层之间的所有神经元都有权重链接
    • 通常全连接层在卷积神经网络尾部
    • 全连接层参数量通常最大
  • 卷积神经网络典型结构:

  • AlexNet

    • ILSVRC2012冠军,错误率下降十个百分点,深度学习转折点
    • 大数据训练:百万级ImageNet图像数据
    • 非线性激活函数:ReLU
      • 解决了梯度消失问题(在正区间)
      • 计算速度特别快,只需要判断输入是否大于0
      • 收敛速度远快于Sigmoid
    • 防止过拟合1:Dropout(随机失活)
      • 训练时随机关闭部分神经元,测试时整合所有神经元
    • 防止过拟合2:Data augmentation(数据增强)
      • 平移、翻转、对称

        • 随机crop。训练的时候,对于256×256的图片进行随机crop到224×224
        • 水平翻转,相当于将样本倍增
      • 改变RGB通道强度
        • 对RGB空间做一个高斯扰动
    • 其他:双GPU实现

ps:Dropout训练时为0.5,测试时设置0

  • ZFNet

    • ILSVRC2013冠军,14.8%
    • 网络结构与AlexNet相同
    • 提取更详细信息:将卷积层1中的感受野大小由11×11改为7×7,步长由4改为2
    • 卷积层3、4、5中的滤波器个数由384,384,256改为512,512,1024
  • VGG

    • ILSVRC2014亚军,7.3%
    • 是一个更深的网络:8 layers(AlexNet) -> 16 - 19(VGG)
    • 广泛用于迁移学习

因为当时没有Batch Normalization,较深网络训练的方法是先训练前面层,然后冻结前面层参数,再训练后面层。

  • GoogLeNet

    • ILSVRC2014冠军,6.7%
    • 组成
      • 卷积层池化层:卷积—池化—卷积—卷积—池化
      • Inception模块:多个Inception结构堆叠
      • 辅助分类器:解决过深导致梯度消失问题,作用不大,v3拿掉
      • 除分类外没有额外FC层:网络很深,但参数量仅为AlexNet的1/12
    • Naive Inception
      • 多种卷积核增加特征多样性(conv1×1,conv3×3,conv5×5,pool3×3)
      • 在深度上进行串联:padding使结果大小保持一致
      • 通道非常大:计算复杂度过高
    • Inception v2
      • 插入1×1卷积核进行降维:减小通道数,降低参数量
    • Inception v3
      • 用两个3×3卷积核代替5×5卷积核:对应感受野大小一样

        • 进一步对v2参数量进行降低
        • 增加非线性激活函数(激活两次):使网络产生更多独立特征(disentangled feature),表征能力更强,训练更快

Inception结构最初由GoogLeNet引入,GoogLeNet叫做Inception-v1;之后引入了BatchNormalization,叫做Inception-v2;随后引入分解,叫做Inception-v3。

ResNet

  • 残差学习网络(deep residual learning network)
  • ILSVRC2015冠军,3.57%
  • 深度有152层
  • 除了输出层外没有其他全连接层
  • 残差的思想:去掉相同的主体部分,从而突出微小的变化
  • 可以被用来训练非常深的网络,不会出现梯度消失

代码练习

MNIST数据集分类

  • 创建全连接网络和卷积神经网络
class FC2Layer(nn.Module):
def __init__(self, input_size, n_hidden, output_size):
# nn.Module子类的函数必须在构造函数中执行父类的构造函数
# 下式等价于nn.Module.__init__(self)
super(FC2Layer, self).__init__()
self.input_size = input_size
# 这里直接用 Sequential 就定义了网络,注意要和下面 CNN 的代码区分开
self.network = nn.Sequential(
nn.Linear(input_size, n_hidden),
nn.ReLU(),
nn.Linear(n_hidden, n_hidden),
nn.ReLU(),
nn.Linear(n_hidden, output_size),
nn.LogSoftmax(dim=1)
)
def forward(self, x):
# view一般出现在model类的forward函数中,用于改变输入或输出的形状
# x.view(-1, self.input_size) 的意思是多维的数据展成二维
# 代码指定二维数据的列数为 input_size=784,行数 -1 表示我们不想算,电脑会自己计算对应的数字
# 在 DataLoader 部分,我们可以看到 batch_size 是64,所以得到 x 的行数是64
# 大家可以加一行代码:print(x.cpu().numpy().shape)
# 训练过程中,就会看到 (64, 784) 的输出,和我们的预期是一致的 # forward 函数的作用是,指定网络的运行过程,这个全连接网络可能看不啥意义,
# 下面的CNN网络可以看出 forward 的作用。
x = x.view(-1, self.input_size)
return self.network(x) class CNN(nn.Module):
def __init__(self, input_size, n_feature, output_size):
# 执行父类的构造函数,所有的网络都要这么写
super(CNN, self).__init__()
# 下面是网络里典型结构的一些定义,一般就是卷积和全连接
# 池化、ReLU一类的不用在这里定义
self.n_feature = n_feature
self.conv1 = nn.Conv2d(in_channels=1, out_channels=n_feature, kernel_size=5)
self.conv2 = nn.Conv2d(n_feature, n_feature, kernel_size=5)
self.fc1 = nn.Linear(n_feature*4*4, 50)
self.fc2 = nn.Linear(50, 10) # 下面的 forward 函数,定义了网络的结构,按照一定顺序,把上面构建的一些结构组织起来
# 意思就是,conv1, conv2 等等的,可以多次重用
def forward(self, x, verbose=False):
x = self.conv1(x)
x = F.relu(x)
x = F.max_pool2d(x, kernel_size=2)
x = self.conv2(x)
x = F.relu(x)
x = F.max_pool2d(x, kernel_size=2)
x = x.view(-1, self.n_feature*4*4)
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
x = F.log_softmax(x, dim=1)
return x
  • 定义训练与测试函数

控制变量:全连接网络与CNN拥有相同数量的模型参数。

这里分两次进行:第一次不打乱像素顺序,第二次打乱像素顺序。

# 对每个 batch 里的数据,打乱像素顺序的函数

def perm_pixel(data, perm):
# 转化为二维矩阵
data_new = data.view(-1, 28*28)
# 打乱像素顺序
data_new = data_new[:, perm]
# 恢复为原来4维的 tensor
data_new = data_new.view(-1, 1, 28, 28)
return data_new # 训练函数
def train_perm(model, perm):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
# 像素打乱顺序
# data = perm_pixel(data, perm) optimizer.zero_grad()
output = model(data)
loss = F.nll_loss(output, target)
loss.backward()
optimizer.step()
if batch_idx % 100 == 0:
print('Train: [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
batch_idx * len(data), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item())) # 测试函数
def test_perm(model, perm):
model.eval()
test_loss = 0
correct = 0
for data, target in test_loader:
data, target = data.to(device), target.to(device) # 像素打乱顺序
# data = perm_pixel(data, perm) output = model(data)
test_loss += F.nll_loss(output, target, reduction='sum').item()
pred = output.data.max(1, keepdim=True)[1]
correct += pred.eq(target.data.view_as(pred)).cpu().sum().item() test_loss /= len(test_loader.dataset)
accuracy = 100. * correct / len(test_loader.dataset)
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
test_loss, correct, len(test_loader.dataset),
accuracy))

不打乱像素顺序的情况下全连接与CNN准确率分别为88%、96%

打乱像素顺序的情况下全连接与CNN准确率分别为87%、84%

从结果来看,全连接网络的性能基本上没有发生变化,但是CNN的性能明显下降,卷积和池化就难以发挥作用。

这是因为CNN会利用像素的局部关系,但是打乱顺序以后,这些像素间的关系将无法得到利用。

CIFAR10数据集分类

PyTorch 创建了一个叫做 totchvision 的包,该包含有支持加载类似Imagenet,CIFAR10,MNIST 等公共数据集的数据加载模块 torchvision.datasets 和支持加载图像数据转换模块 torch.utils.data.DataLoader。

CIFAR-10数据集,它包含十个类别:‘airplane’, ‘automobile’, ‘bird’, ‘cat’, ‘deer’, ‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’。图像尺寸为3x32x32,也就是RGB的3层颜色通道,每层通道内的尺寸为32*32。

  • 训练网络
for epoch in range(10):  # 重复多轮训练
for i, (inputs, labels) in enumerate(trainloader):
inputs = inputs.to(device)
labels = labels.to(device)
# 优化器梯度归零
optimizer.zero_grad()
# 正向传播 + 反向传播 + 优化
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# 输出统计信息
if i % 100 == 0:
print('Epoch: %d Minibatch: %5d loss: %.3f' %(epoch + 1, i + 1, loss.item())) print('Finished Training')

使用CNN训练10个epoch后在整个数据集上的表现准确率为64%

对于复杂多分类问题可以改进CNN使得性能进一步提升,具体可采用Dropout、Data Augmentation等方法,或者采用下面更强大的网络结构。

使用VGG16对CIFAR10分类

  • VGG16模型

训练测试步骤同上。

使用VGG训练10个epoch后在整个数据集上的表现准确率为83%

我们发现将网络参数改小后,一个简化版的VGG仍然能够显著地将准确率从64%提升到83%。

VGG名称来源于牛津大学视觉几何组(Visual Geometry Group)的缩写。

该模型参加2014年的ImageNet图像分类与定位挑战赛,取得了优异成绩:在分类任务上排名第二,在定位任务上排名第一。

猫狗大战(VGG模型迁移学习)

在源代码基础上做了以下改进,进一步提高准确率:

  1. 数据增强:在数据处理的地方加入旋转

  2. 使用VGG19:相比VGG16网络更深,表现更优

  3. 采用Adam优化器,并将学习率调整为3e-4:相比SGD优化能力更强,学习率比较玄学

  4. 增大训练样本:使得训练结果更精确

import numpy as np
import matplotlib.pyplot as plt
import os
import torch
import torch.nn as nn
import torchvision
from torchvision import models,transforms,datasets
import time
import json # 判断是否存在GPU设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print('Using gpu: %s ' % torch.cuda.is_available())
  • 下载数据:

因为数据集文件存储结构与规范格式不一样,需要加入一些对数据的操作,这里感谢之前同学分享的方法。

! wget https://static.leiphone.com/cat_dog.rar

# 解压rar压缩包,需要安装rarfile库(pip install rarfile)
! pip install rarfile
import rarfile
path = "cat_dog.rar"
path2 = "/content/" rf = rarfile.RarFile(path) #待解压文件
rf.extractall(path2) #解压指定文件路径 ! mkdir cat_dog/val/Dog
! mkdir cat_dog/val/Cat
! mkdir cat_dog/train/Cat
! mkdir cat_dog/train/Dog
! mkdir cat_dog/test/test
! mv cat_dog/val/dog* cat_dog/val/Dog/
! mv cat_dog/val/cat* cat_dog/val/Cat/
! mv cat_dog/train/cat* cat_dog/train/Cat/
! mv cat_dog/train/dog* cat_dog/train/Dog/
! mv cat_dog/test/*.jpg cat_dog/test/test
  • 数据处理:

torchvision支持对输入数据进行一些预处理/变换,图片将被整理成 224×224×3 的大小,同时还将进行归一化处理。

normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])

vgg_format = transforms.Compose([
# transforms.RandomHorizontalFlip(p=0.5), # 水平翻转
# transforms.RandomVerticalFlip(p=0.5), # 垂直翻转
# transforms.RandomRotation(30), # 随机旋转
transforms.CenterCrop(224),
transforms.ToTensor(),
normalize,
]) data_dir = './cat_dog' dsets = {x: datasets.ImageFolder(os.path.join(data_dir, x), vgg_format)
for x in ['train', 'val']} tsets = {y: datasets.ImageFolder(os.path.join(data_dir, y), vgg_format)
for y in ['test']} dset_sizes = {x: len(dsets[x]) for x in ['train', 'val']}
dset_classes = dsets['train'].classes loader_train = torch.utils.data.DataLoader(dsets['train'], batch_size=64, shuffle=True, num_workers=6)
loader_valid = torch.utils.data.DataLoader(dsets['val'], batch_size=5, shuffle=False, num_workers=6) loader_test = torch.utils.data.DataLoader(tsets['test'],batch_size=5,shuffle=False,num_workers=6)
  • 创建VGG Model:

使用预训练好的CNN模型,迁移学习。

我们可以看到VGG对于1000分类的表现也非常出色,可以细分到猫的具体种类。

# ImageNet 1000类的JSON文件展示VGG预测结果
!wget https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json
# 使用了VGG19
model_vgg = models.vgg19(pretrained=True) with open('./imagenet_class_index.json') as f:
class_dict = json.load(f)
dic_imagenet = [class_dict[str(i)][1] for i in range(len(class_dict))] inputs_try , labels_try = inputs_try.to(device), labels_try.to(device)
model_vgg = model_vgg.to(device) outputs_try = model_vgg(inputs_try) print(outputs_try)
print(outputs_try.shape) '''
可以看到结果为5行,1000列的数据,每一列代表对每一种目标识别的结果。
但是我也可以观察到,结果非常奇葩,有负数,有正数,
为了将VGG网络输出的结果转化为对每一类的预测概率,我们把结果输入到 Softmax 函数
'''
m_softm = nn.Softmax(dim=1)
probs = m_softm(outputs_try)
vals_try,pred_try = torch.max(probs,dim=1) print( 'prob sum: ', torch.sum(probs,1))
print( 'vals_try: ', vals_try)
print( 'pred_try: ', pred_try) print([dic_imagenet[i] for i in pred_try.data])
imshow(torchvision.utils.make_grid(inputs_try.data.cpu()),
title=[dset_classes[x] for x in labels_try.data.cpu()])

  • 修改最后一层,冻结前面层的参数:

VGG 模型由三种元素组成:

  1. 卷积层(CONV)是发现图像中局部的 pattern

  2. 全连接层(FC)是在全局上建立特征的关联

  3. 池化(Pool)是给图像降维以提高特征的 invariance

print(model_vgg)

model_vgg_new = model_vgg;

for param in model_vgg_new.parameters():
param.requires_grad = False # 冻结前面层的参数
model_vgg_new.classifier._modules['6'] = nn.Linear(4096, 2) # 1000类替换为2类(4096为全连接层维度)
model_vgg_new.classifier._modules['7'] = torch.nn.LogSoftmax(dim = 1) model_vgg_new = model_vgg_new.to(device) print(model_vgg_new.classifier)
  • 训练并测试全连接层:

    • 创建损失函数和优化器
    • 训练模型
    • 测试模型
'''
第一步:创建损失函数和优化器 损失函数 NLLLoss() 的 输入 是一个对数概率向量和一个目标标签.
它不会为我们计算对数概率,适合最后一层是log_softmax()的网络.
'''
criterion = nn.NLLLoss()
# 二分类:NLLLoss(负对数似然损失函数)
# criterion = nn.CrossEntropyLoss()
# 多分类:CrossEntropyLoss(交叉熵损失函数) # 学习率 Adam最优3e-4
lr = 0.0003 # 随机梯度下降
# optimizer_vgg = torch.optim.SGD(model_vgg_new.classifier[6].parameters(),lr = lr)
# Adam
optimizer_vgg = torch.optim.Adam(model_vgg_new.classifier[6].parameters(),lr = lr) '''
第二步:训练模型
''' def train_model(model,dataloader,size,epochs=1,optimizer=None):
model.train() for epoch in range(epochs):
running_loss = 0.0
running_corrects = 0
count = 0
for inputs,classes in dataloader:
inputs = inputs.to(device)
classes = classes.to(device)
outputs = model(inputs)
loss = criterion(outputs,classes)
optimizer = optimizer
optimizer.zero_grad()
loss.backward()
optimizer.step()
_,preds = torch.max(outputs.data,1)
# statistics
running_loss += loss.data.item()
running_corrects += torch.sum(preds == classes.data)
count += len(inputs) # 可调整训练图像序号,增大训练样本
print('Training: No. ', count, ' process ... total: ', size)
epoch_loss = running_loss / size
epoch_acc = running_corrects.data.item() / size
print('Loss: {:.4f} Acc: {:.4f}'.format(
epoch_loss, epoch_acc)) # 模型训练
train_model(model_vgg_new,loader_train,size=dset_sizes['train'], epochs=1,
optimizer=optimizer_vgg)
# 第三步:测试模型
def test_model(model,dataloader,size):
model.eval()
predictions = np.zeros(size)
all_classes = np.zeros(size)
all_proba = np.zeros((size,2))
i = 0
running_loss = 0.0
running_corrects = 0
for inputs,classes in dataloader:
inputs = inputs.to(device)
classes = classes.to(device)
outputs = model(inputs)
loss = criterion(outputs,classes)
_,preds = torch.max(outputs.data,1)
# statistics
running_loss += loss.data.item()
running_corrects += torch.sum(preds == classes.data)
predictions[i:i+len(classes)] = preds.to('cpu').numpy()
all_classes[i:i+len(classes)] = classes.to('cpu').numpy()
all_proba[i:i+len(classes),:] = outputs.data.to('cpu').numpy()
i += len(classes)
print('Testing: No. ', i, ' process ... total: ', size)
epoch_loss = running_loss / size
epoch_acc = running_corrects.data.item() / size
print('Loss: {:.4f} Acc: {:.4f}'.format(
epoch_loss, epoch_acc))
return predictions, all_proba, all_classes predictions, all_proba, all_classes = test_model(model_vgg_new,loader_valid,size=dset_sizes['val'])

  • 输出CSV类型文件:

import re

# 得到测试图片编号
string = tsets['test'].imgs[0][0]
num = re.sub("\D", "", string) result = []
# 将测试数据集(test)输入到网络中,得到识别结果
for item,lable in loader_test:
item = item.to(device)
ll = model_vgg_new(item)
_,pre = torch.max(ll.data,1) result += pre # 结果排序
result_end =list() cc = 0 for item in result:
string = tsets['test'].imgs[cc][0]
num = re.sub("\D", "", string)
result_end.append((num,item.tolist()))
cc += 1 result_sort = sorted(result_end,key=lambda x:int(x[0])) # 写入文件
import csv f = open('out_file.csv','w')
writer = csv.writer(f)
for i in result_sort:
writer.writerow(i)
f.close()

第二次作业:卷积神经网络 part 1的更多相关文章

  1. 【新生学习】第二周:卷积神经网络_part_1

    DEADLINE: 2020-08-01 22:00 写在最前面: 本周学习的是卷积神经网络,是本课程重点中的重点,大家务必要熟练掌握. 本周的学习任务包括 视频学习 . 代码练习 .论文讲解 三部分 ...

  2. 第二次作业:卷积神经网络 part 2

    第二次作业:卷积神经网络 part 2 问题总结 输出层激活函数是否有必要? 为什么DnCNN要输出残差图片?图像复原又该如何操作? DSCMR中的J2损失函数效果并不明显,为什么还要引入呢? 代码练 ...

  3. 基于卷积神经网络的面部表情识别(Pytorch实现)----台大李宏毅机器学习作业3(HW3)

    一.项目说明 给定数据集train.csv,要求使用卷积神经网络CNN,根据每个样本的面部图片判断出其表情.在本项目中,表情共分7类,分别为:(0)生气,(1)厌恶,(2)恐惧,(3)高兴,(4)难过 ...

  4. 卷积神经网络提取特征并用于SVM

    模式识别课程的一次作业.其目标是对UCI的手写数字数据集进行识别,样本数量大约是1600个.图片大小为16x16.要求必须使用SVM作为二分类的分类器. 本文重点是如何使用卷积神经网络(CNN)来提取 ...

  5. tensorflow学习笔记五:mnist实例--卷积神经网络(CNN)

    mnist的卷积神经网络例子和上一篇博文中的神经网络例子大部分是相同的.但是CNN层数要多一些,网络模型需要自己来构建. 程序比较复杂,我就分成几个部分来叙述. 首先,下载并加载数据: import ...

  6. Deep Learning模型之:CNN卷积神经网络(一)深度解析CNN

    http://m.blog.csdn.net/blog/wu010555688/24487301 本文整理了网上几位大牛的博客,详细地讲解了CNN的基础结构与核心思想,欢迎交流. [1]Deep le ...

  7. [DL学习笔记]从人工神经网络到卷积神经网络_1_神经网络和BP算法

    前言:这只是我的一个学习笔记,里边肯定有不少错误,还希望有大神能帮帮找找,由于是从小白的视角来看问题的,所以对于初学者或多或少会有点帮助吧. 1:人工全连接神经网络和BP算法 <1>:人工 ...

  8. lecture5-对象识别与卷积神经网络

    Hinton第五课 突然不知道object recognition 该翻译成对象识别好,还是目标识别好,还是物体识别好,但是鉴于范围性,还是翻译成对象识别吧.这一课附带了两个论文<Convolu ...

  9. Deep Learning论文笔记之(四)CNN卷积神经网络推导和实现(转)

    Deep Learning论文笔记之(四)CNN卷积神经网络推导和实现 zouxy09@qq.com http://blog.csdn.net/zouxy09          自己平时看了一些论文, ...

随机推荐

  1. hdu 4352 XHXJ's LIS 数位DP+最长上升子序列

    题目描述 #define xhxj (Xin Hang senior sister(学姐))If you do not know xhxj, then carefully reading the en ...

  2. 前端进阶笔记(一)---JS语言通识

    一.语言按照语法分类 1.非形式语言:中文 英文 2.形式语言:乔姆斯基谱系(四种文法 上下文包含文法) 0型 无限制文法 1型 上下文相关文法 2型 上下文无关文法 正则文法 二 产生式(BNF) ...

  3. Java入门系列之final

    前言 在C#经典面试中掺杂过Java的final关键字,主要用于类不能被继承,在C#则是利用关键字seal修饰类为密封类,而在Java中的final关键字的具体用法包含C#中const.readonl ...

  4. 十年老苹果(A1286)强升Catalina及Win10踩坑记

    前言 手头有一台十年老苹果,MacBook Pro,A1286,连视网膜屏都没有,电池也早就衰减以后直接拆掉了(减重). 早些年用得还挺多,后来家里也弄了台式,用得逐渐少了,再后来时不时Windows ...

  5. AI芯片

    课程作业,正好自己也在学深度学习,正好有所帮助,做了深度学习的AI芯片调研,时间比较短,写的比较仓促,大家随便看看 近年来,深度学习技术,如卷积神经网络(CNN).递归神经网络(RNN)等,成为计算机 ...

  6. 一篇文章,学会jmeter模拟文件上传、下载操作

    最近很多同学都在问jmeter上传,下载文件的脚本怎么做? 正巧这阵子忙完有时间,就来“折腾”一番,哈哈 现整理出来和大家分享 到底该怎么做? 一.准备工作: 上传接口一个(自行开发解决了) 下载接口 ...

  7. C# 人脸识别库 0.2

    ViewFaceCore 0.2 超简单的 C# 人脸识别库 前言: 首先谢谢大家对这个库的关注,前一篇博文得到了大家的 支持 和 Star,十分开心.本想尽快实现大家的期待的活体检测功能,但是前段时 ...

  8. 洛谷 P5350 序列 珂朵莉树

    题目描述 分析 操作一.二.三为珂朵莉树的基本操作,操作四.五.六稍作转化即可 不会珂朵莉树请移步至这里 求和操作 把每一段区间分别取出,暴力相加 ll qh(ll l,ll r){ it2=Spli ...

  9. 题解 CF1354D 【Multiset】

    考试拿到题,一看,这不是权值线段树吗? 思路 使用线段树每个节点维护该区间内元素出现次数. 根据题目,对于加入.删除元素,我们可以单点修改(\(+1\).\(-1\)),对于输出,我们可 随便 遍历找 ...

  10. PyQt5布局管理器

    布局分类 绝对定位:使用move方法将空间直接定死在某个坐标,不会随着窗口大小的改变而改变 可变布局:使用各种布局管理器,实现组件的位置和大小随着窗口的变化而变化 布局管理器 QHBoxLayout: ...