准备一个矩阵在Python中返回有什么优势?

3
这是《机器学习实战》一书中的代码。源代码

传递给dataSet的是一个m×3的数组(datingTestSet2.txt可以在上级目录中找到。)
我的问题是:
准备返回矩阵有什么优势吗?(节省内存?)
如果我不准备矩阵,会出错吗?(似乎不会。)
from numpy import *
def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet)) # prepare matrix to return(It's my own comment, not in the source code. )
    # Because there is a similar code before it, 
    # I think it should be the same meaning. Or any means else?
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m,1))
    normDataSet = normDataSet/tile(ranges, (m,1))   #element wise divide
    return normDataSet, ranges, minVals

3
那是书上的确切代码吗?如果是,你所问的那行代码是多余的,因为在后面的两行中normDataSet已经被绑定到其他东西了。(像pyflakes这样的检查工具会标记这行代码。) - Mark Dickinson
@Mark Dickinson 是的,没错。而且这就是源代码。链接 我认为作者是有意为之,或者这是一个好的程序风格。 - Vansiee
不是的。正如你所怀疑的那样,该行没有价值(或可能有负面价值)。这绝对不是良好的程序风格。也许作者打算将下一个normDataSet分配作为切片分配,这种情况下,“准备矩阵”行可能是有意义的。 - Mark Dickinson
在您提供的代码中,并没有出现“准备返回矩阵”的注释。它只出现在完全不同的一行上,而且有一个实际的目的。这个赋值似乎是由于错误而被遗留下来的。 - user2357112
@user2357112 抱歉。但是如果这段代码不是在准备返回一个矩阵,它的意思是什么? - Vansiee
@Vansiee:就像我说的那样,似乎只是因为疏忽而被留下来了。 - user2357112
2个回答

2
没有优势。在您展示的代码中,对normDataSet进行的第一次赋值没有持久影响,因为两行之后有第二个对normDataSet的赋值。此时,曾经绑定到normDataSetzeros数组对象的引用计数达到零,并且旧数组会立即被垃圾回收。(当然,这是假设使用CPython的情况,但编写本文时,Python的替代实现中没有一个完全支持NumPy。)
我猜这只是作者犯下的一个简单(但相对无害)的错误。建议提交一个bug报告以便修复。
顺便说一句,术语上的小问题:normDataSet是一个数组,而不是一个矩阵。这很重要,因为NumPy确实有一个matrix类型,其在乘法、除法和指数运算上的行为与常规的array不同。

关于数组和矩阵的评论非常好。我只想补充一点,使用numpy.matrix类型是一个非常糟糕的想法,因为它可能导致难以捕捉的错误,因为它的类型是“传染性”的。也就是说,在代码中的一个地方使用它可能会使得在某些其他不相关的代码片段中进行矩阵运算而不是数组运算。更好的方法是使用numpy.dot()或者Python 3.5+的(神送的)矩阵运算符@ - Hannes Ovrén
@HannesOvrén:同意 - 有许多理由不使用 numpy.matrix 。你提到的“感染”,它破坏了Liskov替换原则,它缺乏对一些基本操作的直接支持(例如, large_matrix.min() 首先将 large_matrix 转换为一个数组,做一个完整的拷贝!)“ @”很好,但不幸的是,对于许多企业Python用户来说,等待Python 3.5会是一个漫长的等待。 :-( - Mark Dickinson

1
除了初始化normDataSet是不必要的外,它根本不需要。您可以直接修改dataSet指向的数组,而不会影响传入的数组。
总体上,代码过于冗长复杂,没有充分利用numpy的功能。我不知道在numpy中是否有一个内置函数将数组重新归一化为[0,1]范围,但可以使用numpy数组上的元素操作轻松完成。
def autoNorm(dataSet):
    minVals = dataSet.min(0)
    ranges = dataSet.max(0) - minVals
    dataSet = (dataSet-minVals) / ranges
    return dataSet, ranges, minVals

对不起,数据集是一个 m*3 的数组。我忘记说明了。 - Vansiee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接