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

news2025/1/10 10:24:29

卷积神经网络

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 nn

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)

  输出出来是这样:

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})          # sgd

def accuracy(output, label):                                                          # 计算拟合的准确度
    return nd.mean(output.argmax(axis = 1) == label.astype('float32')).asscalar()     # argmax是把每一列的最大概率的index返回出来 然后和label比较是否相同 最后所有求个mean

def 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 plt

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)

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比较是否相同 最后所有求个mean

def 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.coloradmin.cn/o/2131712.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序页面制作——婚礼邀请函(含代码)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

windows下ardusub仿真

接上篇&#xff1a;windows编译ardupilot源码教程 执行以下命令。 #在ardusub根目录下执行下面命令 cd ./Tools/autotest./waf configure --debugpython sim_vehicle.py -v ArduCopter -f quad --console --map -D -L RATBeach 编译时间较长&#xff0c;之后会打开三个窗口。 …

SpringBoot 整合酷狗获取下载音乐(需要自己账户)

程序员必备宝典https://tmxkj.top/#/ 在此声明,本内容仅供个人学习、研究或娱乐之用,严禁任何形式的商业用途。若您发现本内容被用于商业目的,请立即与我们联系,我们将删除原代码。 我们尊重并保护所有原创作品的知识产权。 为了营造一个健康、积极的网络环境,我们鼓励用户…

故障诊断迁移学习项目DDC(保姆教程)

本项目从零开始搭建深度领域混淆&#xff08;Deep Domain Confusion&#xff0c;DDC&#xff09;算法。项目包括加载CWRU轴承原始信号&#xff0c;信号处理、数据集制作&#xff0c;模型搭建&#xff0c;DDC域混淆算法设计、特征可视化&#xff0c;混淆矩阵等流程来帮助读者学习…

Qt_了解Qt Creator

目录 1、使用Qt Creator新建项目 1.1 新建项目 1.2 选择项目模板 1.3 选择项目路径 1.4 选择构建系统 1.5 填写类信息 1.6 选择语言翻译文件 1.7 选择编译器 1.8 选择版本控件系统 1.9 最终效果 2、代码解析 2.1 main.cpp 2.2 widget.h 2.3 widget.cpp …

[SDK] -模态对话框 和 非模态对话框

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解对话框的相关知识点&#xff0c;就此SDK学习告一段落&#xff0c;之后会更新相关项目内容 创建对话框 项目->添加 ->资源->Dialog->修改对话框ID->拖拉尺寸设置对话框大小 通过菜单绑定…

多通道电源测试设备怎么测试多路电源?

为了提升多路电源模块的测试效率和精度&#xff0c;NSAT-8000多通道ATE自动化测试设备持续迭代创新&#xff0c;旨在精准检测电源每个通道的性能指标&#xff0c;判断电源质量是否合格。 一、测试系统结构 二、测试设备 常用的测试电源的仪器主要有示波器、数字万用表、电子负载…

Android app广告变现广告预算来源有哪些?

APP开发者想要通过广告变现实现收益的最大化&#xff0c;首先要了解广告预算来源有哪些&#xff1f; 1、Push 推送广告 通过推送消息到用户设备通知栏上展示广告。 2、第三方 SDK 广告 很多应用都会集成第三方广告平台&#xff0c;比如 AdMob、Facebook Audience Network、…

ESP32-S3百度文心一言大模型AI语音聊天助手(支持自定义唤醒词训练)【手把手非常详细】【万字教程】

简介 此项目主要使用ESP32-S3实现一个AI语音聊天助手&#xff0c;可以通过该项目熟悉ESP32-S3 arduino的开发&#xff0c;百度语音识别&#xff0c;语音合成API调用&#xff0c;百度文心一言大模型API的调用方法&#xff0c;音频的录制及播放&#xff0c;SD卡的读写&#xff0c…

SAP自建表log功能开启

1、SE11下进入“技术设置”&#xff0c;勾选“日志更改” 2、RZ10修改系统参数 rec/clientALL, 或rec/client000&#xff08;客户端号&#xff0c;多个客户端使用“&#xff0c;”分割。激活参数文件 没有这个参数的话新增一个 修改了SAP系统参数文件DEFAULT.PFL需要重启SAP…

【ESP-IDF FreeRTOS】软件定时器

除了ESP-IDF中的软硬件定时器&#xff0c;我们还可以使用FreeRTOS中的软件定时器&#xff0c;它是基于Tick的定时器。不过我一般不用&#xff0c;因为有ESP-IDF的定时器了嘛&#xff0c;但还是介绍一下。 首先包含头文件。 #include "freertos/timers.h" 接着我们…

N2011A叉车限速器如何实现超速报警且强制限速的

叉车安装限速器是对厂区叉车控制行驶速度常见的一种方式&#xff0c;但限速器真的能限速吗&#xff1f; 九盾N2011A叉车限速器是采取无线传感器的方式&#xff0c;相比传统的限速器&#xff0c;需要前桥打孔攻牙&#xff0c;稍有不慎就打断&#xff0c;安装麻烦耗工时&#xf…

2024年提升转化率的10个最佳弹窗软件解决方案

无论你是喜欢还是讨厌它们&#xff0c;弹窗通知并不一定都是坏的。当然&#xff0c;大多数网站访问者并不愿意被横幅打扰&#xff08;更糟糕的是那种自动播放音频的视频&#xff09;。不过&#xff0c;你有没有想过只在他们快要离开你的网站时才显示弹窗&#xff1f;使用退出意…

FP7127 / FP7128:LED舞台灯降压方案 RGB调光 智能调光模块

前言&#xff1a; 舞台灯作为一种应用于文化娱乐场所的灯具&#xff0c;用来营造环境、渲染氛围&#xff0c;在舞台上突出中心人物、塑造演员形象&#xff0c;在文化场馆&#xff0c;如博物馆等的场所&#xff0c;突出展品细节。根据灯光用途和适用类型&#xff0c;舞台灯可以…

【F的领地】项目拆解:百家号批量搬运掘金 | 搬运类项目核心思路分享

【F的领地】项目拆解&#xff1a;百家号批量搬运掘金 项目介绍 百家号批量搬运掘金是之前老百家号项目的一种新玩法&#xff0c;操作简单。 只需会操作电脑和手机即可&#xff0c;无脑搬运就行&#xff0c;玩法是批量搬运视频&#xff0c;用软件去重后在百家号发布。 然后是…

Miracast/WifiDisplay开发相关的深入调研分析-android投屏实战开发

Miracast/WifiDisplay概念介绍 Miracast Miracast是由Wi-Fi联盟于2012年所制定&#xff0c;以Wi-Fi直连&#xff08;Wi-Fi Direct&#xff09;为基础的无线显示标准。支持此标准的消费性电子产品&#xff08;又称3C设备&#xff09;可透过无线方式分享视频画面&#xff0c;例如…

Linux和C语言(Day09)

一、学习内容 指针 指针的概念 什么是内存 内存是计算必不可少的硬件设备&#xff0c;一般说到内存常会说TA多大——M、G、T 内存单位&#xff1a;bit【位&#xff0c;最小单位】 Byte【字节&#xff0c;基本单位】 KB MB GB TB CPU如何从内存取数据 通过内存地址去取 将内存…

全球主流单片机制造商

欧美地区 1、FreescaleNXP&#xff08;飞思卡尔恩智浦&#xff09;&#xff1a;荷兰&#xff0c;主要提供16位、32位MCU。应用范围&#xff1a;汽车电子、LED和普通照明、医疗保健、多媒体融合、家电和电动工具、楼宇自动化技术电机控制、电源和功率转换器、能源和智能电网、自…

数据资产入表(二)|数据要素资产化与数据资产入表路线框架,一文说清“入表”实现步骤

前言 小兵的数据资产入表系列文章第一篇为大家介绍了国内外关于“数据要素市场化”的探索现状以及推进“数据资产入表”的相关政策。想必大家读完第一篇后&#xff0c;已经认识到数据要素市场化是大势所趋&#xff0c;但是数据的特殊性使得其市场化之路比其他生产要素要更加复杂…

Vue3+Django5+REST Framework开发电脑管理系统

前端&#xff1a;Vue3TypeScript 后端&#xff1a;Django5REST Framework 功能介绍 用户管理角色管理菜单管理配件管理仓库管理类型管理电脑管理入库管理出库管理库存管理收发明细管理 界面预览 源码地址&#xff1a;managesystem: 电脑管理系统