zoukankan      html  css  js  c++  java
  • numpy里*与dot与multiply

    一、*  , dot()   multiply()

    1, 对于array来说,(* 和 dot()运算不同, * 和 multiply()运算相同)

    *和multiply() 是每个元素对应相乘

    dot() 是矩阵乘法

    2, 对于matrix来说,(* 和 multiply()运算不同,* 和 dot()运算相同)

    * 和dot() 是矩阵乘法

    multiply()  是每个元素对应相乘

    3, 混合的时候(与矩阵同)

    multiply 为对应乘

    dot为矩阵乘法(矩阵在前数组在后时,均为一维时数组可适应,即能做矩阵乘法)

    *为 矩阵乘法(但无上述适应性)

    总结:dot为矩阵乘法multiply是对应乘* 看元素,元素为矩阵(包括含矩阵)时为矩阵乘法,元素为数组时为对应乘法

    Python 3.6.4 (default, Jan 7 2018, 03:52:16)
    [GCC 4.2.1 Compatible Android Clang 5.0.300080 ] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import numpy as np
    >>> a1=np.array([1,2,3])
    >>> a1*a1
    array([1, 4, 9])
    >>> np.dot(a1,a1)
    14
    >>> np.multiply(a1,a1)
    array([1, 4, 9])
    >>> m1 = np.mat(a1)
    >>> m1
    matrix([[1, 2, 3]])
    >>> m1*m1
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/data/data/com.termux/files/usr/lib/python3.6/site-packages/numpy-1.13.3-py3.6-linux-aarch64.egg/numpy/matrixlib/defmatrix.py", line 309, in __mul__
    return N.dot(self, asmatrix(other))
    ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
    >>> np.dot(m1,m1)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
    >>> np.multiply(m1,m1)
    matrix([[1, 4, 9]])
    >>> np.multiply(a1,m1)
    matrix([[1, 4, 9]])
    >>> np.multiply(m1,a1)
    matrix([[1, 4, 9]])
    >>> np.dot(a1,m1)
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    ValueError: shapes (3,) and (1,3) not aligned: 3 (dim 0) != 1 (dim 0)
    >>> np.dot(m1,a1)
    matrix([[14]])
    >>> a1*m1
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/data/data/com.termux/files/usr/lib/python3.6/site-packages/numpy-1.13.3-py3.6-linux-aarch64.egg/numpy/matrixlib/defmatrix.py", line 315, in __rmul__
    return N.dot(other, self)
    ValueError: shapes (3,) and (1,3) not aligned: 3 (dim 0) != 1 (dim 0)
    >>> m1*a1
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/data/data/com.termux/files/usr/lib/python3.6/site-packages/numpy-1.13.3-py3.6-linux-aarch64.egg/numpy/matrixlib/defmatrix.py", line 309, in __mul__
    return N.dot(self, asmatrix(other))
    ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
    >>> a1,m1
    (array([1, 2, 3]), matrix([[1, 2, 3]]))
    >>>

     -------------------------------------------------------------------

    当array是二维时,我们可以把它看做是矩阵(但是乘法的法则还是按照array来算)

    In [45]: a_x
    Out[45]:
    array([[1, 2, 3],
           [2, 4, 0],
           [1, 2, 1]])

    In [46]: a_y
    Out[46]: array([[-1,  1, -1]])

    先看dot

    # 这时用dot做矩阵乘法要注意:满足左边的列数等于右边的行数

    In [47]: np.dot(a_x,a_y)
    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    <ipython-input-47-3b884e90b0ef> in <module>()
    ----> 1 np.dot(a_x,a_y)

    ValueError: shapes (3,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)

    In [48]: np.dot(a_y,a_x)
    Out[48]: array([[ 0,  0, -4]])

    # 当左边的变为一维的数组时,结果还是一个二维的数组(矩阵形式)

    In [49]: a_y_ = a_y.flatten()

    In [50]: a_y_
    Out[50]: array([-1,  1, -1])

    然后还有一点很重要 np.dot(a_y_,a_y_) 可以将两个一维的数组(这时没有行列向量之说,从转置后还为本身也可以看出)直接做内积
    In [109]: np.dot(a_y_,a_y_)
    Out[109]: 3


    In [51]: np.dot(a_y,a_x)
    Out[51]: array([[ 0,  0, -4]])

    再看multiply(与*的效果一致):

    In [52]: a_y
    Out[52]: array([[-1,  1, -1]])

    In [53]: a_y_
    Out[53]: array([-1,  1, -1])

    In [54]: np.multiply(a_y,a_y_)
    Out[54]: array([[1, 1, 1]])

    In [55]: np.multiply(a_y_,a_y)
    Out[55]: array([[1, 1, 1]])

    得到结论:都是以高维的那个元素决定结果的维度。(重要)

    In [56]: np.multiply(a_y_,a_y_.T)   # 在a_y_是一维的行向量,a_y_ = a_y_.T,所以结果一样
    Out[56]: array([1, 1, 1])

    In [57]: np.multiply(a_y_,a_y.T)    # a_y 是二维的行向量,转置一下就变成二维的列向量
    Out[57]:
    array([[ 1, -1,  1],
           [-1,  1, -1],
           [ 1, -1,  1]])
    In [58]: np.multiply(a_y,a_y.T)     # 与上述效果相同
    Out[58]:
    array([[ 1, -1,  1],
           [-1,  1, -1],
           [ 1, -1,  1]])

    上面两个就是下面这俩对应元素相乘!

    In [59]: a_y
    Out[59]: array([[-1,  1, -1]])

    In [60]: a_y.T
    Out[60]:
    array([[-1],
           [ 1],
           [-1]])

    与下面这种张量积效果相同

    In [61]: np.outer(a_y,a_y)
    Out[61]:
    array([[ 1, -1,  1],
           [-1,  1, -1],
           [ 1, -1,  1]])

    In [62]: np.outer(a_y,a_y.T)     # 这时用不用转置的效果都一样
    Out[62]:
    array([[ 1, -1,  1],
           [-1,  1, -1],
           [ 1, -1,  1]])

    In [63]: np.outer(a_y_,a_y_)    # 两个一维的行向量外积的效果也一样
    Out[63]:
    array([[ 1, -1,  1],
           [-1,  1, -1],
           [ 1, -1,  1]])

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                                                                                        下面看一下 .T 和 .transpose()

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    在小于等于二维的情况下,两者效果是相同的!

    In [64]: x
    Out[64]:
    matrix([[1, 2, 3],
            [2, 4, 0],
            [1, 2, 1]])

    In [65]: a_x
    Out[65]:
    array([[1, 2, 3],
           [2, 4, 0],
           [1, 2, 1]])

    In [68]: (x.T == x.transpose()).all()     # 为矩阵时相同
    Out[68]: True

    In [70]: (a_x.T == a_x.transpose()).all()    # 为数组时相同
    Out[70]: True

    In [71]: (a_y.T == a_y.transpose()).all()   # a_y为一维数组(行向量)相同
    Out[71]: True

    In [72]: (a_y_.T == a_y_.transpose()).all() # a_y_为二维数组(行向量)也相同
    Out[72]: True

    下面才是两种区别的重点:

    当维数大于等于三时(此时只有数组了),

    T 其实就是把顺序全部颠倒过来,

    而transpose(), 里面可以指定顺序,输入为一个元组(x0,x1,x2...x(n-1) )为(0,1,2,...,n-1)的一个排列,其中n为数组维数,

    效果与np.transpose(arr, axes=(x0,x1,x2...x(n-1)) ) 相同,

        def transpose(self, *axes): # real signature unknown; restored from __doc__
            """
            a.transpose(*axes)
            
                Returns a view of the array with axes transposed.
            
                For a 1-D array, this has no effect. (To change between column and
                row vectors, first cast the 1-D array into a matrix object.)
                For a 2-D array, this is the usual matrix transpose.
                For an n-D array, if axes are given, their order indicates how the
                axes are permuted (see Examples). If axes are not provided and
                ``a.shape = (i[0], i[1], ... i[n-2], i[n-1])``, then
                ``a.transpose().shape = (i[n-1], i[n-2], ... i[1], i[0])``.
            
                Parameters
                ----------
                axes : None, tuple of ints, or `n` ints
            
                 * None or no argument: reverses the order of the axes.
            
                 * tuple of ints: `i` in the `j`-th place in the tuple means `a`'s
                   `i`-th axis becomes `a.transpose()`'s `j`-th axis.
            
                 * `n` ints: same as an n-tuple of the same ints (this form is
                   intended simply as a "convenience" alternative to the tuple form)
            
                Returns
                -------
                out : ndarray
                    View of `a`, with axes suitably permuted.
            
                See Also
                --------
                ndarray.T : Array property returning the array transposed.
            
                Examples
                --------
                >>> a = np.array([[1, 2], [3, 4]])
                >>> a
                array([[1, 2],
                       [3, 4]])
                >>> a.transpose()
                array([[1, 3],
                       [2, 4]])
                >>> a.transpose((1, 0))
                array([[1, 3],
                       [2, 4]])
                >>> a.transpose(1, 0)
                array([[1, 3],
                       [2, 4]])
            """
            pass

    这两者的源代码还是又挺大区别的,虽然意思差不多

    def transpose(a, axes=None):
        """
        Permute the dimensions of an array.
        Parameters
        ----------
        a : array_like
            Input array.
        axes : list of ints, optional
            By default, reverse the dimensions, otherwise permute the axes
            according to the values given.
        Returns
        -------
        p : ndarray
            `a` with its axes permuted.  A view is returned whenever
            possible.
        See Also
        --------
        moveaxis
        argsort
        Notes
        -----
        Use `transpose(a, argsort(axes))` to invert the transposition of tensors
        when using the `axes` keyword argument.
        Transposing a 1-D array returns an unchanged view of the original array.
        Examples
        --------
        >>> x = np.arange(4).reshape((2,2))
        >>> x
        array([[0, 1],
               [2, 3]])
        >>> np.transpose(x)
        array([[0, 2],
               [1, 3]])
        >>> x = np.ones((1, 2, 3))
        >>> np.transpose(x, (1, 0, 2)).shape
        (2, 1, 3)
        """
    return _wrapfunc(a, 'transpose', axes)

    还是看实验吧:

    In [73]: arr=np.arange(16).reshape(2,2,4)

    In [74]: arr
    Out[74]:
    array([[[ 0,  1,  2,  3],
            [ 4,  5,  6,  7]],

           [[ 8,  9, 10, 11],
            [12, 13, 14, 15]]])

    In [75]: arr.transpose((1,0,2))   # 注意这个参数不带key,不能写axes=(1,0,2),若写成这个,则报错
    Out[75]:
    array([[[ 0,  1,  2,  3],
            [ 8,  9, 10, 11]],

           [[ 4,  5,  6,  7],
            [12, 13, 14, 15]]])

    In [78]: np.transpose(arr, (1, 0, 2))  #这个参数可带key,刻写成axes=(1,0,2),若写成这个,则通过
    Out[78]:
    array([[[ 0,  1,  2,  3],
            [ 8,  9, 10, 11]],

           [[ 4,  5,  6,  7],
            [12, 13, 14, 15]]])

     

    三个维度的编号对应为(0,1,2),比如这样,我们需要拿到7这个数字,怎么办,肯定需要些三个维度的值,7的第一个维度为0,第二个维度为1,第三个3,

    即坐标轴(0,1,2)的对应的坐标为(0,1,3)所以arr[0,1,3]则拿到了7

    所以相当于把原来坐标轴[0,1,2]的转置到[1,0,2],即把之前第三个维度转为第一个维度,之前的第二个维度不变,之前的第一个维度变为第三个维度

    理解了上面,再来理解swapaxes()就很简单了,swapaxes接受一对轴编号,其实这里我们叫一对维度编号更好吧

    arr.swapaxes(2,1)  就是将第三个维度和第二个维度交换

    注意这个函数必须接受两个参数,(两个轴),不能写成元组(2,1)的形式再传入。

    In [81]: arr.swapaxes(2,1)
    Out[81]:
    array([[[ 0,  4],
            [ 1,  5],
            [ 2,  6],
            [ 3,  7]],

           [[ 8, 12],
            [ 9, 13],
            [10, 14],
            [11, 15]]])

    In [82]: arr.swapaxes((2,1))
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-82-24459d1e2980> in <module>()
    ----> 1 arr.swapaxes((2,1))

    TypeError: swapaxes() takes exactly 2 arguments (1 given)

    还是那我们的数字7来说,之前的索引是(0,1,3),那么交换之后,就应该是(0,3,1)

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  • 相关阅读:
    实验13读后感:《算法竞赛进阶指南》
    实验12图的m着色问题
    实验11哈夫曼编码
    极差 牛客-16736(单调栈,线段树)
    实验10相容问题
    实验9LCS算法
    实验8矩阵链乘法
    Array Without Local Maximums CF-1068D(计数DP)
    Save the Nature CF-1241C(二分、贪心)
    浅谈linux命令大全
  • 原文地址:https://www.cnblogs.com/cymwill/p/8364428.html
Copyright © 2011-2022 走看看