【深入浅出学习笔记】李沐《动手学深度学习2.0》之数据预处理学习

发布于:2022-11-28 ⋅ 阅读:(441) ⋅ 点赞:(0)

本文主要是学习李沐:动手学深度学习2.0在线课程的笔记。
视频地址:https://zhuanlan.zhihu.com/p/29125290。
教材全本:https://zh-v2.d2l.ai/
本课教材:https://zh-v2.d2l.ai/chapter_preliminaries/pandas.html
笔记地址:https://gitee.com/lhm8013609/mldl_-learning-notes/tree/master/1%E3%80%81DL_Limu/Notes

2021.05.08 数据预处理学习

os文件/目录方法模块学习

举一个例子,我们首先创建一个人工数据集,并存储在csv(逗号分隔值)文件 …/data/house_tiny.csv 中。以其他格式存储的数据也可以通过类似的方式进行处理。下面的mkdir_if_not_exist 函数可确保目录 …/data 存在。注意,注释 #@save是一个特殊的标记,该标记下方的函数、类或语句将保存在 d2l 软件包中,以便以后可以直接调用它们(例如 d2l.mkdir_if_not_exist(path))而无需重新定义。

import os

# os.makedirs() 方法用于递归创建目录
os.makedirs(os.path.join('..', 'data'), exist_ok=True)
data_file = os.path.join('..', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:
    f.write('NumRooms,Alley,Price\n')  # 列名
    f.write('NA,Pave,127500\n')  # 每行表示一个数据样本
    f.write('2,NA,106000\n')
    f.write('4,NA,178100\n')
    f.write('NA,NA,140000\n')

Note:

os.makedirs() 方法用于递归创建目录

  • makedirs()方法语法格式如下:
    os.makedirs(path, mode=0o777)
  • 参数
    path – 需要递归创建的目录,可以是相对或者绝对路径。
    mode – 权限模式。

os.path.join()函数用于路径拼接文件路径

  • 路径表示
  • . 表示当前目录
  • .. 表示当前目录的上一级目录。
  • ./表示当前目录下的某个文件或文件夹,视后面跟着的名字而定
  • ../表示当前目录上一级目录的文件或文件夹,视后面跟着的名字而定。
* os.path.join(‘…’, ‘data’) 表示路径…data,实际是在当前目录创建data文件夹
  • 会从第一个以”/”开头的参数开始拼接,之前的参数全部丢弃。
  • 以上一种情况为先。在上一种情况确保情况下,若出现”./”开头的参数,会从”./”开头的参数的上一个参数开始拼接。
  • 有多个以”/”开头的参数,从最后”/”开头的的开始往后拼接,之前的参数全部丢弃
  • !!!注意:Linux下和Windows下有所区别,这是基于Windows下的结论,见评论:python路径拼接os.path.join()函数完全教程
  • os.path.join(‘…’, ‘data’, ‘house_tiny.csv’) 表示当前目录的data文件夹下的house_tiny.csv文件的目录

with open(data_file, ‘w’) as f: f.write()

import os

# windows环境下,结果如上所述,结论正确
print("1:",os.path.join('aaaa','/bbbb','ccccc.txt'))
print("2:",os.path.join('/aaaa','/bbbb','/ccccc.txt'))
print("3:",os.path.join('aaaa','./bbb','ccccc.txt'))

输出:

1: /bbbb\ccccc.txt
2: /ccccc.txt
3: aaaa\./bbb\ccccc.txt

读取文件:

import pandas as pd
data = pd.read_csv(data_file)
data

输出:

	NumRooms	Alley	Price
0	NaN	Pave	127500
1	2.0	NaN	106000
2	4.0	NaN	178100
3	NaN	NaN	140000

2.2.2. 处理缺失值

注意,“NaN” 项代表缺失值。为了处理缺失的数据,典型的方法包括 插值 和 删除,其中插值用替代值代替缺失值。而删除则忽略缺失值。在这里,我们将考虑插值。

通过位置索引iloc,我们将 data 分成 inputs 和 outputs,其中前者为 data的前两列,而后者为 data的最后一列。对于 inputs 中缺少的的数值,我们用同一列的均值替换 “NaN” 项。

# iloc[:,:],逗号前是行,后是列,
# :表示从哪行(列)到哪行(列),如下面的0:2即表示0-2列
# 第二列,即最后一列
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]

inputs = inputs.fillna(inputs.mean())
print(inputs)

输出:

   NumRooms Alley
0       3.0  Pave
1       2.0   NaN
2       4.0   NaN
3       3.0   NaN

Note:

iloc函数:通过行号来取行数据(如取第二行的数据)

fillna(),mean()函数

  • fillna函数形式:fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)

  • 参数:

  • value:用于填充的空值的值。

  • 更多参数:pandas 用均值填充缺失值NaN | fillna 方法解析

  • mean()函数功能:求取均值:python 的numpy库中的mean()函数用法

  • 经常操作的参数为axis,以m * n矩阵举例:
    axis 不设置值,对 mn 个数求均值,返回一个实数
    axis = 0:压缩行,对各列求均值,返回 1 n 矩阵
    axis = 1 :压缩列,对各行求均值,返回 m *1 矩阵

  • mean(A)
    若A为矩阵,则输出每一列的均值(一个向量)
    若A为列向量,则输出均值(一个数)
    若A为行向量,则也是输出均值(一个数),和列向量一样

使用jupyter notebook编辑文本和代码:使用jupyter notebook编辑文本和代码

  • enter两行既是空一行
  • 按两次dd可以删除单元格

对于 inputs 中的类别值或离散值,我们将 “NaN” 视为一个类别。由于 “巷子”(“Alley”)列只接受两种类型的类别值 “Alley” 和 “NaN”,pandas 可以自动将此列转换为两列 “Alley_Pave” 和 “Alley_nan”。巷子类型为 “Pave” 的行会将“Alley_Pave”的值设置为1,“Alley_nan”的值设置为0。缺少巷子类型的行会将“Alley_Pave”和“Alley_nan”分别设置为0和1。

inputs = pd.get_dummies(inputs, dummy_na=True)
print(inputs)
   NumRooms  Alley_Pave  Alley_nan
0       3.0           1          0
1       2.0           0          1
2       4.0           0          1
3       3.0           0          1

Note

pd.get_dummies,

官方文档: 点这

  • pd.get_dummies(inputs, dummy_na=True)

  • 默认按值分为几列,同时dummy_na=True表示用bool值表示具体值

  • 以上只有pave和NAN两种值,所以分为两列,同时pave用1表示,NAN用0表示

  • 对分类型变量,进行编码处理——pd.get_dummies()、LabelEncoder()、oneHotEncoder():点这

2021.05.11

2.2.3. 转换为张量格式

现在 inputs 和 outputs 中的所有条目都是数值类型,它们可以转换为张量格式。当数据采用张量格式后,可以通过在 2.1节 中引入的那些张量函数来进一步操作。

import torch

x, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
x, y

输出:

(tensor([[3., 1., 0.],
         [2., 0., 1.],
         [4., 0., 1.],
         [3., 0., 1.]], dtype=torch.float64),
 tensor([127500, 106000, 178100, 140000]))

Note:inputs就是前面的房间号(NumRooster)、巷子(Alley)这些,而outputs就是价格price

2.2.4. 小结

像庞大的 Python 生态系统中的许多其他扩展包一样,pandas 可以与张量兼容。

插值和删除可用于处理缺失的数据。

2.2.5. 练习

创建包含更多行和列的原始数据集。

删除缺失值最多的列。

将预处理后的数据集转换为张量格式。

作业:

# 1、创建原始数据集
import os
p_datafile = os.path.join('..', 'data', 'house.csv')
with open(p_datafile, 'w') as f:
    f.write('NumRoos,Alley,Size,Garden,Price\n')
    f.write('NA,Pave,100,Yes,127500\n')
    f.write('2,NA,200,Yes,187500\n')
    f.write('3,NA,150,No,155500\n')
    f.write('NA,NA,90,NA,100500\n')
    f.write('4,Pave,120,Yes,137500\n')
import pandas as pd

data1 = pd.read_csv(p_datafile)
data1

输出:

NumRoos	Alley	Size	Garden	Price
0	NaN	Pave	100	Yes	127500
1	2.0	NaN	200	Yes	187500
2	3.0	NaN	150	No	155500
3	NaN	NaN	90	NaN	100500
4	4.0	Pave	120	Yes	137500

Note:处理缺失值

  • df.isnull()#是缺失值返回True,否则范围False
  • df.isnull().sum()#返回每列包含的缺失值的个数
  • df.dropna()#直接删除含有缺失值的行
  • df.dropna(axis = 1)#直接删除含有缺失值的列
  • df.dropna(how = ‘all’)#只删除全是缺失值的行
  • df.dropna(thresh = 4)#保留至少有4个缺失值的行
  • df.dropna(subset = [‘C’])#删除含有缺失值的特定的列
  • dddf = ddf.dropna(subset=[‘jie_num’],axis=0)#删除含有缺失值的特定的行
  • datanota = AData[AData[‘marital’].notna()]#删除某列中含有缺失值的行

* df.dropna()的Parameters说明:

DataFrame.dropna(axis=0, how=‘any’, thresh=None, subset=None, inplace=False)

  • axis 0为行 1为列,default 0,数据删除维度
  • how {‘any’, ‘all’}, default ‘any’,any:删除带有nan的行;all:删除全为nan的行
  • thresh int,保留至少 int 个非nan行
  • subset list,在特定列缺失值处理
  • inplace bool,是否修改源文件

End

data1.isna().sum()# 返回每列包含的缺失值的个数

输出:

NumRoos    2
Alley      3
Size       0
Garden     1
Price      0
dtype: int64
# 2、删除缺失值最多的列
data1 = data1.dropna(axis=1, thresh=max(data1.isna().sum()))
# data1.dropna(axis=1, thresh=3)# 将在列的方向上三个为NaN的项删除
data1 = data1.fillna(data1.mean())# 将数值的空值填充为已有数值的平均值
data1

输出:

	NumRoos	Size	Garden	Price
0	3.0	100	Yes	127500
1	2.0	200	Yes	187500
2	3.0	150	No	155500
3	3.0	90	NaN	100500
4	4.0	120	Yes	137500
input1, output1 = data1.iloc[:, 0:3], data1.iloc[:,3]
input1, output1

输出:

(   NumRoos  Size Garden
 0      3.0   100    Yes
 1      2.0   200    Yes
 2      3.0   150     No
 3      3.0    90    NaN
 4      4.0   120    Yes,
 0    127500
 1    187500
 2    155500
 3    100500
 4    137500
 Name: Price, dtype: int64)
input1 = pd.get_dummies(input1, dummy_na=True) # 按值将Garden分为3列
input1

输出:

NumRoos	Size	Garden_No	Garden_Yes	Garden_nan
0	3.0	100	0	1	0
1	2.0	200	0	1	0
2	3.0	150	1	0	0
3	3.0	90	0	0	1
4	4.0	120	0	1	0
# 3、将其转换为张量格式
import torch 

a, b = torch.tensor(input1.values), torch.tensor(output1.values)
a, b

输出:

(tensor([[  3., 100.,   0.,   1.,   0.],
         [  2., 200.,   0.,   1.,   0.],
         [  3., 150.,   1.,   0.,   0.],
         [  3.,  90.,   0.,   0.,   1.],
         [  4., 120.,   0.,   1.,   0.]], dtype=torch.float64),
 tensor([127500, 187500, 155500, 100500, 137500]))

torch.Tensor和torch.tensor的区别

在Pytorch中,Tensor和tensor都用于生成新的张量。

a = torch.Tensor([1, 2])
a

a=torch.tensor([1,2])
a

首先我们从根源上来看看torch.Tensor()和torch.tensor()区别。

torch.Tensor
torch.Tensor()是Python类,更明确的说,是默认张量类型torch.FloatTensor()的别名,torch.Tensor([1,2]) 会调用Tensor类的构造函数__init__,生成单精度浮点类型的张量。

a=torch.Tensor([1,2])
a.type()

torch.tensor()

torch.tensor()仅仅是Python的函数,函数原型是:

torch.tensor(data, dtype=None, device=None, requires_grad=False)

其中data可以是:list, tuple, array, scalar等类型。
torch.tensor()可以从data中的数据部分做拷贝(而不是直接引用),根据原始数据类型生成相应的torch.LongTensor,torch.FloatTensor,torch.DoubleTensor。

import numpy as np 
a = torch.tensor([1, 2])
a.type()

输出:

'torch.LongTensor'
b = torch.tensor([1., 2.])
b.type()

输出:

'torch.FloatTensor'
c = np.zeros(2, dtype=np.float64)
c = torch.tensor(c)
c.type()

输出:

'torch.DoubleTensor'
a, b=torch.Tensor(1), torch.Tensor([1])
a, b

输出:

(tensor([1.4013e-45]), tensor([1.]))

前者的标量1是作为size传入的,后者的向量1是作为value传入的

# astype函数用于array中数值类型转换
x = np.array([1, 2, 2.5])
x.astype(int)

输出:

array([1, 2, 2])

更多见:深入浅出之dtype( )和astype( )函数:点这

若有不当之处,请指教!更多资料请关注【公z号:龙一的编程life】

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到