Python机器学习如何处理大体量的数据?

在python机器学习项目中,处理大规模或大体量的数据集已经成为经常要面对的问题,这样的数据不适合一次性导入内存,也不可能用机器学习的方法对其进行处理;即使分批导入,如果没有好的数据管理方法,也可能导致系统运行变慢,因此在python机器学习项目中如何处理大体量或大规模的数据集就需要一些切实可行的方法,以便保证程序正常运行的情况下,尽可能的少占用内存,本文就是针对这一问题做一个简单的描述。

python中经常使用 pandas 工具包处理数据集,它也可以用来处理大体量或大规模的数据集,进行数据操控和分析;其提供的 DataFrame 结构功能也很强大,可以处理CSV、JSON、xls等格式文件,删除重复数据和进行数据清理也简便易行。

但是,DataFrame处理大体量或大规模数据还是有很多限制,下面用一个实例来说明(实例中使用的数据是 NYC Yellow Taxi 2015 dataset),导入数据后查看内存的占用情况(这里使用 psutil.virtual_memory())。

使用pandas处理大体量数据集,首先想到的方法就是数据分块(chunking data)。如果系统不是一次性需要所有的数据,那么可以把大体量的数据分成几部分,根据系统需要只导入相应的部分数据,导入多少数据取决于内存的大小。

以下实例中,对导入训练数据集占用内存的情况进行比较,分别看看切分dataframe导入数据集和不切分数据集导入数据集,占用内存的差别。

实例代码如下:

import pandas as pd
import psutil
 
# 把 dataframe 切分,导入训练数据集
memory_timestep_1 = psutil.virtual_memory()
 
data_iterator = pd.read_csv("train_2015.csv", chunksize=100000)
fare_amount_sum_chunk = 0
for data_chunk in data_iterator:
  fare_amount_sum_chunk += data_chunk['fare_amount'].sum()
 
memory_timestep_2 = psutil.virtual_memory()
 
memory_used_pd = (memory_timestep_2[3] - memory_timestep_1[3])/(1024*1024)
print("切分datafrme,导入训练数据集占用内存: %.4f MB"%memory_used_pd)
 
 
# 使用 pandas, 导入训练数据集
memory_timestep_3 = psutil.virtual_memory()
 
training_data_pd = pd.read_csv("train_2015.csv")
fare_amount_sum_pd = training_data_pd['fare_amount'].sum()
 
memory_timestep_4 = psutil.virtual_memory()
 
memory_used_pd = (memory_timestep_4[3] - memory_timestep_3[3])/(1024*1024)
print("不切分dataframe,导入训练数据集占用内存: %.4f MB"%memory_used_pd)

输出结果:

切分datafrme,导入训练数据集占用内存: 15.8164 MB
不切分dataframe,导入训练数据集占用内存: -475.5117 MB

注意:以上输出结果,是这一段代码运行两次后的结果。不同次的运行以上代码,输出结果中的数据会有差别,可能会出现负数,这跟数据本身的大小和切分情况有关。

删除dataframe中不必要的列

有时候,系统只需要dataframe中的某几个列的数据,这种情况下就没有必要把所有列的数据都导入到内存,可以使用read_csv() 的参数usecols。

实例代码如下:

import pandas as pd
import psutil
 
# 切分dataframe,导入训练数据集
memory_timestep_1 = psutil.virtual_memory()
 
columns = ['fare_amount', 'trip_distance']
data_1 = pd.read_csv("dataset/train_2015.csv", usecols=columns)
 
memory_timestep_2 = psutil.virtual_memory()
 
memory_used_pd = (memory_timestep_2[3] - memory_timestep_1[3])/(1024*1024)
print("导入一部分列的数据,占用内存: %.4f MB"%memory_used_pd)
 
 
# 使用pandas,导入训练数据集
memory_timestep_3 = psutil.virtual_memory()
 
data_2 = pd.read_csv("dataset/train_2015.csv")
 
memory_timestep_4 = psutil.virtual_memory()
 
memory_used_pd = (memory_timestep_4[3] - memory_timestep_3[3])/(1024*1024)
print("导入所有列的数据,占用内存: %.4f MB"%memory_used_pd)

输出结果如下:

导入一部分列的数据,占用内存: 48.1953 MB
导入所有列的数据,占用内存: 844.6875 MB

选择合适的数据类型

pandas一般使用的数据类型并没有考虑内存的使用效率,可以根据数据的特点改变一些数据的类型,这样能把更多的数据导入到内存。例如,数据集中的列VendorID,其值都是1或2,但是却使用了int64类型,就非常没有必要,可以把这个列的数据类型转换为布尔型,就可以大幅减少保存数据所需要的内存;另外,还可以把pickup_latitude、pickup_longitude, dropoff_latitude, dropoff_longitude从float64类型转换为float32类型,把payment_type的类型转换为分类。

实例代码如下:

import pandas as pd
from sys import getsizeof
 
data = pd.read_csv("train_2015.csv")
 
size = getsizeof(data)/(1024*1024)
print("训练数据集最初的大小:  %.4f MB"%size)
 
# 改变 VendorID 为 boolean
data.VendorID = data.VendorID.apply(lambda x: x==2)
 
# 改变 pickup_latitude, pickup_longitude, dropoff_latitude, dropoff_longitude 为 float32类型
location_columns = ['pickup_latitude','pickup_longitude',
                    'dropoff_latitude','dropoff_longitude']
data[location_columns] = data[location_columns].astype('float32')
 
# 把payment_type 改变为属类
data.payment_type = data.payment_type.astype('category')
 
size = getsizeof(data)/(1024*1024)
print("改变几个数据列的类型后的大小: %.4f MB"%size)

输出结果如下:

训练数据集最初的大小:  946.6755 MB
改变几个数据列的类型后的大小: 862.6512 MB

使用Dask 处理大体量数据

Dask 是一个并行计算库,可以与Numpy、pandas、scikit工具包结合使用,以便提高计算速度和减少占用内存;用一台多核CPU的计算机,实现并行计算。dask 的数据结构和dataframe的数据结构相似,一个 dask 由多个dataframe组成,调用一个dask相当于调用多个dataframe,dask有一套自己的协调机制。和前面的实例一样,要使用psutil.virtual_memory() 函数。

实例代码如下:

import pandas as pd
import dask.dataframe as ddf
import psutil
 
#使用 dask 导入训练数据集
memory_timestep_3 = psutil.virtual_memory()
 
training_data_ddf = ddf.read_csv("train_2015.csv")
 
memory_timestep_4 = psutil.virtual_memory()
 
memory_used_ddf = (memory_timestep_4[3] - memory_timestep_3[3])/(1024*1024)
print("使用dask导入训练数据集,占用内存:%.4f MB"%memory_used_ddf)
 
 
# 使用pandas导入训练数据集
memory_timestep_1 = psutil.virtual_memory()
 
training_data_pd = pd.read_csv("train_2015.csv")
 
memory_timestep_2 = psutil.virtual_memory()
 
memory_used_pd = (memory_timestep_2[3] - memory_timestep_1[3])/(1024*1024)
print("使用pandas导入训练数据集,占用内存: %.4f MB"%memory_used_pd)

输出结果如下:

使用dask导入训练数据集,占用内存:3.4609 MB
使用pandas导入训练数据集,占用内存: 304.2891 MB

使用 dask 和pandas之间的差别在于,dask 数据操作是一种懒惰机制,不会像pandas那样即刻执行,而是根据 dask 的任务调度读取所需要的数据到内存,并且把导入的数据使用完之后,从内存中清除,因此dask在内存受限的情况下使用效果非常好。

Python机器学习如何处理大体量的数据?

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/76326
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 2024 年 7 月 11 日 下午3:43
下一篇 2024 年 7 月 11 日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注