高考考试网
当前位置: 首页 高考资讯

卷积神经网络需要什么电脑(还是这样理解更简单)

时间:2023-08-16 作者: 小编 阅读量: 5 栏目名: 高考资讯

卷积神经网络的兴起大大促进了深度学习研究的发展。在2012年的ImageNet计算机视觉识别比赛中,卷积神经网络AlexNet以准确率领先第二名10%的显著差距获得了第一名。在卷积神经网络中,这种隐含层被称为“特征图”。图中小窗口覆盖的输入区域卷积结果是隐含层的灰色部分,结果为2。如此一来,在一个隐含层的情况下,卷积神经网络的权重数目可以减小至全连接神经网络权重数目的一万分之一,大大减少计算量,提高计算效率。

互联网发展至今,已经存储了海量的网络图片,但是这些图片被形象地称为互联网的“暗物质”,因为现在的计算机还难以分类或识别这些非结构性的图片数据。在早期的图像识别研究中,使用人工提取的特征造成识别效果不佳。卷积神经网络(Convolutional Neural Network, CNN)的出现给图像识别领域带来了崭新的风气,如今,CNN图像识别技术的正确率已经可以达到人类水平。卷积神经网络的兴起大大促进了深度学习研究的发展。

下面我们来研究下卷积神经网络的基本原理,为接下来的实战打好基础。

仿生模型

20 世纪60 年代,神经科学家们研究了猫的脑皮层中用于局部敏感和方向选择的神经元,在这个过程中,他们发现猫的脑皮层所具有的独特网络结构可以有效地降低反馈神经网络的复杂性,研究结果显示:视觉系统的信息处理是分级的。

大脑分层处理的视觉原理如图1所示:首先,光信号进入瞳孔(视网膜),接着大脑皮层的初级视觉细胞(即V1 区)对信号进行初步处理,发现图像的边缘和方向;然后进入下一层视觉细胞(即V2 区)进行抽象,发现物体的形状;最后在V4 区进一步抽象出物体的概念。

图1 人脑视觉处理机制

卷积神经网络模型的物体识别模仿了人脑的视觉处理机制,采用分级提取特征的原理,每一级的特征均由网络学习提取,识别效果优于人工选取特征的算法。例如在人脸识别过程中,最底层特征基本上是各方向上的边缘,越往上的神经层越能提取出人脸的局部特征(比如眼睛、嘴巴、鼻子等),最上层由不同的高级特征组合成人脸的图像。该模型最早在1998 年由Yann LeCun 提出并应用在手写字体识别上(MINST),LeCun 提出的网络称为LeNet,其网络结构如图2所示,输入的手写字体图片经过两次卷积和池化,进入全连接层后分类输出10 种结果。

图2 LeNet 结构示意图

LeNet 结构简单却完美地诠释了卷积神经网络的结构和其惊人的识别成效,被称为深度神经网络的“果蝇”。囿于当时计算硬件的落后和网络图片数量的不足,卷积神经网络无法在分辨率较大的图片上展示它的巨大潜力,当时并没有引起广泛关注。在2012 年的ImageNet 计算机视觉识别比赛中,卷积神经网络AlexNet 以准确率领先第二名10% 的显著差距获得了第一名。从此,大批计算机视觉科学家纷纷加入了卷积神经网络的研究当中,深度学习的热潮开始兴起。

卷积

在我们前面所介绍的神经网络《这是我看过,最好懂的神经网络》中,输入层被描述为一列神经元,而在卷积神经网络里,我们把输入层看作二维的神经元。如果输入是像素大小为28×28 的图片①,则可以看作28×28 的二维神经元,它的每一个节点对应图片在这个像素点的灰度值,如图3所示。

① PX(Picture Element)就是我们常说的像素,它是构成影像的最小单位。像素是一个相对的单位,当图片尺寸以像素为单位时,我们需要指定其固定的分辨率,才能将图片尺寸与现实中的实际尺寸相转换,因此经常会省略PX和像素,如本句表达为“像素大小为28×28 的图片”或“大小为28×28 的图片”。

图3 输入图片的二维展示

在传统的神经网络中,我们会把输入层的节点与隐含层的所有节点相连。卷积神经网络中,采用“局部感知”的方法,即不再把输入层的每个节点都连接到隐含层的每一个神经元节点上。如图4所示,我们把相邻的5×5 局部区域内的输入节点连接到了第一个隐含层的一个节点上。这个相邻的区域,我们称为局部感知域,可以把它看成是一个小窗口,我们也称之为过滤器。

图4 输入层与隐含层的连接

如图5 所示,我们可以在整个输入图像上滑动这个过滤器。对于每一个过滤器,都有一个隐含层的神经元与之对应。将过滤器向右滑动一个单位后对应一个隐含层的神经元节点。以此类推,我们构建出了第一个隐含层。在这个例子中,输入是28×28,并且使用5×5 的过滤器,那么第一个隐含层的大小为24×24。因为过滤器的小窗口只能向右和向下移动23 像素,再往下或者往右移动就会移出图像的边界。在这个图中,过滤器使用的滑动单位为1 像素,实际上,我们也可以让滑动单位不止1 像素,这个滑动值的英文叫stride,我们也称它为步长。在卷积神经网络中,这种隐含层被称为“特征图”。

图5 过滤器的移动

在进行卷积操作之前,需要定义一个过滤器,其中的每一格都有一个权重值。卷积的过程是将每个格子中的权重值与图片对应的像素值相乘并累加,所得到的值就是特征图中的一个像素值。如图6 所示,我们对过滤器和卷积进行一个比较具体而详细的说明。假设我们输入的是5×5 的图片,过滤器可以看作一个小窗口,这个小窗口大小是3×3,里面包含了9 个权重值,我们将9 个权重值分别与输入的一部分像素值相乘后进行累加,这个过程被称为“卷积”。图中小窗口覆盖的输入区域卷积结果是隐含层的灰色部分,结果为2。隐含层的结果就是我们通过卷积生成的特征图。

图6 过滤器的卷积过程

此外,我们发现,即便步长为1,经过卷积之后的特征图尺寸也会缩小。由于过滤器在移动到边缘的时候就结束了,中间的像素点比边缘的像素点参与计算的次数要多。因此越是边缘的点,对输出的影响就越小,我们就有可能丢失边缘信息。为了解决这个问题,我们进行填充,英文叫padding,即在图片外围补充一些像素点,并将这些像素点的值初始化为0。

为什么卷积

在传统全连接的神经网络中,如果要对一张图片进行分类,连接方式如图7所示。我们把一张大小为100×100 的图片的每个像素点都连接到每一个隐含层的节点上,如果隐含层的节点数为10 000,那么连接的权重总数则为10的8次方个。当图片像素更大,隐含层的节点数目更多时,则需要更加庞大的权重数目。

图7 全连接神经网络的权重数目

在卷积神经网络中,我们不再需要如此庞大的权重数目。如图8 所示,在利用10×10 的过滤器对100×100 的原图进行卷积时,该过滤器在不断滑动的过程中对应生成一张特征图,即一个过滤器(100 个权重值)可对应一张特征图。如果我们有100 张特征图,则一共只需要10的4次方个权重值。

如此一来,在一个隐含层的情况下,卷积神经网络的权重数目可以减小至全连接神经网络权重数目的一万分之一,大大减少计算量,提高计算效率。

图8 卷积神经网络的权重数目

在实际训练的过程中,第一层的每一个过滤器的权重值会不断地被更新优化,最终形成如图3-40所示的结果,每个过滤器的可视化纹理模式基本上反映了各个方向上的边缘特征。图9 为我们展示了24 个过滤器的纹理模式,这24 种边缘可以描绘出我们的原图。

图9 过滤器的可视化

池化

池化的目的是降低数据的维度,过程很简单,实际上就是下采样。具体过程如图10 所示,假如特征图的尺寸是8×8,池化的窗口为4×4,则对特征图按照每4×4 进行一次采样,生成一个池化特征值。这样一来,8×8 的特征图可以生成一个2×2 的池化特征图。

图10 池化过程

在实际应用中,生成池化特征的方式一般有两种:最大值池化(Max-Pooling)与平均值池化(Mean-Pooling)。其中,最大值池化的方法是将特征图中池化窗口范围内的最大值作为池化结果的特征值,过程如图11所示;平均值池化的方法是将特征图中池化窗口范围内的所有值进行平均后作为池化的特征值。

图11 最大池化

实战:用PyTorch 构建卷积神经网络

下面,我们尝试利用PyTorch 构建卷积神经网络。这里以LeNet 网络为例,利用MINST 手写字体库进行训练,实现一个手写体的自动识别器。

1. LeNet——深度学习界的“果蝇”

LeNet是1998年由Yann LeCun提出的一种卷积神经网络,当时已经被美国大多数银行用于识别支票上的手写数字。详细资料可以浏览LeNet-5官网http://yann.lecun.com/exdb/lenet/,图12是LeNet进行手写体识别时,输入图片、各层特征图的可视化形式及其最终的识别结果。

图12 LeNet 进行手写体识别

LeNet-5 的结构如图2所示:

其网络结构比较简单,如果不包括输入,它一共有7 层,输入图像的大小为28×28。通过上面的学习,我们可以分辨出C1 层为6 张特征图,由6 个大小为5×5 的卷积核过滤生成,特征图的尺寸为24×24。S2 是池化层,采用最大池化法,池化窗口大小为2×2。因此,6 张24×24 的特征图池化后会生成6 张12×12 的池化特征图。C3 层是卷积层,一共有16 个过滤器,生成16 张8×8 大小的特征图,卷积核大小为5×5。这里,S2 与C3 的连接组合方式并不是固定的,C3层的每一张特征图可以连接S2 层中的全部或者部分特征图。一般情况下,为了更好地降低总连接数,并不使用全部特征图的全连接方式。S4 是池化层,它是由16 张8×8 的特征图最大池化生成的16 张4×4的特征图,其池化核大小为2×2。F5 是全连接层,一共有120 个神经元节点,每个节点与S4 层的16张池化特征图进行连接。因此,F5 层与S4 层是全连接。F6 层有84 个神经元节点,与F5 进行全连接。最后一层为输出层,把输出的神经元节点数设为10,代表0 到9 的分值。

2. 准备数据集

MNIST 是一个手写数字数据库(官网地址:http://yann.lecun.com/exdb/mnist/)。如图13 所示,该数据库有60 000 张训练样本和10 000 张测试样本,每张图的像素尺寸为28×28。其中train-imagesidx3-ubyte.gz 为训练样本集,train-labels-idx1-ubyte.gz 为训练样本的标签集,t10k-images-idx3-ubyte.gz为测试样本集,t10k-labels-idx1-ubyte.gz 为测试样本的标签集。这些图片文件均被保存为二进制格式。

图13 MNIST 官网

我们现在需要用到上述这些数据集。幸运的是,PyTorch 为我们编写了快速下载并加载MNIST 数据集的方法。为了方便图像的运用开发,PyTorch 团队为我们专门编写了处理图像的工具包:torchvision。

torchvision里面包含了图像的预处理、加载等方法,还包括了数种经过预训练的经典卷积神经网络模型。

下面用一个例子给大家介绍。首先我们从torchvision库中导入datasets和transforms,datasets是加载图像数据的方法,transforms是图像数据预处理的方法:

from torchvision import datasets, transforms

然后我们使用transforms.Compose()函数设置预处理的方式:

transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ])

这里可依次填写需要进行数据预处理的方法。这个例子中,我们只用了两种方法,其中transforms.ToTensor()是将数据转化为Tensor对象,transforms.Normalize()是将数据进行归一化处理。

接下来我们使用datasets.MNIST()函数分别下载训练数据集和测试数据集:

trainset = datasets.MNIST('data', train=True, download=True, transform=transform)testset = datasets.MNIST('data', train=False, download=True, transform=transform)

data.MNIST的第一个参数指定了数据集下载并存储的目标文件夹;train=True表示加载训练数据集,train=False表示加载测试数据集;这里我们令download=True,代表使用这个函数帮助我们自动下载MNIST数据集;transform的设置代表我们使用刚才定义的数据预处理方法。

接下来,运行上述的代码,程序就会自动下载MNIST数据集:

Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gzDownloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gzDownloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gzDownloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gzProcessing...Done!

显示以上信息后,如图14所示,我们会发现代码所在目录下新增了一个data文件夹,里面包含了processed和raw文件夹,其中raw文件夹里面包含了MNIST数据集的训练和测试的数据与标签。

图14 自动下载MNIST数据集

3. 构建LeNet

准备好数据之后,我们可以开始构建LeNet模型。我们知道,初始化函数需要先运行父类的初始化函数。先定义C1卷积层,PyTorch中的nn.Conv2d()函数为我们简化了卷积层的构建。在C1层的定义中,第一个参数为1,代表输入1张灰度图;第二个参数为6,代表输出6张特征图;第三个参数是一个元组 (5, 5),也可以简化成5,代表大小为5×5的卷积核过滤器。然后定义C3卷积层,C3输入6张特征图,输出16张特征图,过滤器大小仍为5×5。接着定义全连接层,其中fc1是由池化层S4中的所有特征点(共16×4×4个)全连接到120个点,fc2是由120个点全连接到84个点,fc3是由84个点全连接到输出层中的10个输出节点。

定义完初始函数之后,我们开始定义foward()函数。c1卷积之后,使用relu()函数增加了网络的非线性拟合能力,接着使用F.max_pool2d()函数对c1的特征图进行池化,池化核大小为2×2,也可以简化参数为2。经过两轮卷积和池化之后,使用view函数将x的形状转化成1维的向量,其中我们自定义了num_flat_features()函数来计算x的特征点的总数。在自定义的num_flat_features()函数中,由于PyTorch只接受批数据输入的方式(即同时输入好几张图片进行处理),所以我们在经过view()函数之前的x是4个维度的。假设我们批量输入4张图片,则x.size()的结果为(4,16,4,4)。我们使用x.size()[1:]返回x的第二维以后的形状,即(16,4,4)。因此,按照num_flat_features()函数返回的数值为16×4×4,即256,随后进行全连接fc1、fc2和fc3:

class LeNet(nn.Module): def __init__(self): super(LeNet,self).__init__() self.c1 = nn.Conv2d(1,6,(5,5)) self.c3 = nn.Conv2d(6,16,5) self.fc1 = nn.Linear(16*4*4,120) self.fc2 = nn.Linear(120,84) self.fc3 = nn.Linear(84,10) def forward(self,x): x = F.max_pool2d(F.relu(self.c1(x)),2) x = F.max_pool2d(F.relu(self.c3(x)),2) x = x.view(-1,self.num_flat_features(x)) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return xdef num_flat_features(self,x): size = x.size()[1:] num_features = 1 for s in size: num_features *= s return num_features

接下来我们初始化LeNet,并定义损失函数为交叉熵函数,优化器为随机梯度下降:

CUDA = torch.cuda.is_available()if CUDA: lenet = LeNet().cuda()else: lenet = LeNet()criterion=nn.CrossEntropyLoss()optimizer = optim.SGD(lenet.parameters(),lr=0.001,momentum=0.9)

随后,用PyTorch的数据加载工具DataLoader来加载训练数据:

trainloader = torch.utils.data.DataLoader(trainset,batch_size=4, shuffle=True,num_workers=2)

上面DataLoader()的参数中,batch_size表示一次性加载的数据量,shuffle=True表示遍历不同批次的数据时打乱顺序,num_workers=2表示使用两个子进程加载数据。

4. 训练

现在开始训练LeNet,我们将完全遍历训练数据2次。为了方便观察训练过程中损失值loss的变化情况,定义变量running_loss。一开始,我们将running_loss设为0.0,随后对输入每一个训练数据后的loss值进行累加,每训练1000次打印一次loss均值,并清零。enumerate(trainloader,0)表示从第0项开始对trainloader中的数据进行枚举,返回的i是序号,data是我们需要的数据,其中包含了训练数据和标签。随后我们进行前向传播和反向传播。代码如下:

def train(model,criterion,optimizer,epochs=1): for epoch in range(epochs): running_loss = 0.0 for i, data in enumerate(trainloader,0): inputs,labels = data if CUDA: inputs,labels = inputs.cuda(),labels.cuda() optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs,labels) loss.backward() optimizer.step()running_loss= loss.item() if i00==999: print('[Epoch:%d, Batch:]] Loss: %.3f' % (epoch 1, i 1, running_loss / 1000)) running_loss = 0.0print('Finished Training') train(lenet,criterion,optimizer,epochs=2)

运行结果如下:

[Epoch:1, Batch: 1000] loss: 1.336[Epoch:1, Batch: 2000] loss: 0.293[Epoch:1, Batch: 3000] loss: 0.213[Epoch:1, Batch: 4000] loss: 0.157[Epoch:1, Batch: 5000] loss: 0.144[Epoch:1, Batch: 6000] loss: 0.120[Epoch:1, Batch: 7000] loss: 0.109[Epoch:1, Batch: 8000] loss: 0.106[Epoch:1, Batch: 9000] loss: 0.117[Epoch:1, Batch:10000] loss: 0.098[Epoch:1, Batch:11000] loss: 0.072[Epoch:1, Batch:12000] loss: 0.095[Epoch:1, Batch:13000] loss: 0.084[Epoch:1, Batch:14000] loss: 0.073[Epoch:1, Batch:15000] loss: 0.079[Epoch:2, Batch: 1000] loss: 0.065[Epoch:2, Batch: 2000] loss: 0.065[Epoch:2, Batch: 3000] loss: 0.072[Epoch:2, Batch: 4000] loss: 0.070[Epoch:2, Batch: 5000] loss: 0.055[Epoch:2, Batch: 6000] loss: 0.047[Epoch:2, Batch: 7000] loss: 0.058[Epoch:2, Batch: 8000] loss: 0.051[Epoch:2, Batch: 9000] loss: 0.066[Epoch:2, Batch:10000] loss: 0.047[Epoch:2, Batch:11000] loss: 0.066[Epoch:2, Batch:12000] loss: 0.059[Epoch:2, Batch:13000] loss: 0.054[Epoch:2, Batch:14000] loss: 0.058[Epoch:2, Batch:15000] loss: 0.062Finished Training

从结果中可以发现,我们的训练是有效的,损失值loss的平均值从1.336逐渐优化并下降为0.062。

5. 存储与加载

我们训练完神经网络之后,需要存储训练好的参数,以方便以后使用。存储的方式有两种。

(1) 存储和加载模型

存储:

torch.save(lenet, 'model.pkl')

加载:

lenet = torch.load('model.pkl')

利用torch.save()函数直接传入整个网络模型lenet,并设置存储的路径。这种方法虽然简洁,但在神经网络比较复杂的时候,会占用较大的存储空间。

(2) 存储和加载模型参数

存储:

torch.save(lenet.state_dict(),'model.pkl')

加载:

lenet.load_state_dict(torch.load('model.pkl'))

这种方法直接保存模型参数,节省了空间,但是它不存储模型的结构,所以在加载时需要先构造好模型结构。

在这个例子中,我们倾向于使用第二种方法,利用os包的exists()方法检查是否存在模型参数文件。构造load_param()和save_param()函数方便随时调用:

def load_param(model,path): if os.path.exists(path): model.load_state_dict(torch.load(path))def save_param(model,path): torch.save(model.state_dict(),path)

6. 测试

神经网络模型经过长时间的训练之后,能在训练集的数据上表现得很好,并不一定代表它在训练集以外的数据上同样表现优异。为了更加客观地衡量神经网络模型的识别率,我们通常需要另外一批数据进行测试。为此,设置train=False准备测试集,并设置testloader对测试集进行加载:

testset = datasets.MNIST('data', train=False, download=True, transform=transform)testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)

下面我们对训练完成的神经网络添加测试模块:

def test(testloader,model): correct = 0 total = 0 for data in testloader: images, labels = data if CUDA: images = images.cuda() labels = labels.cuda() outputs = model(images) _, predicted = torch.max(outputs.data, 1)total= labels.size(0) correct= (predicted == labels).sum() print('Accuracy on the test set: %d %%' % (100 * correct / total))

我们创建一个test()函数,传入testloader和model对象,让testloader中的测试数据经过神经网络,得到outputs,再使用torch.max(outputs.data,1)找出每一组10个输出值中最大的那个值,并将该值所在的序号保存在predicted变量中。total用于累计labels的总数,correct用于累计正确的结果总数:

load_param(lenet,'model.pkl')train(lenet,criterion,optimizer,epochs=2)save_param(lenet,'model.pkl')test(testloader,lenet)

可以在训练前加载之前训练完成的参数,训练后对参数进行保存,接着进行测试,测试结果如下:

Accuracy on the test set: 98 %

fastai库

PyTorch的生态圈非常丰富,AllenNLP、ELP、fastai、Glow、GPyTorch、Horovod、ParlAI、Pyro、TensorLy等库都是基于PyTorch开发的AI工具,可以帮助我们更加快速地开发AI产品。fastai库(https://www.fast.ai)致力于使用当前最先进的实践方法去简化传统的神经网络训练方法,提高训练速度。fastai可以帮助程序员更加高效地训练神经网络,用它来实现MNIST手写字体识别只需要短短7行代码。如果系统安装的PyTorch版本在1.0以上,那么可以直接安装并使用fastai 1.0版本。

1. 安装

使用conda命令进行安装:

conda install -c fastai fastai

我们也可以使用pip命令进行安装:

pip install fastai

2. 代码实践

导入fastai中的vision包:

from fastai.vision import *

使用untar_data()函数,传入参数URLs.MNIST_SAMPLE,下载并解压MNIST数据包:

path = untar_data(URLs.MNIST_SAMPLE)

创建一个DataBunch:

data = ImageDataBunch.from_folder(path)

初始化一个Learner,传入数据data,设置模型为resnet18。调用fit()函数开始训练,fit()函数的参数为训练次数,这里仅训练1次:

learner = create_cnn(data, models.resnet18, metrics=accuracy)learner.fit(1)

训练和测试完成后,打印如下:

epoch train loss valid loss accuracy0 0.078617 0.041789 0.984789

除了图片识别之外,fastai还提供了自然语言处理、协同过滤以及结构数据处理等应用,由于篇幅有限,本文不再细致讲解。

——

本文我们介绍了卷积神经网络的基本原理,用当下很流行的深度学习框架PyTorch构建了一个卷积神经网络。最后,我们还了解了fastai,可以用短短几行代码构建深度卷积网络,完成了识别手写字体的小实验。

——本文节选自《PyTorch深度学习入门》

这是文章阅读量10万 的作者倾力打造的一份超简单PyTorch入门教程。对于想要理解深度学习的人的第一选择。

它更适合小白的思路与讲解方式:从硬件挑选、系统配置开始,图文并茂,手把手教你搭建神经网络。

书中从如何挑选硬件到神经网络的初步搭建,再到实现图片识别、文本翻译、强化学习、生成对抗网络等多个目前最流行的深度学习应用。书中基于目前流行的PyTorch框架,运用Python语言实现了各种深度学习的应用程序,让理论和实践紧密结合。

第一部分 基础篇

第1章 准备工作

第2章 Tensor基础

第3章 深度学习基础

第二部分 实战篇

第4章 迁移学习

第5章 序列转序列模型

第6章 生成对抗网络

第7章 深度强化学习

第8章 风格迁移

第三部分 高级篇

第9章 PyTorch扩展

第10章 PyTorch模型迁移

第11章 PyTorch可视化

第12章 PyTorch的并行计算

    推荐阅读
  • 河南省委书记楼阳生到双汇参观调研

    2月8日,河南省委书记楼阳生到双汇参观调研。双汇作为农业产业化国家重点龙头企业,依托自身优势和产业规模,在转化粮食、农产品加工、转移农村劳动力、农民增收等方面积极发挥龙头企业的引领作用。同时,双汇持续推进产业升级、技术改造,不断增强企业竞争力。在总部漯河,双汇投资6亿多元对两个核心项目进行技术改造。这两个项目的投产,为双汇肉类产业升级奠定了基础、创建了样板,提升了传统肉类加工业的生产国际化水平。

  • 儿童护眼灯十大排名(专业护眼灯什么牌子好)

    超国标AA标准和真实护眼效果,非常适合青少年学习和年轻人办公使用。为了能让用户以更低预算的价格得到千元护眼台灯的体验,南卡将护眼台灯当作防护产品去创新打造。南卡这款主打护眼功能的台灯,基本是按照一比一打造千元级护眼台灯产品品质标准生产、检测、品检流程,光品质检测项目多达50多项,一般的护眼台灯就5-10项。照度和均匀度都只达到国A级标准,能适合普通日常的轻量学习。

  • 如何做小蛋糕简单(小蛋糕如何做简单)

    我们一起去了解并探讨一下这个问题吧!如何做小蛋糕简单鸡蛋4个,底筋面粉100克,白砂糖100克。碗中打入一个鸡蛋,倒入白砂糖。分三次过筛面粉。搅拌至无干粉状态。烤箱预热5分钟,烤焙25分钟。一份杯子蛋糕就完成了。

  • 地漏十大品牌排行榜(性价比高的地漏品牌)

    地漏是地面与排水管道系统连接的排水器具,选择时应以防臭性能好的优先,现在市面上防臭地漏品牌很多,但有些是否真正能起到防臭效果就有待考证了。很多不知道的人在选择的时候要参照防臭地漏品牌来进行购买,下面简单介绍下防臭地漏品牌都有哪些吧。

  • 厦门植物园南门停车场开放时间(厦门植物园东门停车场)

    厦门植物园南门停车场开放时间每天6:30开放,18:00开始只出不进。厦门植物园南门停车场位于南门广场左侧和地下两层,共有270个车位,其中地面停车场上还特别设置了28个大巴车位,无论是散客自驾,还是团队大巴都能找到自己的位置,方便车辆停放和上下客。

  • 韩式焖鱼的做法(韩式焖鱼怎么做好吃)

    接下来我们就一起去研究一下吧!韩式焖鱼的做法扒皮鱼肉切块,加入姜,葱,柠檬片。加入盐,糖,生抽腌制30分钟。去除腌制料头,洒上面粉,让鱼块均匀地包裹上。锅烧热,放油,下鱼块煎制。煎至两面金黄,入姜片炒香。调入韩式辣酱,生抽,蚝油等等调味料,中火焖5分钟。香芹段,葱段,小红尖椒粒入锅,同时开大火收汁,汁浓即可出锅盛盘。

  • 赵丽颖和冯绍峰真的在一起了吗(刚刚官宣完的赵丽颖和冯绍峰)

    赵丽颖冯绍峰官宣结婚照刚刚官宣完的赵丽颖和冯绍峰,夫妻搭档出新戏,期待一下。赵丽颖剧照都说可怜之人必有可爱之处,那本来就可爱的人都可爱到逆天了。时常在想赵丽颖拍戏还要那么认真就说不过去了。说完了赵丽颖,来谈谈她的先生冯绍峰,名声不是特别好,因为绯闻比较多,但是现在和颖宝结婚之后,希望他一改在粉丝心目中的形象哦!

  • 如何做珍珠奶茶(珍珠奶茶怎么做)

    我们一起去了解并探讨一下这个问题吧!如何做珍珠奶茶食材:木薯粉80g,黑糖15g,水55g,淡奶1/3杯,奶茶咖啡糖1包,红茶包1个。煮沸的糖水加入木薯粉中,快速搅拌。取黄豆粒大小的面团搓成丸子。完成后,撒上木薯粉。锅中加水,煮沸后下丸子。煮至呈透明状浮起。捞起放入冰水中。茶壶放进茶包倒进开水,加盖泡五分钟。杯子里倒入半杯泡好的茶水。

  • 关于感恩的简短美句(关于感恩的简短美句高中)

    我们要感恩团队,感恩集体的每一个人给予自己的关心,帮助和支持,感念团队共建的每一份荣誉和成功。感谢对手,感谢敌人,是乐观。

  • 华为手机pdf如何转成word文档(一秒将纸质文档转成电子文档)

    在我们日常的工作和生活中,可能会遇到需要将纸质文档转为电子文档的时刻,这个时候你会怎么做?是出去赶紧找复印店吗?手持华为手机的用户就不用担心这个问题,我们可以不依靠外界的帮助就能达成目标。打开手机中自带的功能,一秒将纸质文档转为电子文档,简直太赞了!当然,如果你手机找不到该功能,又有这方面的需求。好了,以上就是华为手机实现纸质文档转电子文档的方法,有需要的小伙伴快去试试吧!