cubeIDE开发, stm32人工智能开发应用实践(Cube.AI).篇二

news2025/1/9 16:35:47

一、事有蹊跷

        接篇一,前面提到在使用cube.AI生成的c语言神经网络模型API调用时,输入数据数量是24,输出数据数量是4,但上文设想采集了三轴加速度传感器的x/y/z三个各数据,按Jogging(慢跑),Walking(走了)两种态势采集了两组数据.csv,那么在实际中应该是输入数据数量是3(x/y/x-value),输出数据数量是2(Jogging,Walking两种类别)。

        由于模型API是cube.AI基于训练输出的神经网络模型而生成的,想必应该是训练神经网络模型时参数设置问题,因此我们重新回顾HAR训练项目.

        进入“STM32CubeFunctionPack_SENSING1_V4.0.3\Utilities\AI_Ressources\Training Scripts\HAR”目录,运行 python .\RunMe.py -h命令,查看参数设置指令帮助,可以看到--seqLength和--stepSize参数设置都和input有关,默认数值是24,就可以笃定在API中调用时,输入数据数量是24就来自于此。

PS D:\tools\arm_tool\STM32CubeIDE\STM32CubeFunctionPack_SENSING1_V4.0.3\Utilities\AI_Ressources\Training Scripts\HAR> python3 .\RunMe.py -h
Using TensorFlow backend.
usage: RunMe.py [-h] [--model MODEL] [--dataset DATASET] [--dataDir DATADIR]
                [--seqLength SEQLENGTH] [--stepSize STEPSIZE] [-m MERGE]
                [--preprocessing PREPROCESSING] [--trainSplit TRAINSPLIT]
                [--validSplit VALIDSPLIT] [--epochs N] [--lr LR]
                [--decay DECAY] [--batchSize N] [--verbose N]
                [--nrSamplesPostValid NRSAMPLESPOSTVALID]

Human Activity Recognition (HAR) in Keras with Tensorflow as backend on WISDM
and WISDM + self logged datasets

optional arguments:
  -h, --help            show this help message and exit
  --model MODEL         choose one of the two availavle choices, IGN or GMP, (
                        default = IGN )
  --dataset DATASET     choose a dataset to use out of two choices, WISDM or
                        AST, ( default = WISDM )
  --dataDir DATADIR     path to new data collected using STM32 IoT board
                        recorded at 26Hz as sampling rate, (default = )
  --seqLength SEQLENGTH
                        input sequence lenght (default:24)
  --stepSize STEPSIZE   step size while creating segments (default:24, equal
                        to seqLen)
  -m MERGE, --merge MERGE
                        if to merge activities (default: True)
  --preprocessing PREPROCESSING
                        gravity rotation filter application (default = True)
  --trainSplit TRAINSPLIT
                        train and test split (default = 0.6 (60 precent for
                        train and 40 precent for test))
  --validSplit VALIDSPLIT
                        train and validation data split (default = 0.7 (70
                        percent for train and 30 precent for validation))
  --epochs N            number of total epochs to run (default: 20)
  --lr LR               initial learning rate
  --decay DECAY         decay in learning rate, (default = 1e-6)
  --batchSize N         mini-batch size (default: 64)
  --verbose N           verbosity of training and test functions in keras, 0,
                        1, or 2. Verbosity mode. 0 = silent, 1 = progress bar,
                        2 = one line per epoch (default: 1)
  --nrSamplesPostValid NRSAMPLESPOSTVALID
                        Number of samples to save from every class for post
                        training and CubeAI conversion validation. (default =
                        2)
PS D:\tools\arm_tool\STM32CubeIDE\STM32CubeFunctionPack_SENSING1_V4.0.3\Utilities\AI_Ressources\Training Scripts\HAR>

        而输出数据数量是4的原因追踪源码可以看到,来自于PrepareDataset.py(数据集预处理源文件),由于在参数--dataset默认设置是WISDM,因此分类输出即为'Jogging', 'Stationary', 'Stairs', 'Walking',即输出数据数量为4:

         下面来深入了解HAR(Human Activity Recognition,人类行为识别)案例为何会有这样的设置。

二、HAR训练项目分析

        由于前文仅仅采集Jogging(慢跑),Walking(走了)两种态势数据,但通常Stationary(站立不动)态势更常见和默认姿态,因此本文按篇一方法再采集一组Stationary姿态日志数据。

         并同样拷贝到HAR/Log_data目录下,数据如下:

         在PrepareDataset.py文件中,read_dataset( self )和preprocess_data( self, data )是用来处理WISDM数据集的,而get_data_from_file( self, fileName, preparedDataFileName )和prepare_self_logged_data( self )函数是用来处理自行采集数据集的。

         read_dataset会读取WISDM数据集的datasets/WISDM_ar_v1.1_raw.txt文件

         这些数据是已经做了转换预处理的数据集,见下图红线标注部分。

         而get_data_from_file( self, fileName, preparedDataFileName )函数读取自行采集数据集(.csv)文件时,做了转换预处理,确保和WISDM数据集一致。

         同时项目还把预处理过的自行采集数据集与训练好的模型一并以csv格式输出到目录中,以源数据目录命名,例如Log_data.csv。

         下来就是输入数据数量问题,由于在FP-AI-SENSING1案例项目,数据采集是按一定时间间隔连续实时采集的,因此get_segment_indices和get_data_segments函数就是将采集到的连续数据处理成一个长度为seqLength的窗口的输入数据集,即每次输入数据是一段24组(一组3个数据值,x/y/x)数据,也就对应了我们前文定义输入数据缓存是static ai_float in_data[AI_HAR_IGN_IN_1_SIZE=24*3*1];,共72个float 数据。显然HAR项目做法是通过一组连续数据集作为输入比单个态势数据更能反应人类行为姿态的持续性,更贴近实际。

         在read_dataset函数加入打印读取的WISDM数据集语句。

         在prepare_self_logged_data函数加入打印读取自行采集数据集语句

         因为打印输出依据后,后续会打印数据按输入数据长度来分段的信息,暂时保持seqLength和stepSize为默认的24数值,运行python3 .\RunMe.py --dataDir=Log_data命令:

PS D:\tools\arm_tool\STM32CubeIDE\STM32CubeFunctionPack_SENSING1_V4.0.3\Utilities\AI_Ressources\Training Scripts\HAR> python3 .\RunMe.py --dataDir=Log_data
Using TensorFlow backend.
Running HAR on WISDM dataset, with following variables
merge = True
modelName = IGN,
segmentLength = 24
stepSize = 24
preprocessing = True
trainTestSplit = 0.6
trainValidationSplit = 0.7
nEpochs = 20
learningRate = 0.0005
decay =1e-06
batchSize = 64
verbosity = 1
dataDir = Log_data
nrSamplesPostValid = 2
         User Activity_Label     Arrival_Time         x          y             z
0          33        Jogging   49105962326000 -0.694638  12.680544   0.50395286;
1          33        Jogging   49106062271000  5.012288  11.264028   0.95342433;
2          33        Jogging   49106112167000  4.903325  10.882658  -0.08172209;
3          33        Jogging   49106222305000 -0.612916  18.496431    3.0237172;
4          33        Jogging   49106332290000 -1.184970  12.108489     7.205164;
...       ...            ...              ...       ...        ...           ...
1098199    19        Sitting  131623331483000  9.000000  -1.570000         1.69;
1098200    19        Sitting  131623371431000  9.040000  -1.460000         1.73;
1098201    19        Sitting  131623411592000  9.080000  -1.380000         1.69;
1098202    19        Sitting  131623491487000  9.000000  -1.460000         1.73;
1098203    19        Sitting  131623531465000  8.880000  -1.330000         1.61;

[1098204 rows x 6 columns]
Segmenting Train data
Segments built : 100%|███████████████████████████████████████████████████| 27456/27456 [00:28<00:00, 954.67 segments/s]
Segmenting Test data
Segments built : 100%|██████████████████████████████████████████████████| 18304/18304 [00:14<00:00, 1298.22 segments/s]
Segmentation finished!
preparing data file from all the files in directory  Log_data
parsing data from  IoT01-MemsAnn_11_Jan_23_16h_57m_17s.csv
parsing data from  IoT01-MemsAnn_11_Jan_23_16h_57m_53s.csv
parsing data from  IoT01-MemsAnn_26_Jan_23_15h_51m_01s.csv
             x         y         z Activity_Label
0    -1.965414 -0.143890  9.367359        Walking
1    -1.629783  0.664754  9.618931        Walking
2    -1.720833  0.384629  9.492079        Walking
3    -1.681419  0.534637  9.648173        Walking
4    -1.729849  0.421650  9.557259        Walking
...        ...       ...       ...            ...
2639 -1.171046  0.033572  9.746819     Stationary
2640 -1.212873  0.007256  9.759376     Stationary
2641 -1.212011  0.019485  9.753982     Stationary
2642 -1.172311 -0.004511  9.734770     Stationary
2643 -1.175431  0.035787  9.753447     Stationary

[2644 rows x 4 columns]
Segmenting the AI logged Train data
Segments built : 100%|████████████████████████████████████████████████████████| 67/67 [00:00<00:00, 2795.31 segments/s]
Segmenting the AI logged Test data
Segments built : 100%|████████████████████████████████████████████████████████| 45/45 [00:00<00:00, 2370.94 segments/s]
Segmentation finished!
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
conv2d_1 (Conv2D)            (None, 9, 3, 24)          408
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 3, 3, 24)          0
_________________________________________________________________
flatten_1 (Flatten)          (None, 216)               0
_________________________________________________________________
dense_1 (Dense)              (None, 12)                2604
_________________________________________________________________
dropout_1 (Dropout)          (None, 12)                0
_________________________________________________________________
dense_2 (Dense)              (None, 4)                 52
=================================================================
Total params: 3,064
Trainable params: 3,064
Non-trainable params: 0
_________________________________________________________________
Train on 19288 samples, validate on 8233 samples
Epoch 1/20
2023-01-26 17:12:56.882726: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
19288/19288 [==============================] - 1s 54us/step - loss: 1.2022 - acc: 0.5290 - val_loss: 0.7089 - val_acc: 0.7409
Epoch 2/20
19288/19288 [==============================] - 1s 41us/step - loss: 0.7520 - acc: 0.7017 - val_loss: 0.5342 - val_acc: 0.7985
Epoch 3/20
19288/19288 [==============================] - 1s 41us/step - loss: 0.6079 - acc: 0.7571 - val_loss: 0.4573 - val_acc: 0.8153
Epoch 4/20
... ...
19288/19288 [==============================] - 1s 39us/step - loss: 0.3306 - acc: 0.8899 - val_loss: 0.2669 - val_acc: 0.9113
Epoch 20/20
19288/19288 [==============================] - 1s 40us/step - loss: 0.3194 - acc: 0.8913 - val_loss: 0.2646 - val_acc: 0.9168
12831/12831 [==============================] - 0s 22us/step
Accuracy for each class is given below.
Jogging     : 97.51 %
Stationary  : 98.63 %
Stairs      : 70.94 %
Walking     : 81.55 %
PS D:\tools\arm_tool\STM32CubeIDE\STM32CubeFunctionPack_SENSING1_V4.0.3\Utilities\AI_Ressources\Training Scripts\HAR>

        读取到的WISDM数据集大小是1098204≈24*(27456+18304),而27456+18304是按--trainSplit参数默认值0.6:0.4比例切分的。读取到的自行采集数据大小是2644≈24*(67+45)。

 三、工程调整

        从前面分析来看,输入数据数量还是采用默认数值24问题不大(各位粉丝可以自行调整其大小来测试及观察效果),输出数据数量由于有WISDM数据集参与,保持'Jogging', 'Stationary', 'Stairs', 'Walking'是中分类也OK。现注意到,其实输入数据是经过了预处理转换实际加速度值,而非是传感器原始输出数值。

        由于自行采集数据增加了Stationary数据文件,因此在cubeMX上采用新的训练模型文件重新生成c语言的神经网络模型。

         然后调整输入数据及预处理函数acquire_and_process_data,采用真实数据来测试

         该函数有原来的随机赋值,

int acquire_and_process_data(void *in_data,int factor)
{
	printf("in_data:");
	for (int i=0; i<AI_HAR_IGN_IN_1_SIZE; i++)
	{
		switch(i%3){
		case 0:
			((ai_float*)in_data)[i] = -175+(ai_float)(i*factor*1.2)/10.0;
			break;
		case 1:
			((ai_float*)in_data)[i] = 50+(ai_float)(i*factor*0.6)/100.0;
			break;
		case 2:
			((ai_float*)in_data)[i] = 975-(ai_float)(i*factor*1.8)/100.0;
			break;
		default:
			break;
		}
		printf("%.4f ",((ai_float*)in_data)[i]);
	}
	printf("\n");

	return 0;
}

        调整为

ai_float in_buf[] =
{
		-1.9654135467252831,-0.14388957575400915,9.36735860765576,
		-1.6297827960727935,0.6647544204312931,9.618930851170278,
		-1.7208332169161387,0.38462856310059845,9.492079217583663,
		-1.6814190066807724,0.5346365723749872,9.648173176699613,
		-1.7298486510592452,0.42164964981080416,9.557259289818587,
		-1.7618787694384546,0.45864558999786653,9.653153776935605,
		-1.7410197123193858,0.4236369742675384,9.55486293595946,
		-1.7600076822930908,0.46214612481362705,9.594426626710453,
		-1.5761631958773263,0.3715109598910308,9.436853714636964,
		-1.5920827364351244,0.37070313540523914,9.66189484448469,
		-1.6178308849438598,0.37500917334673567,9.695719226290015,
		-1.4388296833472143,0.6108605310285585,9.464814699883437,
		-1.5651621282887258,0.5691273914891515,9.513897717476588,
		-1.4637992479412343,0.5105873209777632,9.501636895304161,
		-0.6794677157685166,0.5024637601753793,8.96404801376064,
		0.2600149177042748,0.6699546179356337,8.903349009412763,
		1.0712686735261918,1.4889662656074603,9.520348132500752,
		0.3914123345764725,1.4210706041563634,10.557387805652848,
		1.0779003359396493,1.0582703827741018,10.454469820960814,
		0.12433283758079197,-0.27273511643713033,10.328552286632643,
		-0.010219096051988997,0.2961821896002729,9.483084545625971,
		-1.6910112286007235,-0.2898761724876157,9.704755735796937,
		-2.693651827312974,-0.41126025575408387,9.825328217800239,
		-2.8416981790648177,-0.14586229740441406,9.880552703938179
};

int acquire_and_process_data(void *in_data,int factor)
{
	printf("in_data:");
	for (int i=0; i<AI_HAR_IGN_IN_1_SIZE; i++)
	{
		((ai_float*)in_data)[i] =in_buf[i];
		printf("%.4f ",((ai_float*)in_data)[i]);
	}
	printf("\n");

	return 0;
}

        重新编辑及加载到开发板,打开串口助手,输入test*,查看测试效果如下:

四、遗留问题

        上述结果和HAR项目中的PrepareDataset.py分类似乎并没匹配上,那么就要分析PrepareDataset.py分类和生成后的c语言模型时如何对应的,以及用来测试的数据是否符合模型要求。

        为此,再次回到HAR训练模型项目,在RunMe.py文件中追加以下语句:

print("TestX:")
print(TestX[0:1])
print("TestY:")
print(TestY[0:1])

        以获取用来测试的真实模拟数据,再次运行python3 .\RunMe.py --dataDir=Log_data命令,最后部分输出如下:

TestX:
[[[[-3.64077855e-16]
   [-4.69612372e-16]
   [ 3.68092310e-10]]

  [[ 1.02756571e+01]
   [-1.14305305e+01]
   [ 2.61872125e+01]]

  [[-2.84181689e+00]
   [-3.54747048e+00]
   [-5.51206446e+00]]

  [[-3.82102513e+00]
   [-1.41233186e+01]
   [-4.59900586e+00]]

  [[ 6.68010824e+00]
   [ 9.39457601e+00]
   [-2.96397789e+00]]

  [[-1.71771782e+01]
   [ 1.19374149e+01]
   [ 3.05770680e+00]]

  [[-6.65782005e+00]
   [ 2.39062819e+00]
   [ 3.22844912e+00]]

  [[ 4.59021292e+00]
   [-6.27548028e+00]
   [-4.92783556e+00]]

  [[ 8.03018658e+00]
   [-2.72208600e+00]
   [-6.35796053e+00]]

  [[ 7.73164454e+00]
   [-6.31879160e+00]
   [-5.90723810e+00]]

  [[ 8.53803514e-01]
   [-9.75763211e+00]
   [ 1.02466115e+01]]

  [[ 1.11299171e+01]
   [-1.70658346e+01]
   [ 2.18511283e+01]]

  [[ 3.92044994e-01]
   [ 5.94768181e+00]
   [ 4.30131750e+00]]

  [[-5.61807988e+00]
   [ 1.97310400e+01]
   [-2.22512540e+00]]

  [[ 3.86836548e+00]
   [ 1.71617325e+00]
   [-5.86292387e+00]]

  [[ 7.65913325e+00]
   [-7.19628424e+00]
   [ 2.01628025e+00]]

  [[-7.52357836e+00]
   [ 3.68102584e+00]
   [-1.22753233e+01]]

  [[-5.12351958e+00]
   [ 1.23941669e+01]
   [-1.77385540e+00]]

  [[-4.86155823e-01]
   [ 1.26333902e+01]
   [ 5.93595914e+00]]

  [[-1.96569165e+01]
   [ 1.00467317e+01]
   [ 9.47374003e+00]]

  [[-4.34050581e+00]
   [ 5.16311148e-01]
   [-5.63004156e-01]]

  [[-3.57974669e+00]
   [ 4.87240857e-01]
   [-9.38271247e-01]]

  [[ 6.11930536e+00]
   [ 5.99067573e+00]
   [-7.68834262e+00]]

  [[ 1.12153409e+01]
   [ 2.37168199e+00]
   [-7.40963357e+00]]]]
TestY:
[[1. 0. 0. 0.]]
PS D:\tools\arm_tool\STM32CubeIDE\STM32CubeFunctionPack_SENSING1_V4.0.3\Utilities\AI_Ressources\Training Scripts\HAR>

        显然输入24*3的一组数据,输出结果是[1. 0. 0. 0.],再将该数据用于测试 c语言模型神经网络模型API调用。

ai_float in_buf[] =
{
		-3.64077855e-16,-4.69612372e-16,3.68092310e-10,
		1.02756571e+01,-1.14305305e+01,2.61872125e+01,
		-2.84181689e+00,-3.54747048e+00,-5.51206446e+00,
		-3.82102513e+00,-1.41233186e+01,-4.59900586e+00,
		6.68010824e+00, 9.39457601e+00,-2.96397789e+00,
		-1.71771782e+01,1.19374149e+01,3.05770680e+00,
		-6.65782005e+00,2.39062819e+00,3.22844912e+00,
		4.59021292e+00,-6.27548028e+00,-4.92783556e+00,
		8.03018658e+00,-2.72208600e+00,-6.35796053e+00,
		7.73164454e+00,-6.31879160e+00,-5.90723810e+00,
		8.53803514e-01,-9.75763211e+00, 1.02466115e+01,
		1.11299171e+01,-1.70658346e+01, 2.18511283e+01,
		3.92044994e-01, 5.94768181e+00, 4.30131750e+00,
		-5.61807988e+00, 1.97310400e+01,-2.22512540e+00,
		3.86836548e+00, 1.71617325e+00,-5.86292387e+00,
		7.65913325e+00,-7.19628424e+00, 2.01628025e+00,
		-7.52357836e+00, 3.68102584e+00,-1.22753233e+01,
		-5.12351958e+00, 1.23941669e+01,-1.77385540e+00,
		-4.86155823e-01, 1.26333902e+01, 5.93595914e+00,
		-1.96569165e+01, 1.00467317e+01, 9.47374003e+00,
		-4.34050581e+00, 5.16311148e-01,-5.63004156e-01,
		-3.57974669e+00, 4.87240857e-01,-9.38271247e-01,
		6.11930536e+00, 5.99067573e+00,-7.68834262e+00,
		1.12153409e+01, 2.37168199e+00,-7.40963357e+00
};

int acquire_and_process_data(void *in_data,int factor)
{
	printf("in_data:");
	for (int i=0; i<AI_HAR_IGN_IN_1_SIZE; i++)
	{
		((ai_float*)in_data)[i] =in_buf[i];
		printf("%.4f ",((ai_float*)in_data)[i]);
	}
	printf("\n");

	return 0;
}

        再次编译下载程序,采用串口助手测试如下,输出数据为,【0.943687 0.000000 0.000294 0.056019】,而实际数据是[1. 0. 0. 0.],显然能对应上,只是精度问题:

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

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

相关文章

Java链表OJ题

目录1. 删除链表中等于给定值val的所有结点2. 逆置单链表3. 链表的中间结点4. 链表中倒数第k个结点5. 将两个有序链表合并为一个新的有序链表6. 以给定值x为基准将链表分割成两部分7. 判断是否为回文链表8. 两个链表的第一个公共结点9. 判断链表中是否有环10. 链表开始入环的第…

【Linux】目录权限和默认权限

上期介绍了Linux的文件权限&#xff0c;这期我们仔细来说说Linux环境下目录权限和默认权限一、目录权限1.1 进入目录所需的权限我们在进入目录时需要什么样的权限呢&#xff1f;是r、w还是x呢&#xff1f;下面我们一起来验证一下&#xff1a;&#x1f4cb;如下我门拥有全部目录…

Day11 AOP介绍

1 前言AOP&#xff0c;Aspect Oriented Programming&#xff0c;面向切面编程&#xff0c;是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象&#xff0c;一个对象包括静态的属性信息&#xff0c;包括动态的方法信息等。而AOP是横向的对不同事物的抽象&#xff0c;属性与属…

【Python从入门到精通】第一阶段

文章目录前言python的起源打印hello world注释变量变量基本概念类型类型转换运算符字符串拓展字符串的三种定义方法字符串拼接字符串格式化数据输入input比较布尔类型和比较运算符if判断if elseif elif else嵌套循环while循环while循环嵌套for循环range()的使用函数的使用函数的…

3小时精通opencv(五) 利用TrackBar进行颜色检测

3小时精通opencv(五) 利用TrackBar进行颜色检测 参考视频资源:3h精通Opencv-Python 本章内容介绍如何利用TrackBar调节色域, 手动提取到我们需要的颜色 文章目录3小时精通opencv(五) 利用TrackBar进行颜色检测创建Trackbar色彩检测创建Trackbar 在opencv中使用createTrackbar函…

C语言:数组

往期文章 C语言&#xff1a;初识C语言C语言&#xff1a;分支语句和循环语句C语言&#xff1a;函数 目录往期文章前言1. 一维数组的创建和初始化1.1 数组的创建1.2 数组的初始化2. 一维数组的使用3. 一维数组在内存中的存储4. 二维数组的创建和初始化4.1 二维数组的创建4.2 二维…

大数据技术架构(组件)7——Hive:Filter PushDown Cases And Outer Join Behavior

1.2、Filter PushDown Cases And Outer Join Behavior前提:关闭优化器set hive.auto.convertjoinfalse; set hive.cbo.enablefalse;Inner Join:1、Join On中的谓词: 左表下推、右表下推2、Where谓词:左表下推、右表下推-- 第一种情况: join on 谓词 selectt1.user_id,t2.user_i…

C++函数定义和调用介绍

C函数定义和调用介绍 函数的意义&#xff1a;利用率高&#xff0c;可读性强&#xff0c;利于移植。 一个C程序中主函数有且只有一个&#xff0c;是程序的入口&#xff0c;而函数&#xff08;或称子函数&#xff09;可以有很多。 每个 C 程序都至少有一个函数&#xff0c;即主…

2021 XV6 8:locks

实验有两个任务&#xff0c;都是为了减少锁的竞争从而提高运行效率。Memory allocator一开始我们是有个双向链表用来存储空闲的内存块&#xff0c;如果很多个进程要竞争这一个链表&#xff0c;就会把效率降低很多。所以我们把链表拆成每个CPU一个&#xff0c;在申请内存的时候就…

栈和队列的应用

一、栈在括号匹配中的应用 数据结构之栈_迷茫中的小伙的博客-CSDN博客_数据结构之栈栈括号和队列的应用 二、栈在表达式求值中的应用 中缀转 ->后缀 &#xff1a; 左右先 (左边能先算,先算左边,因为这样可以保证确定性,即计算机运算的方式) 后缀转->中缀 &#xff1a…

王者荣耀入门技能树-解答

前言 前段时间写了一篇关于王者荣耀入门技能树的习题&#xff0c;今天来给大家解答一下。 职业 以下哪个不属于王者荣耀中的职业&#xff1a; 射手法师辅助亚瑟 这道题选&#xff1a;亚瑟 王者荣耀中有6大职业分类&#xff0c;分别是&#xff1a;坦克、战士、刺客、法师、…

如何好好说话-第12章 理清楚问题就是答案

生活中该不该积极主动与别人展开社交活动&#xff1f;有些时候社交活动并不开心&#xff0c;仅仅只是无聊的闲才。但他确实能拉拢人际关系&#xff0c;帮我们获得近身套路。而且有一种观点认为不善于社交的人是不成功的。注意以上说的这些都是偏见。当我们站在一个更高的维度认…

Jetpack架构组件库:Hilt

Hilt Hilt 是基于 Dagger2 的依赖注入框架&#xff0c;Google团队将其专门为Android开发打造了一种纯注解的使用方式&#xff0c;相比 Dagger2 而言使用起来更加简单。 依赖注入框架的主要作用就是控制反转&#xff08;IOC, Inversion of Control&#xff09;, 那么什么是控制…

表格相关的一些标签

<!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>表格相关的标一些签</title> </head> <body> <!-- 需求 1&#xff1a;做一个四行&#xff0c;三…

Golang进阶

"白昼会边长&#xff0c;照亮心脏,让万物生长。"一、Golang进阶我们对golang的语法进行了一定的了解后&#xff0c;也算是入门了。本节的进阶篇围绕三个方向展开,Goroutine 、 Channel 、Sync。如何理解并行与并发&#xff1f;并行是指“并排行走”或“同时实行或实施…

用数组实现链表、栈和队列

目录前言一、用数组实现链表1.1 单链表1.2 双链表二、用数组实现栈三、用数组实现队列前言 众所周知&#xff0c;链表可以用结构体和指针来实现&#xff0c;而栈和队列可以直接调用STL&#xff0c;那为什么还要费尽心思用数组来实现这三种数据结构呢&#xff1f; 首先&#x…

好的质量+数量 = 健康的创作者生态

缘起 CSDN 每天都有近万名创作者发表各种内容&#xff0c; 其中博客就有一万篇左右。 这个数量是非常可喜的&#xff0c;这也是 CSDN 的产品、研发运营小伙伴、和各位博主持续工作的结果。 衡量一个 IT 内容平台&#xff0c;除了数量之外&#xff0c;还有另外一些因素&#xf…

Linux——动态库

目录 制作并发布动态库 使用动态库 使用动态库程序运行时的错误 制作并发布动态库 静态库的代码在链接的时候会被拷贝进对应的可执行程序内部&#xff0c;动态库则不需要拷贝。 动态库在形成目标文件时&#xff0c;需要加一个选项 -fPIC&#xff1a;形成一个与位置无关的二…

Yocto常用术语

Yocto常用术语 Yocto是一套开源、专为嵌入式定制的编译系统&#xff0c;它提供了toolset和开发环境&#xff0c;开发人员可以利用Yocto定制基于Linux的系统。Yocto官网介绍了其常用术语&#xff0c;官网链接Yocto Project Terms&#xff0c;了解这些术语可以加深对Yocto的认识…

第五章 高级数据管理

在第4章&#xff0c;我们审视了R中基本的数据集处理方法&#xff0c;本章我们将关注一些高级话题。本章分为三个基本部分。在第一部分中&#xff0c;我们将快速浏览R中的多种数学、统计和字符处理函数。为了让这一部分的内容相互关联&#xff0c;我们先引入一个能够使用这些函数…