NumPy入门完全解读(上)

本文提要:本文将会讲解NumPy中最基本的操作:如何创建多维数组。
后续文章安排:将使用NumPy和其他相关库完成一个机器学习的入门程序——构建简易神经网络实现Logistic Regression。


学习理由

当前流行的机器学习或神经网络框架是PytorchTensorflow,那么为什么我们还需要花精力在NumPy呢?一个重要的理由是——为了方便入门,当然这是一条强调夯实基础的路径。

为什么这么说呢?NumPy中的基本数据单元是齐次多维数组或n维数组,从NumPy的最基本类ndarray可以看出,而Pytorch中的基本数据单元是张量。数组往上说是矩阵,不管多少维的矩阵,毕竟是矩阵,只要学了高数就基本可以理解,但是张量,除非学习过如工程力学方面的知识会有很深的认识外,可能就只能把它当做矩阵的更高一个层次的数据表示去理解了。

同时,在NumPy和Pytorch在函数构造上有大量重叠,也就是Pytorch的函数在很大程度上沿用了NumPy中的构造思路。这些都导致,NumPy是我们学习Pytorch框架以及其他机器学习理论前必须攻克的前头阵地。

一、NumPy是什么?

要弄清楚这个问题,我想你可以前往NumPy做详细了解。

import numpy as np # 后面直接使用np
print(np.__version__) # 查看numpy的版本

二、创建多维数组

入门NumPy最主要的就是熟悉NumPy中都有哪些基本操作,而要想进行这些操作,一个绝对逃不掉的操作就是把这样一个基于NumPy的数据结构或类实例构建出来,在NumPy中这样的类叫做ndarray(我们给它一个中文名就叫n维数组)。

主要可以分为以下三种创建数组的方式:

  1. 从现有的数据创建
  2. 从形状或值创建
  3. 从数值范围创建

在介绍创建数组的同时,我们还需要了解ndarray的一些常用属性,以及如何打印这样的n维数组

谈到python中的类,一般有实例方法、实例属性、类方法和类属性,这里当然是实例属性。

从现有的数据创建

np.array(object,dtype=None)

  • object: array_like,类似于数组的对象。如果object是标量,则返回包含object的0维数组
  • dtype: data-type,数组所需的数据类型。如果没有给出,会从输入数据推断数据类型
  • 创建一个数组对象并返回(ndarray实例对象)
array0 = np.array(3) # 0维:标量
print(array0)
array1 = np.array([1,2,3]) # 1维
print(array1)
array2 = np.array([[1,3,5],[4,6,9]]) # 2维
print(array2)     # 嵌套列表
lis = [[[1,3,5],[4,6,9.]], # 3维
        [[2,3,4],[11,21,23]]]# 列表的多层嵌套
array3 = np.array(lis) 
print(array3)
lis4 = [[[[1,3,5],[4,6,9]], # 4维
        [[2,3,4],[11,21,23]]],
        [[[1,3,5],[4,6,9]],
        [[2,3,4],[11,21,23]]]]
array4 = np.array(lis4) 
print(array4)

我们先来解释np.array的使用说明:

  1. 类似于数组的对象,可以就是一个n维数组,也可以是列表以及列表的嵌套,也可以是元组以及元组的嵌套,还可以是列表和元组的相互嵌套,但是必须要和矩阵一样的有完整的行和列。
  • 正确✅:
com = [(1,2,3),[2,3,4]]
arr = np.array(com)
print(arr)
  • 错误❌:
com = [(1,2,3),[2,3,4],(3,4,5,6)]
arr = np.array(com)
print(arr)
  • 解释器会出现传值错误:
    ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (3,) + inhomogeneous part.
    翻译:用序列设置数组元素。请求的数组在1维之后具有不均匀的形状。检测形状为(3,)+非均匀部分。
  1. 数据类型就是int,float等等,在NumPy中的数据类型有很多。在不指定dtype的时候,当解释器看到你给的数据中有小数点,就会默认设定成np.float64,当没有看到小数点,就会默认设定成np.int32。提取ndarray的数据类型,即读取实例对象的dtype属性。
arr = np.array([[1,2,3],[4,5,6]])
print(arr.dtype) # int32
arr = np.array([[1,2,3],[4,5,6.]])
print(arr.dtype) # float64
  1. 以下面的四维数组为例解读创建出来的数组对象:
lis4 = [[[[1,3,5],[4,6,9]], # 4维
        [[2,3,4],[11,21,23]]],
        [[[1,3,5],[4,6,9]],
        [[2,3,4],[11,21,23]]]]
array4 = np.array(lis4) 
print(array4)

[[[[ 1 3 5]
[ 4 6 9]]
[[ 2 3 4]
[11 21 23]]]
[[[ 1 3 5]
[ 4 6 9]]
[[ 2 3 4]
[11 21 23]]]]

观察发现,数组对象和列表对象很相似,但是有一点不同,数组对象中没有任何的逗号做分隔。此外,这个数组含有四层方括号与嵌套的列表层数一致,后面我们可以知道也与数组的维度数一致。

为了更好地分析这个数组,我们可以先查看一下它的形状:

print(array4.shape) # (2, 2, 2, 3)

返回的结果是一个元组对象,我们先数一数这个元组共有多少项,共有4项,其实这就对应了数组的维度数或者轴数。使用下面的命令来查看数组的维度数:

print(array4.ndim) # 4

可见数组的确是四维数组。而四维数组由三维数组构成,三维数组由二维数组构成,二维数组由一维数组构成,一维数组由标量构成。从左向右分析上面的元组对象,我们知道这个数组中有2个三维数组,一个三维数组下有2个二维数组,一个二维数组下有2个一维数组,一个一维数组下有3个标量。其中一个三维数组可以用下面的示意图表示。
数组立体图

可以按照图中的坐标系统把数据排列到立方体中,即在(0,0,0)立方体中放入数字1,那么第一层第一行就是[1,3,5],第二层就是[4,6,9],以此类推;当然也可以自己规定自己的坐标系统将数据排列进去。


未来为了方便观察多维数组,我设计了一个简单的matlab程序,借助matlab中的图形窗口可以直观的看到数组的表现形式。这里用真实的三维物理世界为基础,也可以展现二维,将层数设计为1即可,也可以展现一维,将层数设计为1并将行数设计为1即可,当然也可以展现四维,只需要绘制出多个图形即可。

Lz = 2;  % 层数
Lx = 2;  % 行数
Ly = 3;  % 列数

% 定义坐标范围
x = 0:1:Lx;
y = 0:1:Ly;
z = 0:1:Lz;

% 生成每层的颜色(Lz种不同颜色)
colors = hsv(Lz);  % 可替换为jet(Lz)、spring(Lz)等其他配色

% 绘制立体表面
figure;

% 绘制上下底面(与最上层和最下层统一)
[X, Y] = meshgrid(x, y);
surf(X, Y, z(1)*ones(size(X)), 'FaceColor', colors(1,:), 'EdgeColor', 'k'); hold on;  % 底面
surf(X, Y, z(end)*ones(size(X)), 'FaceColor', colors(end,:), 'EdgeColor', 'k'); hold on;  % 顶面

% 按层绘制侧面(每层颜色统一,不同层颜色不同)
for k = 1:Lz
    % 当前层的z范围
    z_layer = z(k:k+1);
    
    % 左面(y=y(1))- 使用第k层颜色
    [X, Z] = meshgrid(x, z_layer);
    Y = y(1) * ones(size(X));
    surf(X, Y, Z, 'FaceColor', colors(k,:), 'EdgeColor', 'k'); hold on;
    
    % 右面(y=y(end))- 使用第k层颜色
    [X, Z] = meshgrid(x, z_layer);
    Y = y(end) * ones(size(X));
    surf(X, Y, Z, 'FaceColor', colors(k,:), 'EdgeColor', 'k'); hold on;
    
    % 前面(x=x(1))- 使用第k层颜色
    [Y, Z] = meshgrid(y, z_layer);
    X = x(1) * ones(size(Y));
    surf(X, Y, Z, 'FaceColor', colors(k,:), 'EdgeColor', 'k'); hold on;
    
    % 后面(x=x(end))- 使用第k层颜色
    [Y, Z] = meshgrid(y, z_layer);
    X = x(end) * ones(size(Y));
    surf(X, Y, Z, 'FaceColor', colors(k,:), 'EdgeColor', 'k'); hold on;
end

% 设置图形属性
xlabel('行数');
ylabel('列数');
zlabel('深度');
title('分层着色的数组立体图');
grid on;
axis equal;
view([Lx, Ly, Lz]);  % 设置3D视角

后续文章中将会补充剩下的创建数组的方式,敬请期待!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值