Python numpy数组扩展效率问题

Numpy库的ndarray数组可以方便地进行各种多维数据处理工作

可是它最大的缺点就是不可动态扩展——“NumPy的数组没有这种动态改变大小的功能,numpy.append()函数每次都会重新分配整个数组,并把原来的数组复制到新数组中。”(引用自http://blog.chinaunix.net/uid-23100982-id-3164530.html

场景:

今天用ndarray处理 42000 条数据时,就遇到了数组扩展的效率问题

文件名:train.csv(后附下载)

文件大小:73.2MB

文件格式:.csv

文件数据:42001 * 785

文件说明:第一行为标题栏,忽略;第一列为样本标签栏

目标:读取所有数据,样本值存入一个矩阵,样本标签存入另一个矩阵

方式1:

我首先想到的是 ndarray.vstack() 方法,它的作用是合并两个矩阵。思路是,先新建一个只有一行的ndarray,然后每次按行读取文件,将读到的数据与原矩阵合并。最后构成42000行的矩阵数据。

代码:

from numpy import *
import time

DIM = 28

def img2matrix(filename):
    start_time = time.time()

    fr = open(filename)

    #drop the header
    fr.readline()

    return_mat = array(fr.readline().strip().split(','))[1::]
    labels = array(['vector[0]'])

    training_num = 0

    for line in fr.readlines():
        vector = line.strip().split(',')
        labels = hstack((labels, array([vector[0]])))
        return_mat = vstack((return_mat, vector[1::]))
        training_num += 1
        print training_num

    end_time = time.time()
    print end_time - start_time

    return return_mat, labels, training_num

结果:

1096.56099987 #约合18分钟

原因分析:

经过检查,ndarray.vstack() 是本程序的性能瓶颈。这时由于该函数的工作原理是将所有return_mat的数据与vector的数据复制出来,重新创建一个新的矩阵写入,因此相当地耗费时间。运行时也容易观察到随着return_mat的扩大,程序运行越来越慢(将training_num输出,一开始上千地跳,后来几百,后来几十,后来几个……)。

下面是github上 vstack的源代码,_nx.concatenate的源代码没找到、、、哪位大神找到了告诉一下~

def vstack(tup):
    """
    Stack arrays in sequence vertically (row wise).

    Take a sequence of arrays and stack them vertically to make a single
    array. Rebuild arrays divided by `vsplit`.

    Parameters
    ----------
    tup : sequence of ndarrays
        Tuple containing arrays to be stacked. The arrays must have the same
        shape along all but the first axis.

    Returns
    -------
    stacked : ndarray
        The array formed by stacking the given arrays.

    See Also
    --------
    hstack : Stack arrays in sequence horizontally (column wise).
    dstack : Stack arrays in sequence depth wise (along third dimension).
    concatenate : Join a sequence of arrays together.
    vsplit : Split array into a list of multiple sub-arrays vertically.

    Notes
    -----
    Equivalent to ``np.concatenate(tup, axis=0)`` if `tup` contains arrays that
    are at least 2-dimensional.

    Examples
    --------
    >>> a = np.array([1, 2, 3])
    >>> b = np.array([2, 3, 4])
    >>> np.vstack((a,b))
    array([[1, 2, 3],
           [2, 3, 4]])

    >>> a = np.array([[1], [2], [3]])
    >>> b = np.array([[2], [3], [4]])
    >>> np.vstack((a,b))
    array([[1],
           [2],
           [3],
           [2],
           [3],
           [4]])

    """
    return _nx.concatenate([atleast_2d(_m) for _m in tup], 0)

方式2:

既然一行行扩展太慢,那干脆来点儿暴力的,一次性把 return_mat 大小建好,再改改里面的数据即可。

代码:

from numpy import *
import time

DIM = 28

def img2matrix(filename):
    start_time = time.time()

    fr = open(filename)

    training_num = len(fr.readlines())-1
    return_mat = zeros((training_num, DIM*DIM))
    labels = array(['vector[0]'])

    index = 0
    fr.seek(0, 0)
    # drop the header
    fr.readline()
    for line in fr.readlines():
        vector = line.strip().split(',')
        labels = hstack((labels, array([vector[0]])))
        return_mat[index, :] = vector[1::]
        index += 1

    end_time = time.time()
    print end_time - start_time

    return return_mat, labels, training_num

结果:

7.63100004196 #约合 7.6秒

原因分析:

可以看出,ndarray的“肚量”还是挺大,一个 42000 * 784 的矩阵创建起来毫无压力。至于具体有多大,以及超过这个大小是怎么处理?可以参考StackOverflow的帖子: Very
large matrices using Python and NumPy

测试数据下载地址:https://www.kaggle.com/c/digit-recognizer/data  欢迎同志加入我的 Kaggle 项目组 :)

Python numpy数组扩展效率问题,布布扣,bubuko.com

时间: 2024-10-21 12:53:48

Python numpy数组扩展效率问题的相关文章

Python Numpy 数组扩展 repeat和tile

numpy.repeat 官方文档 numpy.repeat(a, repeats, axis=None) Repeat elements of an array. 可以看出repeat函数是操作数组中的每一个元素,进行元素的复制. 例如: >>> a = np.arange(3) >>> a array([0, 1, 2]) >>> np.repeat(a, 2) array([0, 0, 1, 1, 2, 2]) >>> a =

python numpy数组中的复制问题

vector = numpy.array([5, 10, 15, 20]) equal_to_ten_or_five = (vector == 10) | (vector == 5) vector[equal_to_ten_or_five] = 50 print(vector) 第一次看到这个的时候一脸懵逼,后来分析了下懂了下面记录下,方便下次看看 第一行分析:结果5, 10, 15, 20 第二行分析:vector == 10 数组和值比对获得结果是每个元素和这个数比较生成相应的bool数组

Python Numpy数组的读入、存储操作

从文件中加载ndarray数组 从文本文件中加载ndarray数组 np.loadtxt >>> np.loadtxt(textfile) # textfile是文本文件 从.npy或者.npz文件中加载ndarray数组np.load 如果是.npy结尾的文件,则返回单个ndarray数组 如果是.npz结尾的文件,则返回一个字典类型对象,{filename: array} >>> np.load(textfile) # textfile是.npz或.npy结尾的二进

numpy数组和python数组的区别

1.numpy数组创建时是固定大小,python数组(list)是动态的.更改ndarray的大小将创建一个新数组并删除原来的数组. 2.元素类型区别. NumPy数组中的元素都需要具有相同的数据类型,因此在内存中的大小相同. python的List可以存放不同类型的元素. 例外情况:Python的原生数组里包含了NumPy的对象的时候,这种情况下就允许不同大小元素的数组. 3.数学操作执行效率高于原生python 4.越来越多的基于Python的科学和数学软件包使用NumPy数组 原文地址:h

【Python实战15】NumPy数组的创建

NumPy提供了一个N维数组对象,即:ndarray.ndarray是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的. 创建ndarray数组 创建数组最简单的方式就是使用array函数,它接受一切序列型的对象,然后产生一个新的含有传入数据的NumPy数组.如下: 嵌套的序列将会被转换为一个多为数组: 除非显示的说明,np.array会尝试为新建的这个数组推断出一个较为合适的数据类型,我们可以通过dtype来进行查看,比如上面刚建立的数组类型为:int32类型:另,我们可以

Python中numpy 数组的切片操作

Python中numpy 数组的切片操作简介取元素 X[n0,n1]切片 X[s0:e0,s1:e1]切片特殊情况 X[:e0,s1:]示例代码输出结果简介X[n0,n1]是通过 numpy 库引用二维数组或矩阵中的某一段数据集的一种写法.类似的,X[n0,n1,n2]表示取三维数组,取N维数组则有N个参数,N-1个逗号分隔.以二维数组为例: import numpy as npX = np.array([[0,1,2,3],[10,11,12,13],[20,21,22,23],[30,31,

Python NumPy学习总结

一.NumPy简介 其官网是:http://www.numpy.org/ NumPy是Python语言的一个扩充程序库.支持高级大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库.Numpy内部解除了Python的GIL(全局解释器锁),运行效率极好,是大量机器学习框架的基础库! 关于GIL请参考博客:http://www.cnblogs.com/wj-1314/p/9056555.html NumPy的全名为Numeric Python,是一个开源的Python科学计算库,它包括

python numpy教程

python numpy教程 2014-08-10 22:21:56 分类: Python/Ruby 先决条件 在阅读这个教程之前,你多少需要知道点python.如果你想重新回忆下,请看看Python Tutorial. 如果你想要运行教程中的示例,你至少需要在你的电脑上安装了以下一些软件: Python NumPy 这些是可能对你有帮助的: ipython是一个净强化的交互Python Shell,对探索NumPy的特性非常方便. matplotlib将允许你绘图 Scipy在NumPy的基础

NumPy数组基本的索引和切片

对一维数组来说,NumPy数组的索引切片与Python列表的功能差不多: >>> arr array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> arr[3] 3 >>> arr[2:6] array([2, 3, 4, 5]) >>> arr[3:] array([3, 4, 5, 6, 7, 8, 9]) 但是,特别注意的是,如果要将一个标量值赋值给一个切片,这个修改会直接反映到源数组上(即使你已经新建