来源 | Deep Learning with PyTorch

作者 |  Stevens, et al.

译者 | 杜小瑞

校对 | gongyouliu

编辑 | auroral-L

全文共7849字,预计阅读时间45分钟。

第四章  使用张量表示真实世界的数据(中)

1. 使用图像

1.1  添加颜色通道

1.2  加载一个图片文件

1.3  改变布局

1.4  数据标准化

2.  三维图像:体积数据

2.1  加载专用格式

3.  表示表格数据

3.1  使用真实数据集

3.2  加载葡萄酒数据张量

3.3  表示分数

3.4  one-hot 编码

3.5  何时进行分类

3.6  找到阈值

4.  使用时间序列

4.1  添加一个时间维度

4.2  按时间段构造数据

4.3  准备训练

5.  表示文本

5.1  将文本转化为数字

5.2  one-hot 编码字符

5.3  one-hot 编码整个单词

5.4  文本嵌入

5.5  作为蓝图的文本嵌入

6.  结论

7.  练习

8.  总结

3. 表示表格数据

我们在机器学习工作中遇到的最简单的数据形式是电子表格、CSV文件或数据库。不管是哪种媒介,它都是一个表,每个样本(或记录)包含一行,其中列包含一条关于样本的信息。

首先,我们假设样本在表中出现的顺序没有意义:与时间序列不同,这样的表是一个独立样本的集合,在时间序列中,样本是由一个时间维度关联的。

列可能包含数值,如特定位置的温度;或者标签(labels),比如表示样本属性的字符串,如“blue”。因此,这些与表格数据通常不是同质的:不同的列没有相同的类型。我们可能有一个列显示苹果的重量,另一个列在标签中编码苹果的颜色。

另一方面,PyTorch张量是同种类的。PyTorch中的信息通常被编码为一个数字,通常是浮点数(尽管也支持整数类型和布尔类型)。这种数字编码是经过深思熟虑的,因为神经网络是以实数作为输入,通过连续应用矩阵乘法和非线性函数产生实数作为输出的数学实体。

3.1 使用真实数据集

作为深度学习实践者,我们的第一项工作是将异构的、真实世界的数据编码成一个浮点数张量,供神经网络使用。大量表格数据集可在互联网上免费获得;比如说,https://github.com/caesar0301/awesome-public-datasets。让我们从一些有趣的事情开始:葡萄酒!葡萄酒质量数据集是一个免费提供的表格,其中包含来自葡萄牙北部的维诺维德葡萄酒样品的化学特征,以及感官质量评分。白葡萄酒的数据集可以在这里下载:http://mng.bz/90Ol。为了方便起见,我们还在data/p1ch4/tabular-wine下使用PyTorch Git库创建了一个数据集副本。

该文件包含一个以逗号分隔的数据集合,这些值按12列组织,前面有一个包含列名的标题行。前11列是化学变量值,最后一列是从0(非常差)到10(优秀)的感官质量分数。以下是列名在数据集中的显示顺序:

在这个数据集上,一个可能的机器学习任务是仅从化学特性预测质量分数。不过不用担心的是,机器学习短期内不会消灭品酒师的职业。我们必须从某处得到训练数据!如图4.3所示,我们希望找到数据中的一个化学列和质量列之间的关系。在这里,我们期望看到质量随着硫的减少而提高。

图 4.3 我们希望硫与葡萄酒质量的关系

3.2 加载葡萄酒数据张量

然而,在实现这一点之前,我们需要能够以比在文本编辑器中打开文件更有用的方式检查数据。让我们看看如何使用Python加载数据,然后将其转换为PyTorch张量。Python提供了几个快速加载CSV文件的选项。三种流行的选择是:

 Python附带的csv模块

 Numpy

 Pandas

第三种选择是最节省时间和内存的。但是,我们将避免仅仅因为需要加载文件而在学习轨迹中引入额外的库。由于我们在上一节中已经介绍了NumPy,并且PyTorch具有出色的NumPy互操作性,因此我们将继续讨论。让我们加载文件并将结果NumPy数组转换成PyTorch张量(code/p1ch4/3_tabular_wine.ipynb)。

在这里,我们只需指定2维数组的类型(32位浮点)、用于分隔每行中的值的分隔符,以及不应读取包含列名的第一行。让我们检查一下是否所有的数据都被读取了

然后继续将NumPy数组转换为PyTorch张量:

此时,我们有一个包含所有列的浮点torch.tensor,包括代表质量分数的最后一列。

连续值、序数值和分类值

当我们试图理解我们的数据时,我们应该意识到三种不同的数值。第一种是连续值。当用数字表示时,这是最直观的方式。它们是严格有序的,各种数值之间的差异有严格的含义。说明A包比B包重2公斤,或者B包来自比A远100英里的地方,无论A包是3公斤还是10公斤,或者B包来自200英里以外或2000英里以外,都具有固定的含义。如果你用单位来计算或测量某物,它可能是一个连续值。有的文献实际上进一步划分了连续值:在前面的例子中,如果说某个物体的重量是原来的两倍或距离的三倍,那么这些值被称为是一个比例标度。另一方面,一天中的时间确实有差异的概念,但是声称6:00是3:00的两倍是不合理的;所以一天中的时间只提供了一个时间间隔。

接下来是序数值。我们对连续值的严格排序仍然存在,但值之间的固定关系不再适用。一个很好的例子是订购一个小杯、中杯或大杯的饮料,其中小杯映射到值1、中杯为2和大杯为3。大杯比中杯大,就像3比2大一样,但它并不能告诉我们大杯的大小。如果我们将1、2和3转换为实际体积(比如8、12和24盎司),那么它们将转换为区间值。重要的是要记住,我们无法对序数值进行排序之外的其他操作;尝试将等于3的大杯和等于1的小杯平均并不会得到中杯!

最后,分类值对它们的值既没有顺序也没有数字意义,它们通常只是分配给任意数字的可能性的枚举。将水分配给1,咖啡分配给2,苏打水分配给3,牛奶分配给4就是一个很好的例子。把水放在第一位,牛奶放在最后是没有真正的逻辑的;它们只需要不同的值来区分它们。我们可以将咖啡分配到10,将牛奶分配到–3,并且不会有显著的变化(尽管将值分配在0到N–1范围内对one-hot编码和嵌入有好处,我们将在第4.5.4节中讨论。)因为数值没有意义,所以它们被称为名义上的值。

3.3 表示分数

我们可以把分数看作一个连续变量,保持它为一个实数,然后执行回归任务,或者把它看作一个标签,然后在分类任务中尝试从分析中猜测标签。在这两种方法中,我们通常会从输入数据的张量中移除分数,并将其保留在单独的张量中,以便我们可以使用分数作为基本事实,而不必将其输入到我们的模型中:

如果我们想将目标张量转换为标签张量,我们有两个选择,这取决于我们使用分类数据的策略或目的。一种是简单地将标签视为分数的整数向量:

如果目标是字符串标签,比如葡萄酒颜色,那么为每个字符串指定一个整数就可以让我们遵循相同的方法。

3.4 one-hot编码

另一种方法是构建分数的one-hot编码:也就是说,在10个元素的向量中对10个分数中的每一个进行编码,所有元素都设置为0,但每个分数有一个不同的索引。这样,得分1可以映射到向量(1,0,0,0,0,0,0,0,0,0),得分5可以映射到向量(0,0,0,0,0,1,0,0,0,0,0),依此类推。请注意,分数对应于非零元素的索引这一事实纯粹是偶然的:我们可以重新赋值,从分类的角度看不会有任何变化。

这两种方法有明显的区别。将葡萄酒质量分数保持在分数的整数向量中会导致对分数进行排序,在这种情况下可能是完全合适的,因为1的分数低于4的分数。同时也可以对分数之间的距离进行区分:即1和3之间的距离与2和4之间的距离相同。另一方面,如果分数是完全离散的,比如葡萄品种,one-hot编码会更合适,因为没有隐含的顺序或距离。one-hot编码也适用于当整数分数之间的分数(如2.4),对于分数值为this或that的应用程序分数则毫无意义。

我们可以使用scatter_方法实现one-hot编码,该方法使用原张量中的值沿着作为参数提供的索引填充张量:

让我们看看scatter_是怎么做的。首先,我们注意到它的名称以下划线结尾。正如你在上一章中了解到的,这是PyTorch中的一个约定,表示该方法不会返回新的张量,而是会就地修改张量。scatter_的参数如下:

 指定后面两个参数按照哪一个维度来定义

l 一个列张量,表示要赋值的元素的指标

 包含要赋值的张量或单个要赋值的标量(在本例中为1)

换句话说,前面的调用是,“对于每一行,取目标标签的索引(在我们的例子中,它与得分一致)并将其用作列索引,以将值设置为1.0。”最终结果是对分类信息进行张量编码。

scatter_的第二个参数,索引张量,要求与要赋值的张量具有相同的维数。因为目标有两个维度(4898× 10) ,我们需要使用unsqueeze向target添加额外的虚拟维度:

对unsqueeze的调用添加了一个单例维度,从4898个元素的一维张量到大小为4898× 1的二维张量,在不改变其内容的情况下,不添加额外的元素;我们只是决定使用一个额外的索引来访问元素。也就是说,我们将target的第一个元素访问为target[0],将unqueezed对应项的第一个元素访问为target_unqueezed[0,0]。

PyTorch允许我们在训练神经网络时直接使用类索引作为目标。然而,如果我们想使用分数作为网络的分类值输入,我们必须将其转换为one-hot编码张量。

3.5 何时进行分类

现在我们看到了处理连续数据和分类数据的方法。你可能想知道,在前面讨论的序数情况是什么样的。没有通用的方法;最常见的是,这样的数据要么被视为分类的(丢失排序部分,并且如果我们只有少数几个类别的话,希望我们的模型在训练过程中会获得序信息),要么被视为连续的(引入任意的距离概念)。对于图4.5中的天气情况,我们将使用后者。我们在图4.4中的流程图中总结了我们的数据映射。

图 4.4 如何处理具有连续、有序和分类数据的列

让我们回到我们的数据张量,包含11个与化学分析相关的变量。我们可以使用PyTorch张量API中的函数来处理张量形式的数据。让我们首先获得每列的平均值和标准差:

在这种情况下,dim=0表示沿维度0进行缩减。此时,我们可以通过减去平均值并除以标准偏差来规范化数据,这有助于学习过程(我们将在第5章第5.4.4节中对此进行更详细的讨论):

3.6 找到阈值

接下来,让我们来看看数据,看看是否有一个简单的一目了然的方法来区分好的和坏的葡萄酒。首先,我们要确定target中哪些行对应于小于或等于3的分数:

请注意,只有20个bad_index项被设置为True!通过在PyTorch中使用高级索引的功能,我们可以使用数据类型为torch.bool的张量来索引数据张量。这实际上将过滤数据,使其过滤出索引张量中与True相对应的项(或行)。bad_index张量与目标张量的shape相同,其值为假或真取决于阈值与原始目标张量中每个元素之间的比较结果:

注意,新的bad_data张量有20行,与bad_index张量中带True的行数相同。它保留了所有11列。现在我们可以开始了解葡萄酒分为好的、中等的和不好的类别。我们取每列的.mean():

看起来我们已经知道了一些事情:乍一看,劣质葡萄酒的总二氧化硫含量似乎更高,当然也还有其他的区别。我们可以用一个总二氧化硫的阈值作为区分好葡萄酒和坏葡萄酒的粗略标准。让我们得到总二氧化硫列低于我们之前计算的均值的索引(index),如下所示:

这表示按照我们的阈值有超过一半的葡萄酒都是高品质的。接下来,我们需要得到真正好的葡萄酒的指数:

因为有大约有比我们的阈值预期多500多个真正的好葡萄酒,我们已经有确凿的证据说明我们之前的结论是不完美的。现在我们需要看看我们的预测与实际排名的吻合程度。我们将在预测指数和实际良好指数之间执行逻辑“与”(记住,每一个指数只是一个0和1的数组),并使用一致的葡萄酒交集来验证我们的结论的准确度:

我们的预测中有大约2000瓶葡萄酒是正确的预测!因为我们预测了2700种葡萄酒,这表示如果我们预测某一瓶葡萄酒是高品质的,那么我们有74%的概率是正确的。不幸的是,在3200种高品质的酒中,我们只鉴定了其中的61%。好吧,我们得到了我们想要的结果,但是这比随机预测的好不了多少!当然,这种方法太天真了,我们确信多个变量对葡萄酒质量有贡献,这些变量的值与结果之间的关系(可能是实际分数,而不是0-1值)可能比单一值的简单阈值更复杂。

事实上,一个简单的神经网络将克服所有这些限制,就像许多其他基本的机器学习方法一样。在接下来的两章中,一旦我们学会了如何从头开始构建第一个神经网络,我们就有了解决这个问题的工具。我们还将在第12章重新讨论如何更好地对结果进行分级。现在让我们继续讨论其他数据类型。

4. 使用时间序列

在上一节中,我们介绍了如何表示在二维表中组织的数据。我们注意到,表中的每一行都是独立的;他们的顺序无关紧要。或者,等价地,没有一列编码是关于哪些行来得早,哪些行来得晚的信息。

回到葡萄酒数据集,我们可以有一个“年份”专栏,让我们看看葡萄酒质量是如何年复一年地演变的。不幸的是,我们手头没有这样的数据,但我们正在努力手动一瓶一瓶的收集数据样本(方便我们第二版的数据)与此同时,我们将切换到另一个有趣的数据集:来自华盛顿特区自行车共享系统的数据,该系统报告了2011-2012年首都自行车共享系统中每小时租赁自行车的数量,以及天气和季节信息(可从以下网址获得:http://mng.bz/jgOx). 我们的目标是获取一个平面的2D数据集并将其转换为3D数据集,如图4.5所示。

图 4.5 通过将每个样本的日期和时间分隔为单独的轴,将一维多通道数据集转换为二维多通道数据集

4.1 添加一个时间维度

在源数据中,每一行都是单独的一小时数据(图4.5显示了一个转置版本,以便更好地适应输出页面)。我们想要改变每小时行的组织,这样我们就有了一个轴,它以每索引增量一天的速度增加,另一个轴表示一天中的小时(与日期无关),第三个轴将是不同的数据列(天气、温度等)。

让我们加载数据(代码/p1ch4/4_time_series_bikes.ipynb)。

数据集每小时报告以下变量:

记录索引:instant

月份中的天:day

季节:season(1:春天,2:夏天,3:秋天,4:冬天)

年:yr(0:2011, 1:2012)

小时:hr(0到23)

假期状态:holiday

工作日:weekday

工作日状态:workingday

天气情况:weathersit(1:晴朗,2:雾,3:小雨,4:大雨)

摄氏度表示的温度:temp

感觉到的温度:atemp

湿度:hum

风速:windspeed

临时用户数:casual

注册用户数:registered

租赁自行车的数量:cnt

在像这样的时间序列数据集中,行表示连续的时间点:有一个维度,它们是沿着这个维度排序的。当然,我们也可以将每一行视为独立的,并尝试根据一天中的某个特定时间预测自行车的数量,而不管之前发生了什么。然而,排序的存在使我们有机会利用跨时间的因果关系。例如,它可以让我们是基于下雨之前的时间预测在某个时间骑自行车的数量。目前,我们将专注于学习如何将我们的自行车共享数据集转化为我们的神经网络能够以固定大小的块读取的数据。

这个神经网络模型将需要看到每个变量的数值序列,例如乘坐次数、一天中的时间、温度和天气条件:N个大小为C的平行序列。用神经网络的说法,C代表通道,和我们这里的一维数据列是一样的。N表示时间轴,这里每小时一个条目。

4.2 按时间段构造数据

我们可能想把两年的数据集分成更广泛的观察期,比如几天。这样我们就有N个长度为L的C序列集合。换句话说,我们的时间序列数据集将是一个维数为3,形状为N× C× L的张量。C仍然是我们的17个通道,而L通道则是每天24:1。我们没有特别的理由必须使用24小时的时间段,尽管一般的日常节奏可能会给我们提供一些模式,我们可以利用这些模式进行预测。如果我们愿意的话,我们也可以用7× 24将每周划分168个小时的区块。当然,所有这些都取决于数据集的大小,行数必须是24或168的倍数,而且,为了使这一点有意义,时间序列中不能有间隔。

让我们回到我们的自行车共享数据集。第一列是索引(数据的全局排序),第二列是日期,第六列是时间。我们有创建一个乘坐计数和其他外生变量的每日序列数据集所需要的全部条件。我们的数据集已经排序,如果没有排序的话,我们可以使用torch.sort对其进行适当排序。

注意

我们使用的文件版本hour-fixed.csv已经进行了一些处理,以包含原始数据集中缺少的行。我们假设缺失的时间没有自行车活动(通常是在清晨)。

要获取我们的每日小时数据集,我们要做的就是每24小时查看同一张量。让我们看看自行车张量的形状和步长:

这是17,520小时,共17列。现在,我们将数据重塑为具有3个轴:天,时,然后是17列:

这里发生了什么?首先,bikes.shape[1]是17,也就是bikes张量中的列数。但这段代码真正的关键是对视图的调用,这一点非常重要:它改变了张量查看存储中包含的相同数据的方式。

正如你在上一章中了解到的,调用张量上的视图将返回一个新的张量,该张量将更改维度数和步长信息,而不更改存储。这意味着我们可以零成本重新排列我们的张量,因为数据不会被复制。我们对视图的调用要求我们为返回的张量提供新的形状。我们使用-1作为占位符来表示“给定其他维度和元素的原始数量,不管剩下多少索引。”

还请记住上一章中提到的存储是一个连续的线性数字容器(在本例中是浮点)。我们的bikes张量将把每一行依次存储在相应的存储器中。前面对bikes.stride()的调用的输出证实了这一点。

对于daily_bikes,步长告诉我们,沿时间维度(第二维度)前进1需要我们在存储中前进17个位置(或一列);而沿日期维度(第一个维度)前进需要我们将元素的数量增加等于存储时间24(小时)中一行的长度(此处为408,即17×24)。

我们看到最右边的维度是原始数据集中的列数。然后,在中间维度,我们有分成连续的24小时的时间。换句话说,对于C通道,我们现在一天有N个L小时序列。达到我们想要的目标N× C× L排序,我们需要转置张量:

现在,让我们将前面学习的一些技术应用到这个数据集。

4.3 准备训练

“天气状况”变量是有序的。它有四个等级:1是天气好,4是天气很差。我们可以将此变量视为分类变量,将级别解释为标签,或者将其视为连续变量。如果我们决定使用分类变量,我们会将变量转换为one-hot编码向量,并将列与数据集连接起来。

为了更方便地呈现数据,我们暂时将自己的时间限制在第一天。我们初始化一个零填充矩阵,行数等于一天中的小时数,列数等于天气级别数:

然后我们根据每一行的对应级别将它们分散到我们的矩阵中。请记住使用unsqueze添加单例维度,就像我们在前面几节中所做的那样:

我们的一天从天气“1”开始,以“2”结束,所以这似乎是对的。

最后,我们使用cat函数将我们的矩阵连接到原始数据集。让我们看一下我们的第一个结果:

在这里,我们规定了原始的bikes数据集和one-hot编码的“天气状况”矩阵沿列维度串联(也就是维度1)。换句话说,这两个数据集的列被堆叠在一起;或者,等价地,新的one-hot编码列被附加到原始数据集中。要使cat连接成功,在这种情况下,其他维度(行维度)上的张量必须具有相同的大小。请注意,新的最后四列是1、0、0、0,这与天气值为1时所期望的完全一样。

我们可以用重塑后的每日自行车张量做同样的事情。记住它的形状是(B,C,L),其中L=24。我们首先创建零张量,使用相同的B和L,但额外的列数为C:

然后我们将one-hot编码分散到C维的张量中。由于此操作是在适当的位置执行的,因此只有张量的内容会改变:

我们沿着C维连接:

我们前面提到,这不是处理“天气状况”变量的唯一方法。事实上,它的标签有顺序关系,所以我们可以假设它们是连续变量的特殊值。我们可以转换变量到0.0到1.0的范围内:

正如我们在上一节中提到的,将变量重新缩放到[0.0,1.0]区间或[-1.0,1.0]区间是我们要为所有定量变量做的事情,比如温度(数据集中的第10列)。我们稍后再看原因;现在,我们应该知道这对训练过程是有益的。

重新缩放变量有多种可能性。我们可以将它们的范围映射到[0.0,1.0]

或减去平均值并除以标准差:

在后一种情况下,我们的变量将有0平均值和单位标准差。如果我们的变量来自高斯分布,68%的样本将位于[-1.0,1.0]区间。

太好了:我们建立了另一个不错的数据集,而且我们已经了解了如何处理时间序列数据。对于这次旅程,重要的是我们了解时间序列的布局方式以及如何将数据整理成网络可理解的形式。

其他类型的数据看起来像一个时间序列,因为有一个严格的排序。列表最前的两个是什么呢?文本和音频。那么接下来我们将看一看文本,“结论”部分有指向其他音频示例的链接。

「PyTorch深度学习入门」4. 使用张量表示真实世界的数据(中)相关推荐

  1. PyTorch深度学习入门与实战(案例视频精讲)

    作者:孙玉林,余本国 著 出版社:中国水利水电出版社 品牌:智博尚书 出版时间:2020-07-01 PyTorch深度学习入门与实战(案例视频精讲)

  2. PyTorch深度学习入门

    作者:曾芃壹 出版社:人民邮电出版社 品牌:iTuring 出版时间:2019-09-01 PyTorch深度学习入门

  3. pytorch深度学习入门笔记

    Pytorch 深度学习入门笔记 作者:梅如你 学习来源: 公众号: 阿力阿哩哩.土堆碎念 B站视频:https://www.bilibili.com/video/BV1hE411t7RN? 中国大学 ...

  4. Pytorch深度学习入门:60分钟闪电战

    目录 1. 学习基础知识 1.1运行教程代码 1.2如何使用本指南 2.快速启动 2.1与数据打交道 2.2建立模型 2.3优化模型参数 2.4保存模型 2.5装载模型 3.张量 3.1初始化一个张量 ...

  5. 为什么医学影像AI已进入「后深度学习时代」?

    http://blog.itpub.net/29829936/viewspace-2644440/ "深度学习正走向两极化,大部分研究深度学习的人员会偏向于工程化,包括建立更加全面.便捷.快 ...

  6. 使用深度学习的PointNet直接从无人机载激光雷达数据中分割单个树冠

    Paper题目:Individual Tree Crown Segmentation Directly from UAV-Borne LiDAR Data Using the PointNet of ...

  7. PyTorch深度学习入门 || 系列(四)——非线性回归

    文章目录 0 写在前面 1 激活函数 2 人工神经网络 3 数据处理 4 定义模型 5 完整代码 0 写在前面 这个系列之前学习是线性回归,但是生活中需要解决问题大多数都是非线性的. 本文要讨论的重点 ...

  8. PyTorch深度学习入门笔记(五)Transforms的使用

    课程学习笔记,课程链接 学习笔记同步发布在我的个人网站上,欢迎来访查看. 文章目录 一.Transforms的使用 二.Tensor数据类型 三.常见的Transforms 总结 一.Transfor ...

  9. PyTorch深度学习入门笔记(五)torchvision中DataLoader的使用

    dataloader简介 dataset在程序中起到的作用是告诉程序数据在哪,每个索引所对应的数据是什么.相当于一系列的存储单元,每个单元都存储了数据.这里可以类比成一幅扑克牌,一张扑克牌就是一个数据 ...

最新文章

  1. python取均匀不重复的随机数
  2. 【Java Web开发指南】线程安全和单线程
  3. [YTU]_2445(C++习题 输入输出--公用继承)
  4. opencv 人脸检测
  5. ElasticSearch搜索引擎: 内存分析与设置
  6. URAL 1033 Labyrinth
  7. CF838C-Future Failure【dp,子集卷积】
  8. MySQL的mysql_insert_id和LAST_INSERT_ID
  9. Windows 中自定义Error Codes
  10. 机器学习笔记(六):正则化
  11. Qt文档阅读笔记-TextEdit QML Type官方解析及实例
  12. 谷歌趋势:“比特币”热度远不及2017年高点
  13. Android桌面壁纸
  14. 电脑正下方显示桌面和计算机,电脑桌面下方的显示栏怎么设置
  15. 洛谷P1308 统计单词数
  16. iOS APP适配iPhone X全屏
  17. 微信小程序进度条样式_详解微信小程序——自定义圆形进度条
  18. 手机连上wifi不能上网
  19. Java通过javacsv实现读取csv文件数据
  20. 舍斯托夫与尼采和《圣经》思想--舍斯托夫的著作《雅典与耶路撒冷》 [ZZ]

热门文章

  1. Keycloak自定义实现第三方登录
  2. 最新destoon 模板标签大全
  3. 利用python-opencv 做出图像/视频的哈哈镜效果
  4. 云防护600Gddos流量攻击完美解决
  5. altium designer设计电路板全流程
  6. debian 开发版 移植_Debian 下安装 WineHQ 最新开发版和Staging版的方法
  7. 如何对连续型数据进行离散化处理,并进行OneHot编码?
  8. 国风(1)中国民族调式
  9. jspssm小区车位物业管理系统
  10. IoT入门:拆解物联网全栈开发工作