深度学习架构-Tensorflow

news2024/12/23 17:18:27

深度学习基本概念

  1. 人工智能是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能的目的 就是让计算机能够像人一样思考。
    强人工智能:就是要使机器学习人的理解、学习和执行任务的能力。
    弱人工智能:指用于自动化特定任务的软件。
  2. 机器学习的广义概念:是指从已知数据中获得规律,并利用规律对未知数据进行预测的方法。机器学习是一种统计学习方法,机器人和计算机等机器需要使用大量数据进行学习,从而提取出所需的信息。
  3. 深度学习 就是一种利用深度人工神经网络来进行自动分类、预测和学习的技术。
  4. 人工智能>机器学习>深度学习
    在这里插入图片描述

TensorFlow

TensorFlow 是一款用于数值计算的强大的开源软件库,特别适用于大规模机器学习的微调。

  1. MNIST数据读取、建模、编译、训练、测试
import tensorflow as tf
# 载入数据
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
# 建模
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)), # 将输入“压平”,即把多维的输入一维化,只有第一层有输入数据的形状
  tf.keras.layers.Dense(128, activation='relu'), # 该层的输出维度或神经元个数和激活函数
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])
# 编译(优化器、损失和评价)
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
# 训练(训练和验证数据不一样)
model.fit(x_train, y_train, epochs=5)
#  验证
model.evaluate(x_test, y_test, verbose=2)

  1. 优化器 tf.optimizers;
    SGD 随机梯度下降优化器
tf.keras.optimizers.SGD( learning_rate=0.01, momentum=0.0,nesterov=False, name='SGD', **kwargs)
学习率、动量、是否使用nesterov震荡

Adam优化器
tf.keras.optimizers.Adam(learning_rate=0.001)

  1. 损失函数:均方根误差MSE(MeanSquaredError)、二值交叉熵(BinaryCrossentropy);
    metrics sparse_categorical_crossentropy(多分类损失函数)
  2. metrics评价函数
    “accuracy” :真实值(y_)和预测值(y) 都是数值;
    “sparse_accuracy”:y_和y都是以独热码和概率分布表示;
    “sparse_categorical_accuracy”:y_是以数值形式给出,y是以独热码给出
  3. 数据结构
    1)Rank:维度
    2)Shape:每个维度数据的个数
    3)Data type:bool、int、float、string、complex、Truncated float、Quantized int
    4)Variables与Constant : 变量和常数

常用函数

  • 数据类型转换

在这里插入图片描述

import tensorflow as tf
import tensorflow.compat.v1 as tf1
string = '12.3'
n1 = tf1.string_to_number(string, out_type=None, name=None)  #字符串转为数字
x = 12.3
d1 = tf1.to_double(x, name='ToDouble')#转为64位浮点类型float64
f1 = tf1.to_float(x, name='ToFloat') #转为32位浮点类型float32
i1 = tf1.to_int32(x, name='ToInt32') #转为32位整型int32
i2 = tf1.to_int64(x, name='ToInt64')     #转为64位整型–int64
a = [1.8, 2.2]
i3 = tf.cast(a, tf.int32)  # 将a或者a.values转换为dtype
  • 形状操作
t = [ [[1, 1, 1], [2, 2, 2]] ,  [[3, 3, 3], [4, 4, 4]] ]
tf.shape(t)    #返回维度中数据的个数
tf.size(t)      #返回数据的元素数量
tf.rank(t)      #返回数据维度
t = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(tf.shape(t))
t2 = tf.reshape(t, [3, 3])  #改变tensor的形状
print(tf.shape(t2))
t3 = tf.reshape(t, [3, -1])
print(t3)

在这里插入图片描述

  • 其它操作函数
t = [2,3] #插⼊维度1进⼊⼀个tensor中
t1 = tf.shape(tf.expand_dims(t, 0)) [1,2]
t2 = tf.shape(tf.expand_dims(t, 1))  [2,1]
t3 = tf.shape(tf.expand_dims(t, -1)) [2,1]
t4 = tf.ones([2,3,5])   #用数字1填充所有维度
t6 = tf.shape(tf.expand_dims(t4, 2))  shape=2315】
t= [[[1, 1, 1], [2, 2, 2]],[[3, 3, 3], [4, 4, 4]],[[5, 5, 5], [6, 6, 6]]]
#对tensor进⾏切⽚操作
t1 = tf.slice(t, [1, 0, 0], [1, 1, 3])  
t2 = tf.slice(t, [1, 0, 0], [1, 2, 3])
t3 = tf.slice(t, [1, 0, 0], [2, 1, 3])

t = tf.ones([5,30]) 
t1, t2, t3 = tf.split(t,3,1)  #沿着某⼀维度将tensor分离
print(tf.shape(t1))
print(tf.shape(t2))
print(tf.shape(t3))

t1 = [[1, 2, 3], [4, 5, 6]]
t2 = [[7, 8, 9], [10, 11, 12]] 
t3 = tf.concat([t1, t2], 0)  #沿着某⼀维度连结tensor
t4 = tf.concat([t1, t2], 1)

x = [1, 4] y = [2, 5] z = [3, 6]
t1 =tf.stack([x, y, z]) #沿着第⼀维stack [[1 4] [2 5] [3 6]]
t2 = tf.stack([x, y, z], axis=1) #axis取0时表示按x轴叠加,取1时表示按y轴叠加#[[1 2 3] [4 5 6]]

t = [[  [[ 0, 1, 2, 3],[ 4, 5, 6, 7],[ 8, 9, 10, 11]], 
 [[12, 13, 14, 15],[16, 17, 18, 19],[20, 21, 22, 23]]  ]] # shape=(1,2,3,4),dims = [3]
t1 = tf.reverse(t, dims) #沿着某维度进⾏序列反转dims = [1] 
t2 = tf.reverse(t, dims) #dims = [2] 
t3 = tf.reverse(t, dims) [[  [[ 8 9 10 11] [ 4 5 6 7] [ 0 1 2 3]]  [[20 21 22 23] [16 17 18 19] [12 13 14 15]] ]]

t = [[1, 2, 3],[4, 5, 6]]
t1 = tf.transpose(t)  #调换tensor的维度顺序	
t2 = tf.transpose(t, perm=[1, 0])  # [[1 4] [2 5] [3 6]]

indices = [0, 1, 2]  depth = 3
t1 = tf.one_hot(indices, depth)  #
indices = [0, 2, -1, 1]   depth = 3
t2 = tf.one_hot(indices, depth,on_value=5.0, off_value=0.0,axis=-1) 
indices = [[0, 2], [1, -1]]  depth = 3
t3 = tf.one_hot(indices, depth,on_value=1.0, off_value=0.0,axis=-1) #    [ [[1. 0. 0.][0. 0. 1.]]
[[0. 1. 0.][0. 0. 0.]] ]
t = [1, 1, 2, 4, 4, 4, 7, 8, 8]
y, idx = tf.unique(t)  
print(y) #t的所有唯一元素
print(idx) #y中每个值的索引

tf.math.ceil([-1.7,-1.5,-0.2,0.2,1.5,1.7,2.0])  #向上取整函数
tf.gather(params,indices,axis=0 ) 从params的axis维根据indices的参数值获取切片
  • 运算
tf.diag(diagonal) 根据主对角线元素生成矩阵
tf.trace(x, name=None)求二维tensor对角值之和
tf.matrix_determinant(input, name=None)求方阵行列式
tf.matrix_inverse(input, adjoint=None,name=None)求逆矩阵
tf.matmul(a,b,transpose_a=False,transpose_b=False,a_is_sparse=False,b_is_sparse=False,name=None)矩阵相乘
tf.complex(real, imag, name=None) 将两实数转换为复数形式
tf.complex_abs(x, name=None) 计算复数的绝对值,即⻓度。
tf.conj(input, name=None) 计算共轭复数
tf.imag(input, name=None)
tf.real(input, name=None)
tf.eye(num_rows,num_columns=None)生成单位阵
tf.fill(dims,value,name=None)   fill([2, 3], 9) ==> [[9, 9, 9][9, 9, 9]]
tf.ones(shape,dtype=tf.dtypes.float32,name=None)

  • 数据生成
⽣成随机张量
tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None)
从“服从指定正态分布的序列”中随机取出指定个数的值,shape: 输出张量的形状,mean: 正态分布的均值,stddev: 正态分布的标准差,dtype: 输出的类型,seed: 随机数种子,是一个整数,当设置之后,每次生成的随机数都一样

tf.truncated_normal(shape, mean, stddev)
产生截断正态分布随机数,取值范围为 [ mean - 2 * stddev, mean + 2 * stddev ]

tf.random_uniform(shape,minval=0, maxval=None, dtype=tf.float32, seed=None)
生成的值在 [minval, maxval) 范围内遵循均匀分布.

tf.random_shuffle()  随机地将张量沿其第一维度打乱

变量:
biases = tf.Variable(tf.zeros([200]),name=“var") 生成一组变量(没有初始化)
const = tf.constant(1.0,name="constant") 创建常量

名称作用域
在TensorFlow 应用程序中,可能会有数以千计的计算节点。如此多节点汇集在一起,难以分析,甚至无法用标准的图表工具来展示。为解决这个问题,一个有效方法就是,为Op/Tensor 划定名称范围。在TensorFlow 中,这个机制叫名称作用域(name scope)

tf.variable_scope() 管理变量命名空间,可以创建同名变量。在tf.variable_scope 中创建的变量,名称. name 中名称前面会加入命名空间的名称,并通过“/” 来分隔命名空间名和变量名。

tf.get_variable(name="foo/bar", shape=[1]) ,可以通过带命名空间名称的变量名来获取其命名空间下的变量。如果变量存在,则使用以前创建的变量,如果不存在,则新创建一个变量。不能创建同名变量。

Pytorch

概念:Pytorch是一个基于python的科学计算包,主要用途为,

  1. 作为Numpy的替代品,可以利用GPU的性能进行高效计算
  2. 作为高灵活性,速度快的深度学习平台
测试:
torch.cuda.is_available()
x = torch.rand(5,3) print(x)
print(x)

基本元素: 张量(Tensor)、变量(Variable)、神经网络模块(nn.Module)

  • 张量(Tensor):张量是PyTorch中最基本的元素,相当于numpy.ndarray。Tensor是PyTorch中numpy.ndarray的替代品。
  • 变量(Variable):搭建神经⽹络时,需要variable来构建计算图。
  • Variable是对tensor的封装,是⼀个存放会变化的值(tensor)的物理位置。
  • variable有3个属性:
    • variable.data: variable中tensor的值
    • variable.grad: variable中tensor的梯度;
    • variable.gradfn: 指向Function对象,⽤于反向传播的梯度计算之⽤

nn.Module

神经⽹络模块nn.Module:神经⽹络的接⼝。定义⾃⼰的神经⽹络时,需继承 nn.Module类

  • (1) Liner模块

torch.nn.Linear(in_features, out_features, bias=True)
⽹络中的全连接层,全连接层输⼊与输出都是⼆维张量,输⼊形状为[batch_size, size]。
in_features:指的是输入的二维张量的大小。
out_features:指的是输出的二维张量的大小,即输出的二维张量的形状为[batch_size,output_size],也代表该全连接层的神经元个数。

  • (2) Conv2d模块

torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
kernel_size:卷积核的⼤⼩,⽤(H,W)表示HxW的输出,H表示H*H⼤⼩的输出。
stride:卷积步幅,卷积核每次挪动间距
padding:填充操作,控制padding_mode的数⽬。默认为Zero-padding。
dilation:扩张操作,控制kernel点(卷积核点)的间距,默认为1。
group:控制分组卷积,默认不分组。 (对输入feature map进行分组,然后每组分别卷积。)
bias:是否添加偏置,如为真,则在输出中添加⼀个可学习的偏差,默认为True。

在这里插入图片描述

  • Linear和Conv2d连接,Conv2d的输出为四维张量,转换为⼆维张量之后,才能作为全连接层的输⼊

在这里插入图片描述

  • (3)⼆维批量归⼀化模块

torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True)
num_features:特征数C

在这里插入图片描述

  • (4)最⼤池化模块

torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1)
输⼊: (N,C,H_in,W_in)
输出: (N,C,H_out,W_out)

在这里插入图片描述

  • (5)平均池化模块:

torch.nn.AvgPool2d(kernel_size, stride=None, padding=0, ceil_mode=False)
ceil_mode:如果为True,则在计算输出形状时使⽤ceil函数替代floor

在这里插入图片描述

  • (6)⾃适应平均池化模块:

torch.nn.AdaptiveAvgPool2d(output_size) output_size: 输出信号的尺⼨
Adaptive Pooling特殊性在于输出张量的⼤⼩是给定的output_size。对于任何输⼊⼤⼩的输⼊,可以将输出尺⼨指定为H*W,但是输⼊和输出特征的数⽬不会变化。
在这里插入图片描述

nn.function

  1. 位置:torch.nn.functional
    例:torch.nn.functional.adaptive_avg_pool2d(input, output_size)
  2. torch.nn.ReLU(inplace=False) inplace:选择是否进⾏原位运算,即x = x+1
  3. Sigmoid:
m = nn.Sigmoid() 
input = torch.randn(2) 
output = m(input) 
input, output 
(tensor([-0.8425, 0.7383]), tensor([0.3010, 0.6766]))

4.Tanh:

m = nn.Tanh() 
input = torch.randn(2) 
output = m(input) 
input, output 
(tensor([1.3372, 0.6170]), tensor([0.8710, 0.5490])) 

RNN

函数:torch.nn.RNN(input_size, hidden_size, num_layers)

  • hidden_size:隐含层神经元个数,也是输出的维度,因为rnn输出为各时间步上的隐藏状态;
  • num_layers:隐含层的层数;

RNN的输出包含两部分:输出值Y(即output)和 最后⼀个时刻隐含层的输出 h n h_n hn

前向预测:
在这里插入图片描述

  • x:[seq_len, batch, feature_len],是⼀次性将所有时刻特征输⼊的,不需要每次输⼊当前时刻的xt;
  • h0是第⼀个初始时刻所有层的记忆单元的Tensor(理解成每⼀层中每个句⼦的隐藏输出);

例:输⼊⼀段中⽂,输出⼀段英⽂。每个中⽂字符⽤100维数据进⾏编码,每个隐含层的维度是20,有4个隐含层。所以input_size = 100,hidden_size = 20,num_layers = 4。设模型已经训练好了,现在有个1个⻓度为10的句⼦做输⼊,那seq_len = 10, batch_size = 1。


import torch 
import torch.nn as nn 
input_size = 100 # 输⼊数据编码的维度 
hidden_size = 20 # 隐含层维度 
num_layers = 4 # 隐含层层数 
rnn = nn.RNN(input_size=input_size,hidden_size=hidden_size,num_layers=num_layers) 
print("rnn:",rnn)
seq_len = 10 # 句⼦⻓度 
batch_size = 1 

x = torch.randn(seq_len,batch_size,input_size) # 输⼊数据x 
h0 = torch.zeros(num_layers,batch_size,hidden_size) # 输⼊数据h0 

out, h = rnn(x, h0) # 输出数据 

print("out.shape:",out.shape) 
print("h.shape:",h.shape)
  • RNNCell模块:
    (1)区别:nn.RNN是⼀次性将所有时刻特征输⼊⽹络的。nn.RNNCell将序列上的‘每个时刻的数据’分开来处理
    (2)前向预测: h t = f o r w a r d ( x t , h t − 1 ) h_t = forward(x_t, h_{t-1}) ht=forward(xt,ht1)

例如:如果要处理3个句⼦,每个句⼦10个单词,每个单词⽤100维的嵌⼊向量表示
nn.RNN传⼊的Tensor的shape是[10,3,100]
nn.RNNCell传⼊的Tensor的shape是[3,100],将此计算单元运⾏10次

  • LSTM模块
    • 函数:torch.nn.LSTM(input_size, hidden_size, num_layers)
    • 输⼊及输出格式:out, (h_t, c_t) = lstm(x, [h_t0, c_t0])
    • LSTMCell模块: h_t, c_t = lstmcell(x_t, [h_t-1, c_t-1])
      • xt:[batch, feature_len]表示t时刻的输⼊
      • ht−1,ct−1:[batch, hidden_len],t−1时刻本层的隐藏单元和记忆单元)

nn.LSTM是⼀次性将所有时刻特征输⼊⽹络的。
nn.LSTMCell将序列上的‘每个时刻的数据’分开来处理


CNN

  • 前馈型神经网络的学习主要采用误差修正法(如BP算法),计算过程比较慢,收敛速度也较慢;
  • 而反馈型神经网络主要采用Hebb学习规则,计算收敛速度很快。

CNN使用部分连接层,三个思想为局部性、相同性、不变性

卷积层

  • 第一层神经元只连接输入图像中位于他感知区域中的像素 专注图像的低级特征
  • 第二层神经元仅连接到位于第一层中感知区域内的神经元 高级特征

过滤器(Filters、卷积核) 卷积操作 设定参数
1)滤波器的长宽高 HWC
2)步长(Stride)
3)边界填充

在这里插入图片描述在这里插入图片描述

注:经过滤器处理后的图像称为特征图,特征图中所有神经元共享相同参数(权重、偏差顷)

基本结构(输入层+卷积层(提取特征)+池化层(压缩特征)+ 全连接层(非线性输出))

  • 输⼊图像的表示:3D张量 [⾼度,宽度,通道];
  • ⼩批量表示:4D张量 [⼩批量,⾼度,宽度,通道];

卷积层的权重表示:4D张量 [ fh,fw,fn,fn′]

  • fh为当前层过滤器高度 ;fw为当前层过滤器宽度;fn为当前层过滤器数量 ;fn’为上一层特征图数量

卷积层的偏置项表示:1D张量 [fn]

计算:一个具有5×5过滤器的卷积层,输出尺寸为150×100的200个特征图,带有步幅1和SAME填充。

参数数量:若输入是150×100 RGB图像(三通道),则参数的数量:(5×5×3+1*200=15,200

200个特征图每一个都包含150×100个神经元,每个都需要计算其5×5×3=75个输入的加权和,总共有75*150*100*200=2.25亿次浮点乘法。

若用32位浮点数表示特征图,卷积层输出将占200×150×100×32=96百万位(约11.4 MB)内存

关于padding

写代码时,要注意,padding有两个模式,分别是 ‘same’ 和 ‘valid’ ,

padding='same'表示进行填充,填充的值由算法内部根据卷积核大小计算,目的是让输出尺寸和输入相等;
padding='valid'表示不进行填充,即是 padding=0,只使用有效的窗口位置,这是默认的选项。

  • 填充的值= (b - 1) / 2
    填充的值,b的值就是卷积核的尺寸,这里就是为什么卷积核尺寸通常选择奇数的原因

举例子:
问题1. 一个尺寸 55 的特征图,经过 33 的卷积层,步幅(stride)=1,想要输出尺寸和输入尺寸相等,填充(padding)的值应该等于多少?
答:填充的值=(3 - 1)/2 = 1,即每一边填充1层

问题2. 一个尺寸 224224 的特征图,经过 77 的卷积层,步幅(stride)=2,想要输出尺寸和输入尺寸相等,填充(padding)的值应该等于多少?
答:填充的值=(7 - 1)/2 = 3,即每一边填充3层

  • padding='same’目的是让输出尺寸和输入尺寸相等,但前提是步幅=1,步幅若不是1,那么输出尺寸跟输入尺寸肯定是不一样。

对于 padding 的 same 和 valid 模式两种直白的理解就是要么不填充,要么填充就让输出尺寸和输入尺寸相等
padding 的值不会乱取,就两种情况,要么padding=0 要么padding=(b - 1)/2。


池化层:

1)⽬标:对输⼊图像进⾏⼆次采样(即缩⼩),以减少计算量、内存占⽤和参数数量(减少过拟合⻛险)
2)特点:池化层中的每个神经元都和前⼀层神经元的输出相连,位于⼀个⼩的矩形感受区内。但池化神经元没有权重,它⽤聚合函数(如max_pool()或avg_pool())聚合输⼊。
3)作用:特征降维,避免过拟合;空间不变性;减少参数,降低训练难度

4)代码实现⼀个2x2内核的池化层(keras实现)

keras.layers.MaxPool2D( pool_size=(2,2),  strides=None, #默认值和pool_size相等
padding='valid', data_format=None)

keras.layers.AvgPool2D(pool_size=(2,2),strides= None, # 默认值和pool_size相等
padding='valid', data_format=None)

keras.layers.GlobalAveragePooling2D(data_format=None)

  • 设计一个对MNIST处理的CNN网络,结构和参数如下,每次MaxPooling后添加系数为0.25的Dropout.

在这里插入图片描述

import os
import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Flatten, Conv2D, 
import numpy as np

(X_tarin, y_train), (X_test, y_test) = mnist.load_data()
X_train4D = X_tarin.reshape(X_tarin.shape[0], 28, 28, 1).astype('float32')
X_test4D = X_test.reshape(X_test.shape[0], 28, 28, 1).astype('float32')

 # 归⼀化
X_train4D_Normalize = X_train4D / 255
X_test4D_Normalize = X_test4D / 255
# 标签onehot编码
y_trainOnehot = to_categorical(y_train)
y_testOnehot = to_categorical(y_test)

# 建⽴模型
model = Sequential()
model.add(Conv2D(filters=16,kernel_size=(5, 5),padding='SAME', input_shape=(28, 28, 1),activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

# ⼆层卷积
model.add(Conv2D(filters=32,kernel_size=(5, 5), padding='SAME', activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

#三、四层卷积
model.add(Conv2D(filters=64, kernel_size=(5, 5), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(filters=128, kernel_size=(5, 5), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25)) 
# 全连接层
model.add(Flatten()) 
model.add(Dense(128, activation='relu')) 
model.add(Dropout(0.25)) 

model.add(Dense(10, activation='softmax')) 
model.summary()
# 编译模型
model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])
#训练模型
train_history = model.fit(x=X_train4D_Normalize,y=y_trainOnehot,validation_split=0.2,batch_size=300,
 epochs=10,verbose=2)
#评估模型
model.evaluate(X_test4D_Normalize, y_testOnehot)[1] 
#预测
prediction = model.predict_classes(X_test4D_Normalize)

RNN

概念:⼀类⽤于处理序列数据的神经⽹络,⼀个序列当前的输出与前⾯的输出有关。具体的表现形式为:⽹络会对前⾯的信息进⾏记忆并应⽤于当前输出的计算中,即隐藏层之间的节点是有连接的,并且隐藏层的输⼊不仅包括输⼊层的输出还包括上⼀时刻隐藏层的输出。


结构
在这里插入图片描述

参数3组权重:

  • U(输⼊x和节点间的计算)
  • W(节点随时间转换计算)
  • V:(节点x和输出节点间计算)
  • St为时刻t隐层的状态 s t = f ( U x t + W s t − 1 ) s_t = f(U_{x_t} + W_{s_t−1}) st=f(Uxt+Wst1)

激励函数 :⼀般为tanh或ReLU
o t o_t ot为时刻t的输出。 o t = s o f t m a x ( V s t ) o_t = softmax(V_{s_t}) ot=softmax(Vst)


分类:

  • 按输⼊和输出序列的结构:One to One、One to Many(向量到序列)、Many to One(序列到向量)、Many to Many 、Encoder-Decoder模型(Seq2Seq模型)
  • 按内部结构:传统RNN、LSTM、Bi-LSTM、GRU、Bi-GRU

简单RNN缺点:在预测⻓序列上表现不佳,⾯临不稳定梯度问题,易发生梯度消失或爆炸;且当 RNN 处理⻓序列时,会逐渐忘掉序列的第⼀个输⼊

  • 简易RNN
np.random.seed(42)
tf.random.set_seed(42)

model = keras.models.Sequential([
keras.layers.SimpleRNN(1, input_shape=[None, 1]) ])

optimizer = keras.optimizers.Adam(learning_rate=0.005)

model.compile(loss="mse", optimizer=optimizer)
history = model.fit(X_train, y_train, epochs=20,validation_data=(X_valid, y_valid))

model.evaluate(X_valid, y_valid)
y_pred = model.predict(X_valid)
  • 深度RNN
np.random.seed(42)
tf.random.set_seed(42)
model = keras.models.Sequential([
 keras.layers.SimpleRNN(20, return_sequences=True,input_shape=[None, 1]),
 keras.layers.SimpleRNN(20, return_sequences=True),
 keras.layers.SimpleRNN(1)
])
model.compile(loss="mse", optimizer="adam")
history = model.fit(X_train, y_train, epochs=20,validation_data=(X_valid, y_valid))
model.evaluate(X_valid, y_valid)
y_pred = model.predict(X_valid)
np.random.seed(42)
tf.random.set_seed(42)

model = keras.models.Sequential([
keras.layers.SimpleRNN(20, return_sequences=True, input_shape=[None, 1])
keras.layers.BatchNormalization(),
keras.layers.SimpleRNN(20, return_sequences=True),
keras.layers.BatchNormalization(), 批量归一化
keras.layers.TimeDistributed(keras.layers.Dense(10)) 时间步
每⼀步都预测10个值,即在时刻0会预测110,时刻1预测211.
])
model.summary()
model.compile(loss="mse", optimizer="adam", metrics=[last_time_step_mse])
history = model.fit(X_train, Y_train, epochs=20, validation_data=(X_valid, Y_valid))
model.evaluate(X_valid, Y_valid)

LSTM

在这里插入图片描述

  • LSTM 单元的状态:h[t](短期记忆状态),c[t](⻓期记忆状态)

c[t−1]先经遗忘⻔丢弃⼀些记忆;后经添加操作增加⼀些记忆(从输⼊⻔中选
择⼀些),最后不经转换直接输出。添加操作之后,⻓时状态复制后经tanh 激活函数,后结果被输出⻔过滤得到短时状态h[t]。h[t]即为这⼀时间步的单元输出y[t]。

短期记忆状态 h [ t − 1 ] h[t−1] h[t1]和输⼊向量 x [ t ] x[t] x[t]经4个不同的全连接层: g [ t ] g[t] g[t]层为主要层(将最重要的部分保存在⻓期状态中,tanh为激活函数),其它三个全连接层(FC)是⻔控制器(Logistic作为激活函数)

权重计算
W x i , W x f , W x o , W x g W_{xi},W_{xf} ,W_{xo},W_{xg} WxiWxfWxoWxg是四个全连接层连接输⼊向量x(t)的权重;
W h i , W h f , W h o , W h g W_{hi},W_{hf} ,W_{ho},W_{hg} WhiWhfWhoWhg是四个全连接层连接h(t−1)的权重;
b i , b f , b o , b g b_i,b_f ,b_o,b_g bibfbobg是全连接层的四个偏置项。

在这里插入图片描述
W x i , W x f , W x o , W x g W_{xi},W_{xf} ,W_{xo},W_{xg} WxiWxfWxoWxg 权重数量:
输入参数数量×隐层参数数量+隐层参数数量 ×隐层参数数量
偏置数量:隐层参数数量

np.random.seed(42)
tf.random.set_seed(42)
model = keras.models.Sequential([
keras.layers.LSTM(20, return_sequences=True, input_shape=[None, 1]),
keras.layers.LSTM(20, return_sequences=True),
keras.layers.TimeDistributed(keras.layers.Dense(10))
])

model.summary()
model.compile(loss="mse", optimizer="adam", metrics=[last_time_step_mse])
history = model.fit(X_train, Y_train, epochs=20, validation_data=(X_valid, Y_valid))
model.evaluate(X_valid, Y_valid)

GRU

在这里插入图片描述
⻓时状态和短时状态合并为⼀个向量h(t)。⽤⼀个⻔控制器z(t)(重置门)控制遗忘⻔和输⼊⻔

  • (若⻔控制器输出1,则遗忘⻔打开(= 1),输⼊⻔关闭(1 - 1 = 0)。
  • 若输出0,则做相反操作)取消输出⻔,每个时间步输出全态向量。

增加⼀个控制门r(t)(更新门)来控制前⼀状态的哪些部分呈现给主层g(t)

在这里插入图片描述

  • 注:尽管它们相⽐于简单RNN可处理更⻓的序列了,还是有⼀定程度的短时记忆

应对⽅法之⼀是将输⼊序列缩短,例如使⽤ 1D 卷积层。1D 卷积层在序列上滑动⼏个核,每个核可以产⽣⼀个 1D 特征映射。 每个核能学到⼀个⾮常短序列模式(不会超过核的⼤⼩)

np.random.seed(42)
tf.random.set_seed(42)

model = keras.models.Sequential([
keras.layers.GRU(20, return_sequences=True, input_shape=[None, 1]),
keras.layers.GRU(20, return_sequences=True),
keras.layers.TimeDistributed(keras.layers.Dense(10))
])
model.summary()
model.compile(loss="mse", optimizer="adam", metrics=[last_time_step_mse])
history = model.fit(X_train, Y_train, epochs=20, validation_data=(X_valid, Y_valid))
  • 实现RNN对数据集MNIST的分类任务
import torch
import torch.nn as nn
import torchvision.datasets as ds
import torchvision.transforms as transforms
from torch.autograd import Variable

sequence_length = 28 , input_size = 28 ,  hidden_size = 128 
num_layers = 2, num_classes = 10 ,  batch_size = 100  ,  num_epochs = 2      
learning_rate = 0.003

#加载MNIST数据集
train_dataset = ds.MNIST(root='.\data',train=True,transform=transforms.ToTensor(),download=True)
test_dataset = ds.MNIST(root='.\data',train=False,transform=transforms.ToTensor())
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,batch_size=batch_size,shuffle=False)

#定义多对⼀双向RNN模型
class BiRNN(nn.Module):
   def __init__(self, input_size, hidden_size, num_layers, num_classes):
      super(BiRNN, self).__init__()
      self.hidden_size = hidden_size
      self.num_layers = num_layers
      self.lstm = nn.LSTM(input_size, hidden_size, num_layers,
      batch_first=True, bidirectional=True)
      self.fc = nn.Linear(hidden_size * 2, num_classes) 
      
   def forward(self, x):
      h0 = Variable(torch.zeros(self.num_layers * 2, x.size(0),self.hidden_size)) # 设置初始状态
      c0 = Variable(torch.zeros(self.num_layers * 2, x.size(0),self.hidden_size)) 
      out, _ = self.lstm(x, (h0, c0)) #前向传播
      out = self.fc(out[:, -1, :]) # 上一时间步隐藏状态输出
      return out

#定义模型
rnn = BiRNN(input_size, hidden_size, num_layers, num_classes)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(rnn.parameters(), lr=learning_rate)

#训练模型
for epoch in range(num_epochs):
   for i, (images, labels) in enumerate(train_loader):
     images = Variable(images.view(-1, sequence_length, input_size)) 
     labels = Variable(labels) 
     optimizer.zero_grad()#前向+后向+优化器
     outputs = rnn(images)
	 loss = criterion(outputs, labels)
	 loss.backward()
	 optimizer.step()
 if (i + 1) % 100 == 0:
 	print('Epoch [%d/%d], Step [%d/%d], Loss: %.4f'% (epoch+1,num_epochs,i + 1, len(train_dataset)
 // batch_size, loss.item()))
 
# 测试模型
correct = 0
total = 0
for images, labels in test_loader:
	 images = Variable(images.view(-1, sequence_length, input_size))
	 outputs = rnn(images)
	 _, predicted = torch.max(outputs.data, 1)
	 total += labels.size(0)
	 correct += (predicted.cpu() == labels).sum()
	 print('Test Accuracy of the model on test images: %d %%'  %  (100 * correct / total))

AE

  1. 特征
    自动编码器通常具有比输入数据低得多的维度,使其可以实现降维目的。
    自动编码器还可以应⽤于降噪场合。
    自动编码器还可以作为强⼤的特征检测器,它们可以⽤于⽆监督的深度神经⽹络预训练。
    ⼀些自动编码器是生成式模型,能够随机生成与训练数据⾮常相似的新数据。
  2. 自动编码器由两部分组成:
    识别⽹络: 将输⼊转换为潜在表征的编码器
    ⽣成⽹络: 将潜在表征转换为输出的解码器
  3. 数据的潜在空间表示包含表示原始数据点所需的所有重要信息。该表示必须表示原始数据的特征。换句话说,该模型学习数据特征并简化其表示,从⽽使其更易于分析。
  4. 输出层中的神经元数量必须等于输⼊数量。⾃动编码器试图重构输⼊,所以输出通常被称为重建,并且损失函数包含重建损失,当重建与输⼊不同时,重建损失会对模型进⾏惩罚。
X_train = np.random.rand(100,3)
encoder = Sequential([Dense(2, input_shape=[3])])
decoder = Sequential([Dense(3)])

autoencoder = Sequential([encoder, decoder])
autoencoder.compile(loss="mse", optimizer=SGD(lr=0.1))

history = autoencoder.fit(X_train, X_train, epochs=20)
codings = encoder.predict(X_train)

自动编码器被迫学习输⼊数据中最重要的特征,并且要删除不重要的特征。(借助PCA)如果⾃动编码器仅使⽤线性激活并且损失函数是均⽅误差(MSE),最终其实是做了主成分分析(PCA)
在这里插入图片描述

深度自动编码器

⾃动编码器可以有多个隐藏层,称为深度⾃动编码器。
添加更多层有助于⾃动编码器学习更复杂的编码。 但不要让⾃动编码器功能太强⼤。
如果⼀个编码器太强⼤,就会导致过拟合问题, 这样的⾃动编码器将完美地重构训练数据,但它不会在过程中学习到任何有⽤的数据表征,并且它不可能很好地泛化到新的实例。
在这里插入图片描述

import utils.mnist_reader
X_train, y_train = utils.mnist_reader.load_mnist('./data/', kind='train')
X_valid, y_valid = utils.mnist_reader.load_mnist('./data/', kind='t10k')
X_train = X_train.reshape(X_train.shape[0],28,28).astype('float32')
X_valid = X_valid.reshape(X_valid.shape[0],28,28).astype('float32')

stacked_encoder = Sequential([
Flatten(input_shape=[28, 28]),
Dense(100, activation="selu"),
Dense(30, activation="selu"),
])

stacked_decoder = Sequential([
Dense(100, activation="selu", input_shape=[30]),
Dense(28 * 28, activation="sigmoid"),
Reshape([28, 28])
])

stacked_ae = Sequential([stacked_encoder, stacked_decoder])
stacked_ae.compile( loss="binary_crossentropy", optimizer=SGD(lr=1.5))
history = stacked_ae.fit(X_train,X_train,epochs=10,validation_data=[X_valid])

卷积自动编码

卷积⾃动编码器通常会降低输⼊的空间维度(即,⾼和宽),同时增加深度(即,特征映射的数量)。⽽解码器的⼯作相反,即放⼤图⽚,压缩深度。可以通过转置卷积层实现。也可以将上采样层和卷积层合并。

conv_encoder = Sequential([
Reshape([28, 28, 1], input_shape=[28, 28]),
Conv2D(16, kernel_size=3, padding="same", activation="selu"),
MaxPool2D(pool_size=2),
Conv2D(32, kernel_size=3, padding="same", activation="selu"),
MaxPool2D(pool_size=2),
Conv2D(64, kernel_size=3, padding="same", activation="selu"),
MaxPool2D(pool_size=2)
])

conv_decoder = Sequential([
Conv2DTranspose(32, kernel_size=3, strides=2, padding="valid",
activation="selu", input_shape=[3, 3, 64]),
Conv2DTranspose(16, kernel_size=3, strides=2, padding="same",
activation="selu"),
Conv2DTranspose(1, kernel_size=3, strides=2, padding="same",
activation="sigmoid"),
Reshape([28, 28])
])

conv_ae = Sequential([conv_encoder, conv_decoder])
  • 反卷积
    ⼀种⽤于扩⼤图像的尺⼨的⽅法,称为逆卷积或反卷积。
    例如:输⼊特征图:3 ∗ 3 输⼊卷积核:kernel=3 ∗ 3, stride=2,padding=1
    输出特征图:3 * 3 - 3 + 2 * 1 +1 = 5

  • 循环自动编码器
    循环⾃动编码器中的编码器是⼀个序列到向量的 RNN,⽽解码器是向量到序列的 RNN。

recurrent_encoder = Sequential([
	LSTM(100, return_sequences=True, input_shape=[None, 28]),
	LSTM(30)
])
recurrent_decoder = Sequential([
	RepeatVector(28, input_shape=[30]), 将输⼊重复28LSTM(100, return_sequences=True),
	TimeDistributed(Dense(28, activation="sigmoid"))将Dense层应⽤于输⼊的每个时间⽚(对输入的每个向量进行一次Dense操作)。
])
recurrent_ae = Sequential([recurrent_encoder, recurrent_decoder])
  • VAE(变分自编码)

损失函数:

  1. 重建损失:推动⾃动编码器重现其输⼊。
  2. 潜在损失:推动⾃动编码器使编码看起来像是从简单的⾼斯分布中采样;
    使⽤⽬标分布(⾼斯分布)与编码实际分布之间的 KL散度

变分⾃动编码器不是直接为给定的输⼊⽣成编码;编码器产⽣平均编码μ和标准差σ, 然后从平均值μ和标准差σ的⾼斯分布随机采样实现编码。之后,解码器正常解码采样的编码。

  • 通过随机采样,可以将之前离散的潜在属性空间变为连续、平滑的潜在空间。

RL

Agent:智能体,也就是机器人,你的代码。
Environment:环境,也就是游戏本身,openai gym提供了多款游戏,也就是提供了多个游戏环境。
Action:行动,比如玩超级玛丽,向上向下等动作。
State:状态,每次智能体做出行动,环境会相应地做出反应,返回一个状态和奖励。
Reward:奖励:根据游戏规则的得分。智能体不知道怎么才能得分,它通过不断地尝试来理解游戏规则,比如它在这个状态做出向上的动作,得分,那么下一次它处于这个环境状态,就倾向于做出向上的动作。

在强化学习中,智能体(Agent)在环境(Environment)中观察(Observation)状态(State)并且做出决策(Action),随后它会得到奖励(Reward)。

  • 智能体的目标是去学习如何行动能最大化期望奖励

gym的核心接口是统一的环境Env,Env包含下面几个核心方法:

1、reset(self):重置环境的状态,返回观察值 observation 。
2、step(self,action):推进一个时间步长,返回[observation,reward,done,info]
3、render(self,mode='human', close=False): 重绘环境的一帧。默认模式一般比较友好,如弹出一个窗口。
4、info(dict):用于调试的诊断信息。
5、observation(object):返回一个特定环境的对象,描述对环境的观察。比如,来自相机的像素数 据,机器人的关节角度和关节速度,或棋盘游戏中 的棋盘状态。
6、reward(float):返回之前动作收获的总的奖 励值。
7、done(boolean):返回是否应该重新设置 (reset)环境。大多数游戏任务分为多个环节 (episode),当done=true的时候,表示这个环节结束了。

对于 CartPole 环境,每个观测是包含四个浮点的 1D Numpy 向量:
1.小车的水平位置(0 为中心)
2.小车的速度
3.杆的角度(垂直)
4.杆的角速度

CartPole-v0示例

env = gym.make('CartPole-v0') # 初始化环境
for i_episode in range(20): # 外层循环
	obs = env.reset()  返回观察值
	for t in range(100): # 内层循环
		env.render()  重绘环境的一帧。
		action = env.action_space.sample()  随机选取动作
		obs, re, done, info = env.step(action)
		print(obs)
		if done:
			print("done == True : %d" % (t+1))
			break
env.close()

深度强化学习

策略搜索

在强化学习中,被智能体(Agent)使用去改变它行为的算法叫做策略(Policy)。例如,策略可以是一个把观测(Observations)当输入,行为(Actions)当做输出的神经网络。

搜寻策略方法:
1)随机策略:这个策略可以是你能想到的任何算法;
2)尝试策略:可以通过尝试来搜索,即通过大量实验来选择参数的最佳组合;
3)遗传算法:通过遗传算法来搜索最佳参数
4)策略梯度(PG):使用优化技术,通过评估奖励关于策略参数的梯度,然后通过跟随梯度向更高的奖励(梯度上升)调整这些参数;
5)神经网络策略:神经网络将把观察作为输入,输出要执行的动作。它将估计每个动作的概率,然后我们将根据估计的概率随机地选择一个动作。

Q:为什么根据神经网络给出的概率来选择随机的动作,而不是选择最高分数的动作?
A:这种方法使智能体在探索新的行为和选择可行的行动之间找到平衡。

评价行为:信用分配问题

在强化学习中,智能体获得的指导的唯一途径是通过奖励,奖励通常是稀疏的和有延迟的。

信用分配问题:当智能体得到奖励时,如何知道哪些行为应该被信任(或责备)。

解决策略是基于这个动作后得分的总和来评估这个动作,通常在每个步骤中应用衰减率r。如果衰减率接近0,那么与即时奖励相比,未来的奖励不会有多大意义。相反,如果衰减率接近1,那么对未来的奖励几乎等于即时回报。

如果一个智能体决定连续三次向右,在第一步之后得到 +10 奖励,第二步后得到 0,第三步之后得到 -50,衰减率r=0.8,那么第一个动作将得到 10 + r × 0 + r 2 × ( − 50 ) = 10 + 0.8 × 0 + 0. 8 2 × ( − 50 ) = − 22 10+ r ×0+ r^2 ×(−50) = 10+0.8×0+0.8^2 ×(−50)=−22 10+r×0+r2×(50)=10+0.8×0+0.82×(50)=22的分数。

Q-Learning

  1. 马尔科夫链
    包含N个状态,从某个状态到其它状态的转移概率(Transition Probability)是确定的,且不取决于过去的状态(系统没有记忆)。将来的状态分布只取决于现在,跟过去无关。所有状态之间的转移概率关系可以用一个矩阵表示,称为转移矩阵(Transition Matrix)。
  2. 马尔可夫决策过程(MDP):
    1)在每个步骤中,agent 可以选择几种可能的动作中的一个,并且转移概率取决于所选择的动作。一些状态转换会返回一些奖励(正面或负面),而agent的目标是找到一种能够随着时间的推移最大化回报的策略。
    2)一种估算任何状态s的最佳状态值的方法,记为V*(s):
    在这里插入图片描述
  • T(s,a,s’)是agent 选择了动作a时,从状态s到状态s’的转换概率。
  • R(s,a,s’)是agent选择了动作a时,从状态s到状态s’时获得的奖励。γ是折扣率。

Q值迭代算法:

动态规划的一个例子,它将一个复杂的问题分解为易处理的子问题,并且可以通过迭代解决。

原理:将状态-动作值 (s,a) 称为Q值,记为Q(s,a),它将返回在该状态下执行该动作的未来奖励期望。状态-动作(s,a)的最佳Q值,记为Q*(s,a)。

  • 工作原理:首先将所有Q值估算值初始化为零,然后使用Q值迭代算法更新它们。
    在这里插入图片描述

Q-Learning算法是Q值迭代算法适应转移概率和奖励未知的情况。

对于每个状态 - 动作对(s,a),算法跟踪agent 在离开状态s时采取动作a的奖励的运行平均值,以及预期稍后获得的奖励。由于目标策略将采取最优行动,因此我们对下一个状态采取最大Q值估计。


估值Q-Learning
Q-Learning的主要问题是它不能很好地扩展到具有许多状态和动作的大型、中型MDP问题。找到一个使用参数数量可管理的函数来近似Q值,称为估值Q-Learning

  • 用于估计Q值的DNN称为深度Q网络(DQN)。使用DQN进行近似Q学习称为深度Q学习(DQL)。

Q-learning 示例

用一个简单的例子介绍Q-Learning算法的执行过程。在一幢建筑里有6个房间,房间用编号0-5表示,房间之间通过门相连。房间5是建筑外围空间,可以看作是一个大的房间。首先将Agent置于建筑中任意一个房间,其1目标是从那个房间开始走到房间5。

在这里插入图片描述

  1. 初始化:初始化Q,R,γ
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

  2. Q-Learning算法

在这里插入图片描述

Step 1 给定参数 和R矩阵,Q=0.
Step 2 循环执行Step3,4
Step 3 随机选择一个初始状态s
Step 4 循环执行:
	1.判断s是否是目标状态,如否则执行下列步骤,如是则结束Step 4.
	2.在当前状态s的所有可能行动中选取一个动作a
	3.利用选定的动作a,得到下一个状态s~
	4.利用公式计算Q(s,a)
	5.令s=s~
  1. 执行过程

     循环1
     	令初始状态为1。
     	状态不为5,则在R矩阵中选择状态1的可能动作:3或5。
     	选择状态5,得到下一个状态为5。
     	利用公式计算Q(1,5)
     	Q矩阵更新为:
     		当前状态为5,所以下次循环判断后即可结束
    

在这里插入图片描述
在这里插入图片描述


	循环2
		回到Step 3, 重新选择一个初始状态。
		选择初始状态为3.
		找出状态3的可能动作:1,2,4
		选择状态1,对应2个可能的动作:3或5
		利用公式计算Q(3,1)
		Q矩阵更新为:
			现在的当前状态变成了状态1,因为状态1不是目标状态,因此从状态1 的可能动作选择一个:3或5。
		选择状态5,其动作有3个可能:1,4或5;
		利用公式计算Q(1,5)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


	继续循环,继续执行多次后,将得到矩阵Q:
	
	一旦Q接近收敛状态,就可以指导Agent进行最佳路径选择。
	如,假定Agent从状态2出发,可到到下列路径:
	1. Q矩阵中,状态2的最大元素值为320,选择状态3;
	2. 状态3的最大元素值为400, 状态为1或4,选择状态4;
	3. 状态4的最大元素值为500,即状态5,到达目标。
	因此最佳路径为:2-3-4-5

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

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

相关文章

计算机网络安全的主要内容是什么?CISP题库分享

在技术上,网络安全包括物理安全、运行安全、信息安全和安全保证四个方面: 物理安全 包括环境安全、设备安全和记录介质安全。环境安全涉及中心机房和通信线路的安全保护问题;设备安全涉及设备的防盗和防毁、设备的安全使用等问题;记录介质安…

linux-docker备份数据库

利用计划任务和批处理从docker容器中备份数据库文件到宿主机指定目录 如何创建定时任务 创建计划任务(定时任务): crontab -e打开后是VI编辑器,将自己计划任务的内容写到里边然后wq(保存并退出)就行了 查…

当涉及到嵌入式开发时

以下是一些建议和关键要点,可以帮助您进行有效的开发: 硬件选择:根据项目需求选择合适的硬件平台和组件,包括处理器、存储器、传感器和通信接口等。考虑功耗、性能、可靠性和成本等因素。 软件开发环境:选择适合嵌入式…

3.1 增加多进程执行playwright

增加了多进程的方式执行测试代码,对代码改动比较大 1、case case目录依然是自动生成 2、config dir_collection.py新增了配置 mkdir_collections [case,log,img, ] del_collections [results,report ] del_regex temp3、data/img/log/resource/video data/im…

Linux内核4.14版本——drm框架分析(6)——实例注册drm device/ encoder/crtc/plane/connector等

目录 1. 简介 2. drm device的注册 3. fops 根据前面几篇文档的介绍,我们知道了drm的整体的构成,后面的文章我们从实际的一个例子中进行分析。 1. 简介 kernel版本:4.14 gpu:ARM Mali DP650 hdmi:dw hdmi 涉及的…

[已解决]无法在Windows 11中扩展C盘

如果你的台式电脑或笔记本电脑刚刚升级到Windows 11,如果你没有足够的硬盘空间来保存新文件和软件,那你可能会收到磁盘空间不足的警告。在这种情况下,你可能需要扩展分区来解决这个问题。 虽然Windows系统自带了“磁盘管理”工具&a…

10分钟了解Kubernetes网络

Kubernetes是现代容器化应用不可或缺的强大、可靠的基础平台。本文将介绍Kubernetes中与网络相关的组件,正是这些组件支撑Kubernetes成为云原生应用的首选基础设施。原文: Networking in Kubernetes 网络是Kubernetes中非常值得理解的重要主题,它帮助Kub…

【熬夜送书 | 第四期】python期末考试总结

文章目录 前言单选题程序填空题函数题编程题熬夜送书 第三期 前言 博主也是第一次接触到python语言,在考试前过了一遍python语法,因为有Java基础学习起来相对比较轻松,学校考的题相对简单一些,也是PTA上机考试,大概30…

字节测开岗面试记:二面被血虐,幸好还是拿到了Offer.....

在互联网做了几年之后,去大厂“镀镀金”是大部分人的首选。大厂不仅待遇高、福利好,更重要的是,它是对你专业能力的背书,大厂工作背景多少会给你的简历增加几分竞争力。 但说实话,想进大厂还真没那么容易。最近面试字…

让CSS布局呈现您的个性:学习常见布局方式

本文介绍常用的css布局&#xff1a; 三栏布局两列自适应布局元素居中 盒模型简介&#xff1a; 三栏布局 中间列自适应宽度&#xff0c;两边宽度固定 1. 圣杯布局 <!DOCTYPE html> <html> <head> <style> /* This is a single-line comment */.con…

迅为RK3588开发板-基于瑞芯微RK3588摄像头方案

硬件&#xff1a; RK3588开发板摄像头 MIPI摄像头&#xff1a; 1.1 硬件连接 RK3588 底板上有四个摄像头接口&#xff0c;如下图所示&#xff0c;此四个接口均可连接摄像头 ov5695 和 摄像头 ov13850。 摄像头模块连接硬件时要将模块对准插槽缺口处&#xff0c;J1 接口连接摄…

ipad手写笔哪款好?最好用的电容笔

近几年&#xff0c;电容笔逐渐成为人们日常生活中最重要的数码产品之一&#xff0c;不管是书写、绘画或者是玩游戏&#xff0c;使用iPad的地方就都能看到电容笔的身影。那么&#xff0c;哪个品牌的电容笔质量比较好&#xff1f;下面&#xff0c;我来给大家推荐四款好用的电容笔…

node+uniapp+socket简易聊天

目录 一、技术简介 1.1、客户端 1.2、服务器 二、代码分析 2.1、前端连接后端 2.2、前端发送&#xff0c;后端接收并广播回去 三、效果展示 四、升级版 一、技术简介 1.1、客户端 uni-app项目自行创建、weapp.socket.io这个需要后端下载cnpm i weapp.socket.io&…

1.2C++运算符重载

C运算符重载 C运算符重载是指对已有的C运算符进行重新定义&#xff0c;使其能够适用于用户自定义的数据类型。通过运算符重载&#xff0c;我们可以使用C运算符对自定义的数据类型进行操作&#xff0c;使得程序更加简洁、易读、易维护。 C支持对大部分运算符进行重载&#xff…

CleanMyMac X2023电脑深度清理软件

在使用mac时&#xff0c;小编遇到了运行内存不足、硬盘空间不足的情况。遇到这种情况&#xff0c;我们可以借助经典的电脑深度清理软件——CleanMyMac X&#xff0c;清理不常用的软件和系统垃圾&#xff01; 作为一款专业的mac电脑系统管家&#xff0c;CleanMymac X一直致力于…

韧性数据安全体系的原则和组成|CEO专栏

“韧性”数据安全体系&#xff0c;是美创科技在数据安全的最新探索。 特设专栏“构建适应性进化的韧性数据安全体系”中&#xff0c;首期文章&#xff08;点击此处跳转&#xff09;&#xff0c;我们重点介绍了韧性数据安全体系的三个目标&#xff1a;韧性和弹性、适应性进化、复…

【基于Rsync实现Linux To Windows文件同步】

基于Rsync实现Linux To Windows文件同步 简介安装步骤安装Linux服务器端1.安装rsync2.启动Rsync3.验证是否启动成功4.修改rsyncd.conf重启rsync服务 安装Windows客户端1.rsync客户端安装&#xff1a;2.配置环境变量3.测试rsync命令4.创建密码文件5.密码文件授权6.查看服务端需要…

【jupyter notebook】‘jupyter‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

目录 0.问题背景环境介绍 1.解决步骤 2.测试步骤 0.问题背景环境介绍 1&#xff09;环境&#xff1a;windows64 2&#xff09;问题背景&#xff1a;在搭建jupyter notebook的过程中&#xff0c;想用windows的任务管理器启动jupyter notebook或者使用【jupyter notebook --…

赋能生态合作 共话数字创新 | 2023开放原子全球开源峰会软硬协同开源分论坛即将启幕

随着信息技术的迅猛发展&#xff0c;当下智能应用场景日益复杂、数据量爆发式增长、数据形式也多种多样&#xff0c;作为跨越无数创新领域的驱动者&#xff0c;理应打造更高质量的生态系统和开源生态&#xff0c;提供丰富的软件产品和服务&#xff0c;打造软件和硬件协同开源的…

地理空间数据云管理-四维轻云1.3.2-版本更新内容

很多用户想要在不上传数据的情况下查看案例数据&#xff0c;我们在四维轻云1.3.2版本中为新用户新增了示例项目。此外&#xff0c;此次更新还新增了标绘数据模式和场景定时保存提醒功能&#xff0c;优化了插件启动流程以及移动和旋转变化轴。 1、新增示例项目 示例项目中包含…