机器学习--卷积神经网络(包括python实现)

卷积神经网络

1. 计算方法

(1)输入和输出channel = 1时

  首先我们要知道channel是什么意思,顾名思义channel就是“通道”的意思qwq。我们来举个例子,在计算机视觉中,如果一张图片是黑白的,那么每个像素点都是有一个信息也就是这个像素点的灰度。但是对于一张彩色图片来说,每个像素点都是由三个信息叠加而成的,也就是 R B G RBG RBG 三个颜色的“灰度”。

  于是我们对黑白照片操作变成矩阵的时候,我们就会直接将灰度拿来用,把它变成一个二维的矩阵。

  而对于彩色照片来说,我们就会建立一个高为 3 3 3 的三维张量来存储这个图片。这里的所谓“高度3”就是我们的channel。

  这里我们先说只有一个通道的时候(也就是二维的时候)卷积网络的计算方法,我们来看这样一个图:

在这里插入图片描述
  这里就很形象的展示了卷积的计算方法,其中 3 × 3 3 \times 3 3×3 的矩阵我们叫做 输入矩阵 2 × 2 2 \times 2 2×2 的蓝色矩阵叫做 核函数,最后得到的 2 × 2 2 \times 2 2×2 的白色矩阵叫做 输出矩阵

  其中,我们有:

0 × 0 + 1 × 1 + 3 × 2 + 4 × 3 = 19 0 × 1 + 2 × 1 + 4 × 2 + 5 × 3 = 25 3 × 0 + 4 × 1 + 6 × 2 + 7 × 3 = 37 4 × 0 + 5 × 1 + 7 × 2 + 8 × 3 = 43 0 \times 0 + 1 \times 1 + 3 \times 2 + 4 \times 3 = 19 \\ 0 \times 1 + 2 \times 1 + 4 \times 2 + 5 \times 3 = 25 \\ 3 \times 0 + 4 \times 1 + 6 \times 2 + 7 \times 3 = 37 \\ 4 \times 0 + 5 \times 1 + 7 \times 2 + 8 \times 3 = 43 0×0+1×1+3×2+4×3=190×1+2×1+4×2+5×3=253×0+4×1+6×2+7×3=374×0+5×1+7×2+8×3=43

  这就是最基本的计算方法了。

  用代码写出来就是这样:

from mxnet import gluon, np, npx, autograd, nd
from mxnet.gluon import nndata = nd.arange(9).reshape((1, 1, 3, 3))
w = nd.arange(4).reshape((1, 1, 2, 2))
out = nd.Convolution(data, w, nd.array([0]), kernel = w.shape[2:], num_filter = w.shape[0])
print("input :", data, "\n\nweight :", w, "\n\noutput :", out)

  输出出来是这样:

input : 
[[[[0. 1. 2.][3. 4. 5.][6. 7. 8.]]]]
<NDArray 1x1x3x3 @cpu(0)> weight : 
[[[[0. 1.][2. 3.]]]]
<NDArray 1x1x2x2 @cpu(0)> output : 
[[[[19. 25.][37. 43.]]]]
<NDArray 1x1x2x2 @cpu(0)>

(2)对于输入的channel > 1 但 输出的channel = 1的时候

  然后对于channe 输入的channel > 1但输出的channel = 1的时候,我们还是举例说明计算方法:

在这里插入图片描述

  这里我们的输入矩阵变成了红色的这两个,也就是一个 2 × 3 × 3 2 \times 3 \times 3 2×3×3 的张量,而我们的核函数变成了这两个蓝色的,也就是一个 2 × 2 × 2 2 \times 2 \times 2 2×2×2 的张量。我们计算时,分别对对应的张量进行一次卷积,得到黄色的两个矩阵,然后再把这俩加起来就得到了输出矩阵。

  写代码的话就是这样:

w = nd.arange(8).reshape((1, 2, 2, 2))
data = nd.arange(18).reshape((1, 2, 3, 3))
out = nd.Convolution(data, w, nd.array([0]), kernel = w.shape[2:], num_filter = w.shape[0])
print("input :", data, "\n\nweight :", w, "\n\noutput :", out)

  输出就是这样:

input : 
[[[[ 0.  1.  2.][ 3.  4.  5.][ 6.  7.  8.]][[ 9. 10. 11.][12. 13. 14.][15. 16. 17.]]]]
<NDArray 1x2x3x3 @cpu(0)> weight : 
[[[[0. 1.][2. 3.]][[4. 5.][6. 7.]]]]
<NDArray 1x2x2x2 @cpu(0)> output : 
[[[[268. 296.][352. 380.]]]]
<NDArray 1x1x2x2 @cpu(0)>

(3)对于输入的channel > 1 且 输出的channel > 1的时候

  还是老样子,举个例子:

在这里插入图片描述

  这里的输入变成了 3 × 3 × 3 3 \times 3 \times 3 3×3×3 的张量,而我们的核函数则是 2 × 3 × 1 × 1 2 \times 3 \times 1 \times 1 2×3×1×1 的张量。这里,我们的计算方法就是用核函数的第一层跟输入做一次卷积,得到第一个矩阵,然后用核函数的第二层和输入再做一次卷积得到第二个矩阵,这两个矩阵就是我们的输出了。

  代码如下:

data = nd.arange(27).reshape((1, 3, 3, 3))
w = nd.arange(6).reshape((2, 3, 1, 1))
out = nd.Convolution(data, w, nd.array([0, 0]), kernel = w.shape[2:], num_filter = w.shape[0])
print("input :", data, "\n\nweight :", w, "\n\noutput :", out)

  输出:

input : 
[[[[ 0.  1.  2.][ 3.  4.  5.][ 6.  7.  8.]][[ 9. 10. 11.][12. 13. 14.][15. 16. 17.]][[18. 19. 20.][21. 22. 23.][24. 25. 26.]]]]
<NDArray 1x3x3x3 @cpu(0)> weight : 
[[[[0.]][[1.]][[2.]]][[[3.]][[4.]][[5.]]]]
<NDArray 2x3x1x1 @cpu(0)> output : 
[[[[ 45.  48.  51.][ 54.  57.  60.][ 63.  66.  69.]][[126. 138. 150.][162. 174. 186.][198. 210. 222.]]]]
<NDArray 1x2x3x3 @cpu(0)>

(4) 关于代码的一些事

  我们把刚才的三段代码贴过来,然后我们观察一下看看能不能发现什么规律:

data = nd.arange(9).reshape((1, 1, 3, 3))
w = nd.arange(4).reshape((1, 1, 2, 2))
out = nd.Convolution(data, w, nd.array([0]), kernel = w.shape[2:], num_filter = w.shape[0])
print("input :", data, "\n\nweight :", w, "\n\noutput :", out)
w = nd.arange(8).reshape((1, 2, 2, 2))
data = nd.arange(18).reshape((1, 2, 3, 3))
out = nd.Convolution(data, w, nd.array([0]), kernel = w.shape[2:], num_filter = w.shape[0])
print("input :", data, "\n\nweight :", w, "\n\noutput :", out)
data = nd.arange(27).reshape((1, 3, 3, 3))
w = nd.arange(6).reshape((2, 3, 1, 1))
out = nd.Convolution(data, w, nd.array([0, 0]), kernel = w.shape[2:], num_filter = w.shape[0])
print("input :", data, "\n\nweight :", w, "\n\noutput :", out)

  我们会发现,我们的 d a t a . s h a p e data.shape data.shape w . s h a p e w.shape w.shape b . s h a p e b.shape b.shape 都是有讲究的,其中 d a t a . s h a p e = ( b a t c h _ s i z e , c h a n n e l s , h e i g h t , w i d t h ) data.shape = (batch\_size, channels, height, width) data.shape=(batch_size,channels,height,width),而 w . s h a p e = ( n u m _ f i l t e r , i n p u t _ c h a n n e l s , k e r n e l _ h e i g h t , k e r n e l _ w i d t h ) w.shape = (num\_filter, input\_channels, kernel\_height, kernel\_width) w.shape=(num_filter,input_channels,kernel_height,kernel_width)。然后就是 b . s h a p e = ( 1 , n u m _ f i l t e r ) b.shape = (1, num\_filter) b.shape=(1,num_filter)

2. padding & strides

(1) 填充 Padding

  如上所述,在应用多层卷积时,我们常常丢失边缘像素。由于我们通常使用小卷积核,因此对于任何单个卷积,我们可能只会丢失几个像素。但随着我们应用许多连续卷积层,累积丢失的像素数就多了。解决这个问题的简单方法即为填充(padding):在输入图像的边界填充元素(通常填充元素是 0 0 0)。例如,:numref:img_conv_pad中,我们将 3 × 3 3 \times 3 3×3输入填充到 5 × 5 5 \times 5 5×5,那么它的输出就增加为 4 × 4 4 \times 4 4×4。阴影部分是第一个输出元素以及用于输出计算的输入和核张量元素: 0 × 0 + 0 × 1 + 0 × 2 + 0 × 3 = 0 0\times0+0\times1+0\times2+0\times3=0 0×0+0×1+0×2+0×3=0

在这里插入图片描述

  代码是这样的:


w = nd.arange(4).reshape((1, 1, 2, 2))
data = nd.arange(9).reshape((1, 1, 3, 3))
out = nd.Convolution(data, w, nd.array([0]), kernel = w.shape[2:], num_filter = w.shape[0], pad = (1, 1))       # pad:矩阵向外扩展的距离
print("input :", data, "\n\nweight :", w, "\n\noutput :", out)

  output:

input : 
[[[[0. 1. 2.][3. 4. 5.][6. 7. 8.]]]]
<NDArray 1x1x3x3 @cpu(0)> weight : 
[[[[0. 1.][2. 3.]]]]
<NDArray 1x1x2x2 @cpu(0)> output : 
[[[[ 0.  3.  8.  4.][ 9. 19. 25. 10.][21. 37. 43. 16.][ 6.  7.  8.  0.]]]]
<NDArray 1x1x4x4 @cpu(0)>

(2) 步幅 Strides

  我们看之前看到的都是每次把 k e r n e l kernel kernel 对准的一方移动一格所计算出来的输出,而 s t r i d e stride stride 就是用来控制每次移动的步幅的:

在这里插入图片描述
  这里就是 s t r i d e = ( 2 , 2 ) stride = (2, 2) stride=(2,2) 说明步幅是 2 2 2,那我们每次移动就走两格。所以红色和 k e r n e l kernel kernel 乘起来就是 24 24 24,蓝色和 k e r n e l kernel kernel 乘起来就是 36 36 36,以此类推。

  代码如下:

data = nd.arange(16).reshape((1, 1, 4, 4))
w = nd.arange(4).reshape((1, 1, 2, 2))
out = nd.Convolution(data, w, nd.array([0]), kernel = w.shape[2:], num_filter = w.shape[0], stride = (2, 2))
print("input :", data, "\n\nweight :", w, "\n\noutput :", out)

  输出:

input : 
[[[[ 0.  1.  2.  3.][ 4.  5.  6.  7.][ 8.  9. 10. 11.][12. 13. 14. 15.]]]]
<NDArray 1x1x4x4 @cpu(0)> weight : 
[[[[0. 1.][2. 3.]]]]
<NDArray 1x1x2x2 @cpu(0)> output : 
[[[[24. 36.][72. 84.]]]]
<NDArray 1x1x2x2 @cpu(0)>

3. 汇聚层 Pooling

  与卷积层类似,汇聚层运算符由一个固定形状的窗口组成,该窗口根据其步幅大小在输入的所有区域上滑动,为固定形状窗口(有时称为汇聚窗口)遍历的每个位置计算一个输出。 然而,不同于卷积层中的输入与卷积核之间的互相关计算,汇聚层不包含参数。 相反,池运算是确定性的,我们通常计算汇聚窗口中所有元素的最大值或平均值。这些操作分别称为最大汇聚层(maximum pooling)和平均汇聚层(average pooling)

  这里我们先说最大汇聚层:

在这里插入图片描述

  这里其实就是:

max ⁡ { 0 , 1 , 3 , 4 } = 4 max ⁡ { 1 , 2 , 4 , 5 } = 5 max ⁡ { 3 , 4 , 6 , 7 } = 7 max ⁡ { 4 , 5 , 7 , 8 } = 8 \max\{0, 1, 3, 4\} = 4 \\ \max\{1, 2, 4, 5\} = 5 \\\max\{3, 4, 6, 7\} = 7 \\ \max\{4, 5, 7, 8\} = 8 max{0,1,3,4}=4max{1,2,4,5}=5max{3,4,6,7}=7max{4,5,7,8}=8

  再有就是平均汇聚层,其实跟上面一样,只是把 max ⁡ \max max 换成了 m e a n ( ) mean() mean() 而已

  代码如下:

data = nd.arange(9).reshape((1, 1, 3, 3))                                                      # 关于pooling
max_pool = nd.Pooling(data = data, pool_type = 'max', kernel = (2, 2))
avg_pool = nd.Pooling(data = data, pool_type = 'avg', kernel = (2, 2))
print("data :", data, "\n\nmax pool :", max_pool, "\n\navg pool :", avg_pool)

  输出:

data : 
[[[[0. 1. 2.][3. 4. 5.][6. 7. 8.]]]]
<NDArray 1x1x3x3 @cpu(0)> max pool : 
[[[[4. 5.][7. 8.]]]]
<NDArray 1x1x2x2 @cpu(0)> avg pool : 
[[[[2. 3.][5. 6.]]]]
<NDArray 1x1x2x2 @cpu(0)>

LeNet

  说白了,这玩意儿就是用卷积层 convolution layer 替换了普通神经网络中的全连接层 dense layer,其他的也没什么区别…

  首先就是一堆import

from mxnet import gluon
from mxnet.gluon import nn
from d2l import mxnet as d2l
from mxnet import autograd, nd
import matplotlib.pyplot as plt

  然后就是定义我们的 L e N e t LeNet LeNet,也就是两层 c o n v o l u t i o n convolution convolution 每次 m a x p o o l i n g maxpooling maxpooling 一下,再搞一层 d e n s e l a y e r dense \;\; layer denselayer 再输出:

net = nn.Sequential()
with net.name_scope():net.add(nn.Conv2D(channels = 20, kernel_size = 5, activation = 'relu'))net.add(nn.MaxPool2D(pool_size = 2, strides = 2))net.add(nn.Conv2D(channels = 50, kernel_size = 3, activation = 'relu'))net.add(nn.MaxPool2D(pool_size = 2, strides = 2))net.add(nn.Flatten())net.add(nn.Dense(128, activation = 'relu'))net.add(nn.Dense(10))ctx = d2l.try_gpu()                                                  # 试试gpu能不能跑 如果报错则返回cpu
print("context :", ctx)
net.initialize(ctx = ctx)
print(net)

  运行这段 代码后会输出以下内容:

context : cpu(0)
Sequential((0): Conv2D(None -> 20, kernel_size=(5, 5), stride=(1, 1), Activation(relu))(1): MaxPool2D(size=(2, 2), stride=(2, 2), padding=(0, 0), ceil_mode=False, global_pool=False, pool_type=max, layout=NCHW)(2): Conv2D(None -> 50, kernel_size=(3, 3), stride=(1, 1), Activation(relu))(3): MaxPool2D(size=(2, 2), stride=(2, 2), padding=(0, 0), ceil_mode=False, global_pool=False, pool_type=max, layout=NCHW)(4): Flatten(5): Dense(None -> 128, Activation(relu))(6): Dense(None -> 10, linear)
)

  然后就是从 m n i s t mnist mnist load数据下来:

batch_size, num_epoch, lr = 256, 10, 0.5
train_data, test_data = d2l.load_data_fashion_mnist(batch_size)

  然后跟我们的 s o f t m a x r e g r e s s i o n softmax \;\; regression softmaxregression 里面一样,定义一些函数:

softmax_cross_entropy = gluon.loss.SoftmaxCrossEntropyLoss()                          # 损失函数
trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate' : lr})          # sgddef accuracy(output, label):                                                          # 计算拟合的准确度return nd.mean(output.argmax(axis = 1) == label.astype('float32')).asscalar()     # argmax是把每一列的最大概率的index返回出来 然后和label比较是否相同 最后所有求个meandef evaluate_accuracy(data_itetator, net, context):acc = 0.for data, label in data_itetator:output = net(data)acc += accuracy(output, label)return acc / len(data_itetator)

  然后就是开始训练了(也和前面的 s o f t m a x r e g r e s s i o n softmax \;\; regression softmaxregression 是一样的:

for epoch in range(num_epoch):train_loss, train_acc = 0., 0.for data, label in train_data:label = label.as_in_context(ctx)with autograd.record():out = net(data.as_in_context(ctx))loss = softmax_cross_entropy(out, label)loss.backward()trainer.step(batch_size)train_loss += nd.mean(loss).asscalar()train_acc += accuracy(out, label)# test_acc = 0.test_acc = evaluate_accuracy(test_data, net, ctx)print("Epoch  %d. Loss : %f, Train acc : %f, Test acc : %f" %(epoch, train_loss / len(train_data), train_acc / len(train_data), test_acc))

  我们运行之后就能得到一下输出:

Epoch  0. Loss : 1.155733, Train acc : 0.567287, Test acc : 0.761133
Epoch  1. Loss : 0.558990, Train acc : 0.782680, Test acc : 0.826172
Epoch  2. Loss : 0.465726, Train acc : 0.821543, Test acc : 0.848633
Epoch  3. Loss : 0.420673, Train acc : 0.838697, Test acc : 0.857227
Epoch  4. Loss : 0.382026, Train acc : 0.855740, Test acc : 0.869824
Epoch  5. Loss : 0.358218, Train acc : 0.865320, Test acc : 0.871094
Epoch  6. Loss : 0.335073, Train acc : 0.873648, Test acc : 0.881641
Epoch  7. Loss : 0.317190, Train acc : 0.881250, Test acc : 0.884863
Epoch  8. Loss : 0.303633, Train acc : 0.885882, Test acc : 0.886133
Epoch  9. Loss : 0.291287, Train acc : 0.889993, Test acc : 0.886719

  我们能看出这个的 t e s t a c c u r a c y test \;\; accuracy testaccuracy 要比 s o f t m a x softmax softmax 的高很多qwq

  完成代码如下:

from mxnet import gluon
from mxnet.gluon import nn
from d2l import mxnet as d2l
from mxnet import autograd, nd
import matplotlib.pyplot as pltnet = nn.Sequential()
with net.name_scope():net.add(nn.Conv2D(channels = 20, kernel_size = 5, activation = 'relu'))net.add(nn.MaxPool2D(pool_size = 2, strides = 2))net.add(nn.Conv2D(channels = 50, kernel_size = 3, activation = 'relu'))net.add(nn.MaxPool2D(pool_size = 2, strides = 2))net.add(nn.Flatten())net.add(nn.Dense(128, activation = 'relu'))net.add(nn.Dense(10))ctx = d2l.try_gpu()                                                                   # 试试gpu能不能跑 如果报错则返回cpu
print("context :", ctx)
net.initialize(ctx = ctx)
print(net)batch_size, num_epoch, lr = 256, 10, 0.5
train_data, test_data = d2l.load_data_fashion_mnist(batch_size)softmax_cross_entropy = gluon.loss.SoftmaxCrossEntropyLoss()
trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate' : lr})def accuracy(output, label):                                                                     # 计算拟合的准确度return nd.mean(output.argmax(axis = 1) == label.astype('float32')).asscalar()                # argmax是把每一列的最大概率的index返回出来 然后和label比较是否相同 最后所有求个meandef evaluate_accuracy(data_itetator, net, context):acc = 0.for data, label in data_itetator:output = net(data)acc += accuracy(output, label)return acc / len(data_itetator)for epoch in range(num_epoch):train_loss, train_acc = 0., 0.for data, label in train_data:label = label.as_in_context(ctx)with autograd.record():out = net(data.as_in_context(ctx))loss = softmax_cross_entropy(out, label)loss.backward()trainer.step(batch_size)train_loss += nd.mean(loss).asscalar()train_acc += accuracy(out, label)# test_acc = 0.test_acc = evaluate_accuracy(test_data, net, ctx)print("Epoch  %d. Loss : %f, Train acc : %f, Test acc : %f" %(epoch, train_loss / len(train_data), train_acc / len(train_data), test_acc))

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux中使用Docker构建Nginx容器完整教程

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️创作…

JD18年秋招笔试疯狂数列python解答

问题如下&#xff1a; 链接&#xff1a;疯狂序列_京东笔试题_牛客网 [编程题]疯狂序列 热度指数&#xff1a;149 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32M&#xff0c;其他语言64M 东东从京京那里了解到有一个无限长的数字序列: 1…

uniapp 做一个查看图片的组件,图片可缩放移动

因为是手机端&#xff0c;所以需要触摸可移动&#xff0c;双指放大缩小。 首先在components里建个组件 查看图片使用 uni-popup 弹窗 要注意 transform的translate和scale属性在同一标签上不会一起生效 移动就根据触摸效果进行偏移图片 缩放就根据双指距离的变大变小进行缩…

DFS算法专题(二)——穷举vs暴搜vs深搜vs回溯vs剪枝【OF决策树】

目录 1、决策树 2、算法实战应用【leetcode】 2.1 题一&#xff1a;全排列 2.2.1 算法原理 2.2.2 算法代码 2.2 题二&#xff1a;子集 2.2.1 算法原理【策略一】 2.2.2 算法代码【策略一】 2.2.3 算法原理【策略二&#xff0c;推荐】 2.2.4 算法代码【策略二&#x…

浅谈基于负荷时空均衡和弹性响应的电动汽车快充电价定价策略

摘要&#xff1a;为了引导电动汽车有序充电&#xff0c;提出了一种考虑负荷时空均衡和弹性响应的电动汽车快充电价定价策略。引入交通流理论描述交通路网&#xff0c;建立电动汽车快充负荷时空分布模型&#xff1b;考虑配电网调度和电动汽车快充负荷的弹性需求&#xff0c;构建…

React Native 0.76,New Architecture 将成为默认模式,全新的 RN 来了

关于 React Native 的 New Architecture 概念&#xff0c;最早应该是从 2018 年 RN 团队决定重写大量底层实现开始&#xff0c;因为那时候 React Native 面临各种结构问题和性能瓶颈&#xff0c;最终迫使 RN 团队开始进行重构。 而从 React Native 0.68 开始&#xff0c;New A…

轻松搞定Arduino开发环境,像玩积木一样简单!

朋友们,有没有人和我一样,曾经对Arduino望而却步?说到“开发环境”这几个字,感觉脑子就要爆炸了,光是想象安装各种软件、调试环境就能把人吓跑。相信我,我也曾有过这样的感觉。但是,当我真正开始玩Arduino后,我发现一切都不像想象中那么复杂!其实,搭建Arduino开发环境…

光耦合器的工作原理和故障诊断

光耦合器&#xff0c;也称为光隔离器&#xff0c;是现代电子设备中必不可少的组件&#xff0c;尤其是在确保系统不同部分之间的电气隔离方面。它们通过使用光传输信号来防止高压或不需要的信号影响敏感组件。在本文中&#xff0c;我们将讨论光耦合器的工作原理、故障诊断和识别…

安泰功率放大器有哪些特点呢

功率放大器是电子设备中的重要组成部分&#xff0c;其作用是将输入信号的电功率放大到足够的水平&#xff0c;以驱动负载&#xff0c;如扬声器或天线。功率放大器有一些独特的特点&#xff0c;这些特点对于各种应用至关重要。下面将详细介绍功率放大器的特点&#xff0c;以更好…

Unity教程(十五)敌人战斗状态的实现

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

前端JS必用工具【js-tool-big-box】学习,获取全球热点城市当前时间、时区以及令时

js-tool-big-box工具库&#xff0c;之前也添加了几个热点城市的当前时间显示&#xff0c;但当时城市较少&#xff0c;功能也比较简单&#xff0c;只是显示了时分秒。 最近有使用者说&#xff0c;光有时分秒&#xff0c;功能太少&#xff0c;所以对js-tool-big-box工具库做了改进…

windows vscode ssh 连接远程服务器

1.在 PowerShell 中运行以下命令&#xff0c;查看 OpenSSH 客户端是否已安装 Get-WindowsCapability -Online | Where-Object Name -like OpenSSH.Client*如果有安装的话&#xff0c;如下图 2.如果没有安装&#xff0c;那么用下面的命令进行安装 Get-WindowsCapability -On…

科研绘图系列:R语言宏基因组PCoA图(PCoA plot)

介绍 PCoA(主坐标分析,也称为主轴分析)是一种多维统计技术,用于分析和可视化高维数据集,如宏基因组数据。在宏基因组学中,PCoA图用于展示样本之间的相似性和差异性,通常基于样本之间的距离或相似度矩阵。PCoA图说明: 样本间关系:PCoA图通过降维技术将高维数据投影到二…

(不用互三)AI绘画工具大比拼:Midjourney VS Stable Diffusion该如何选择?

文章目录 &#x1f4af;如何选择合适的AI绘画工具根据个人需求选择1. 您喜欢什么风格的绘画&#xff1f;2. 您想要创作什么主题的内容&#xff1f;3. 您对绘画工具的使用经验如何&#xff1f; 比较工具特点1. 工具的易用性和功能性如何&#xff1f;易用性&#xff1a;功能性&am…

【机器学习】分类与回归——掌握两大核心算法的区别与应用

【机器学习】分类与回归——掌握两大核心算法的区别与应用 1. 引言 在机器学习中&#xff0c;分类和回归是两大核心算法。它们广泛应用于不同类型的预测问题。分类用于离散的输出&#xff0c;如预测图像中的对象类型&#xff0c;而回归则用于连续输出&#xff0c;如预测房价。…

Linux | 进程控制(上):进程终止(strerror函数、errno宏、_exit() 与 exit())

文章目录 进程控制1、进程终止1.1进程常见退出方法退出码1.1.1 strerror函数 & errno宏1.1.1 _exit函数_exit和exit的区别结合现象分析&#xff1a; 进程控制 1、进程终止 1.1进程常见退出方法 进程退出场景 代码运行完毕&#xff0c;结果正确代码运行完毕&#xff0c;结…

Redis 集群高可用详解及配置

关型数据库 关系型数据库&#xff1a; 是建立在关系模型基础上的数据库&#xff0c;其借助于集合代数等数学概念和方法来处理数据库中的数据 主流的 MySQL、Oracle、MS SQL Server 和 DB2 都属于这类传统数据库 关型数据库的优缺点 特点&#xff1a; 1、数据关系模型基于关系…

学生请假管理系统

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 学生请假管理系统拥有两种角色 管理员&#xff1a;班级管理、课程管理、学生管理、审核请假信息、导出请假单 学生&#xff1a;填写请假单、查看请假审核情况 1.1 背景描述 学生请假管…

音视频入门基础:WAV专题(11)——FFmpeg源码中计算WAV音频文件每个packet的pts_time、dts_time的实现

音视频入门基础&#xff1a;WAV专题系列文章&#xff1a; 音视频入门基础&#xff1a;WAV专题&#xff08;1&#xff09;——使用FFmpeg命令生成WAV音频文件 音视频入门基础&#xff1a;WAV专题&#xff08;2&#xff09;——WAV格式简介 音视频入门基础&#xff1a;WAV专题…

C++速通LeetCode第6题-环形链表

快慢指针真的很好用&#xff01; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Solution { public:bool hasCycle(ListNode *head) {//快慢指针ListNode* fast…