python中那些对数组维度处理的奇技淫巧

2020-04-02  本文已影响0人  不分享的知识毫无意义

python作为数据科学中最受欢迎的编程语言,它的优势就在于对数据的转换,还可以灵活的处理多维数据。下面我们就来看看各种包里边的那些对数据维度操作的函数。
不放官网解释,以通俗语言来解释,先写再整理。要是各位看官想具体了解每个方法,可以逐个百度。

1.numpy

import numpy as np
a = np.arange(15).reshape(3,5)
a.reshape(-1,3)
#输出
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]])
a.resize(5,3)
#没有输出,直接改变a
注意resize不接受负数作为参数传递
#第一种情况
import numpy as np
arr1 = np.array([[0, 0, 0],[1, 1, 1],[2, 2, 2], [3, 3, 3]])  
arr2 = np.array([1, 2, 3]) 
arr1+arr2
#输出:
array([[1, 2, 3],
       [2, 3, 4],
       [3, 4, 5],
       [4, 5, 6]])
#解释:arr1二维(4,3),arr2一维(3,)后缘维度相同,即倒数第一个维度相同都为3可以自动扩充,进行相加。
#第二种情况
arr1 = np.array([[0, 0, 0],[1, 1, 1],[2, 2, 2], [3, 3, 3]])  #arr1.shape = (4,3)
arr2 = np.array([[1],[2],[3],[4]])
arr1+arr2
#输出:
array([[1, 1, 1],
       [3, 3, 3],
       [5, 5, 5],
       [7, 7, 7]])
#解释:arr1二维(4,3)arr2二维(4,1),满足维度相同,且有一个数组维度为1的条件,自动将arr2扩充为二维。
arr = np.array([[1,2,3],[3,4,5]])
arr_new = np.expand_dims(arr, axis=2)
arr_new.shape
#输出:
(2, 3, 1)
#解释,原来的(2,3)维度不变,变成(2,3,1)的维度形式,数组本身发生了改变
import numpy as np
a = np.arange(9).reshape(3,3)
np.tile(a,2)
#输出:
array([[0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [6, 7, 8, 6, 7, 8]])
np.tile(a,(2,2))
#输出:
array([[0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [6, 7, 8, 6, 7, 8],
       [0, 1, 2, 0, 1, 2],
       [3, 4, 5, 3, 4, 5],
       [6, 7, 8, 6, 7, 8]])
a=np.arange(12).reshape(3,4)
a.flatten()
a.ravel()
输出:
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
a = np.arange(12).reshape(2,2,3)
输出:
array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])
a.transpose((2,1,0))
输出:
array([[[ 0,  6],
        [ 3,  9]],

       [[ 1,  7],
        [ 4, 10]],

       [[ 2,  8],
        [ 5, 11]]])
解释:
因为维度要对齐,其实就是现有维度的两两组合。
a = np.arange(10).reshape(1,1,10)
print(a.shape)
输出:(1, 1, 10)
print(a.squeeze().shape)
输出:(10,)
x = np.array([[0, 1, 2, 3],
              [0, 1, 2, 3],
              [0, 1, 2, 3],
              [0, 1, 2, 3]])
y = np.array([[0, 0, 0, 0],
              [1, 1, 1, 1],
              [2, 2, 2, 2],
              [3, 3, 3, 3]])
X,Y = np.meshgrid(x,y)
print(X)
print(Y)
#输出太长了,自己打出来看吧

有了numpy的维度处理基础知识,其他任何框架的维度转换基本就是这些方法的转换,有时候会有一些新方法出现,但大抵的思路都是差不多的。

2.pytorch

pytorch的维度变化和numpy有区别,需要注意一下。

import torch as t
t1 = t.Tensor([[1,2],[3,4]])
t1.view(4,)
输出:
tensor([1., 2., 3., 4.])
import torch as t
t1 = t.Tensor([[1,2],[3,4]])
print(t1)
t.gather(t1, dim=0, index=t.LongTensor([[0,1],[0,1]]))
#输出
tensor([[1., 4.],
        [1., 4.]])
#解释
#dim=0横向,比如第一个[0,1]中的就是第2行第2列

注意:index需要是pytorch中的LongTensor数据类型,Tensor都不可以。

import torch
a = torch.Tensor([[[1, 2, 3], [4, 5, 6]]])
b = a.view(-1,3,2)
print(b.size())
#输出:torch.Size([1, 3, 2])
b1 = b.squeeze(1)
print(b1.size())
#输出:torch.Size([1, 3, 2])
b2 = b.squeeze(0)
print(b2.size())
#输出:torch.Size([3, 2])
b3 = b.squeeze()
print(b3.size())
#输出:torch.Size([3, 2])

unsqueeze就是在指定维度增加一个维度1。

b.unsqueeze(2).size()
#输出:torch.Size([1, 3, 1, 2])
b.size()
#输出:torch.Size([1, 3, 2])
torch.transpose(b,2,1).size()
#输出:torch.Size([1, 2, 3])
b.size()
#输出:torch.Size([1, 3, 2])
b.permute(2, 0, 1).size()
#输出:torch.Size([2, 1, 3])
x = torch.Tensor([[1], [2], [3]])
x.size()
#输出:torch.Size([3, 1])
x.expand(3,4).size()
#输出:torch.Size([3, 4])
 x.repeat(3,4).size()
#输出: torch.Size([9, 4])

3.tensorflow

tensorflow的维度变化函数和numpy基本是一样的,reshape,transpose,squeeze函数是经常使用的方法,只不过前缀变为tf,处理的数据类型也变为张量了。

import tensorflow as tf
tf.__version__
a = tf.convert_to_tensor([[1,1],[1,1]])
a.shape
#输出:TensorShape([2, 2])
a.ndim
#输出:2
a = tf.random.normal([4, 28, 28, 3])
tf.reshape(a, [4, 28*28, 3]).shape   
tf.reshape(a, [4, -1, 3]).shape 
#输出都是TensorShape([4, 784, 3])
a = tf.random.normal([4, 28, 28, 3]) 
a.shape   # TensorShape([4, 28, 28, 3])
tf.transpose(a, perm=[0,3,1,2]).shape   
#输出:TensorShape([4, 3, 28, 28])
a = tf.ones([4,35,10])
a.shape   
# 输出:TensorShape([4, 35, 10])
tf.expand_dims(a, axis=0).shape
#输出:TensorShape([1, 4, 35, 10])
tf.expand_dims(a, axis=0).shape 
a = tf.ones([1,4,35,10])
tf.squeeze(a).shape
#输出:TensorShape([4, 35, 10])
a = tf.ones([4,5,6])
b = tf.fill([6,4], 2.)
bb = tf.broadcast_to(b, [4,6,4])
(a@bb).shape 
#输出:TensorShape([4, 5, 4])
t1 = tf.convert_to_tensor([[1, 2, 3], [4, 5, 6]])
t2 = tf.convert_to_tensor([[7, 8, 9], [10, 11, 12]])
tf.concat([t1, t2], 0)  # [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
tf.concat([t1, t2], 1)
#输出:
<tf.Tensor: id=35, shape=(2, 6), dtype=int32, numpy=
array([[ 1,  2,  3,  7,  8,  9],
       [ 4,  5,  6, 10, 11, 12]], dtype=int32)>

tensorflow里对维度处理的函数比较少,要是想扩展功能咋办,你可以先转化为numpy的array处理完再转换为tensor就好了。

4.keras

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Reshape
model = Sequential()
# 改变数据形状为3行4列
# 模型的第1层必须指定输入的维度,注意不需要指定batch的大小
model.add(Reshape((3, 4), input_shape=(12, )))
# 改变数据形状为6行2列
model.add(Reshape((6, 2)))
# 改变数据形状为 第2,3维为(2,2),根据数据元素数量自动确定第1维大小为3
model.add(Reshape((-1, 2, 2)))
# 改变数据形状为 第1,2维为(2,2),根据数据元素数量自动确定第3维大小为3
model.add(Reshape((2, 2, -1)))
model.summary()
#输出:
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
reshape (Reshape)            (None, 3, 4)              0         
_________________________________________________________________
reshape_1 (Reshape)          (None, 6, 2)              0         
_________________________________________________________________
reshape_2 (Reshape)          (None, None, 2, 2)        0         
_________________________________________________________________
reshape_3 (Reshape)          (None, 2, 2, None)        0         
=================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0
model = Sequential()
modle.add(Permute((2,1),input_shape=(10,64)))
#现在变为(64,10)了
上一篇 下一篇

猜你喜欢

热点阅读