Day01-Numpy
人工智能课程
介绍人工智能课程设计,课件,资料
数据分析,机器学习,深度学习,
发展方向——计算机专业,数学专业,统计学专业
数据分析师——商务分析,与业务紧密相关,excel,sql,图标报告,
数据挖掘工程师——python,pandas,numpy,matplotlib,数据预处理,数据清洗,数据归一化,
机器学习算法工程师——sklearn,scipy,statsmodels,建模
深度学习算法工程师——TensorFlow,pytorch,caffe,计算机视觉,推荐算法,语音识别,自动驾驶,自然语言处理,
配置环境
介绍anaconda 和 pycharm 环境,演示如何新建环境,并下载第三方库
数据分析简介
什么是数据分析?
数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,提取有用信息和形成结论而对数据加以详细研究和概括总结的过程。
数据分析经典案例
(一)啤酒与尿布
沃尔玛在对消费者购物行为分析时发现,男性顾客在购买婴儿尿片时,常常会顺便搭配几瓶啤酒来犒劳自己,于是尝试推出了将啤酒和尿布摆在一起的促销手段。没想到这个举措居然使尿布和啤酒的销量都大幅增加了。
(二)数据新闻让英国撤军
2010年10月23日《卫报》利用维基解密的数据做了一篇“数据新闻”。将伊拉克战争中所有的人员伤亡情况均标注于地图之上。地图上一个红点便代表一次死伤事件,鼠标点击红点后弹出的窗口则有详细的说明:伤亡人数、时间,造成伤亡的具体原因。密布的红点多达39万,显得格外触目惊心。一经刊出立即引起朝野震动,推动英国最终做出撤出驻伊拉克军队的决定。
(三)微软数据分析成功预测奥斯卡21项大奖
2013年,微软纽约研究院的经济学家大卫•罗斯柴尔德(David Rothschild)利用数据分析技术成功预测24个奥斯卡奖项中的19个,成为人们津津乐道的话题。后来,罗斯柴尔德再接再厉,成功预测第86届奥斯卡金像奖颁奖典礼24个奖项中的21个。
数据分析的步骤:
-
定义挖掘目标
-
数据取样
- 标准
- 资料完整无缺,各类指标项齐全
- 数据准确无误,反应的都是正常(而不是异常)状态下的水平
- 相关性,可靠性,有效性
- 方式:
- 随机抽样
- 等距抽样
- 分层抽样
- 分类抽样
- 标准
-
数据探索
- 异常值分析
- 缺失值分析
- 相关性分析
- 周期性分析
- 分布分析
- 对比分析
- 统计量分析
- 贡献度分析
-
数据预处理
- 数据清洗
- 数据集成
- 数据变换
- 数据规约
-
挖掘建模
-
机器学习算法
-
深度学习算法
回归,分类,聚类
-
-
模型评价
- 模型评估指标
为什么要使⽤Python进⾏数据分析
excel —— 100M
R,MATLAB,——几 G
python —— 几十 G
分布式 —— T
- ⾃从1991年诞⽣以来,Python现在已经成为最受欢迎的动态编程语⾔之⼀。
- 近年来,由于Python的库(例如pandas和scikit-learn)不断改良,使其成为数据分析任务的⼀个优选⽅案。
- Python作为胶⽔语⾔,它能够轻松地集成C、C++以及Fortran代码。
- 解决“两种语⾔”问题,Python不仅适⽤于研究和原型构建,同时也适⽤于构建⽣产系统。
Python 库简介
介绍数据分析工具,我们课程用的是 Python 加第三方库,numpy,pandas,scipy,matplotlib等,需要用到的第三方库在环境安装手册里标黄的库。
numpy 的核心:多维数组ndarray
numpy 的特点
- NumPy是在⼀个连续的内存块中存储数据,独⽴于其他Python内置对象。NumPy的C语⾔编写的算法库可以操作内存,⽽不必进⾏类型检查或其它前期⼯作。⽐起Python的内置序列,NumPy数组使⽤的内存更少。更快更高效。
- NumPy可以在整个数组上执⾏复杂的计算,⽽不需要Python的for循环。广播机制。
什么是数组
ndarray数组示例:
import numpy as np
ary = np.array([1, 2, 3, 4, 5, 6])
print(type(ary))
'''
[1 2 3 4 5 6] <class 'numpy.ndarray'>
'''
ndarray是⼀个通⽤的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的。每个数组都有⼀个shape(⼀个表示各维度⼤⼩的元组)和⼀个dtype(⼀个⽤于说明数组数据类型的对象)。
数组在内存中的存储
元数据(metadata)
存储对目标数组的描述信息,如:dim count、dimensions、dtype、data等。
实际数据
完整的数组数据
将实际数据与元数据分开存放,一方面提高了内存空间的使用效率,另一方面减少对实际数据的访问频率,提高性能。
数组的创建
-
np.array() 和 asarray()
import numpy as np a = np.array([1, 2, 3, 4, 5, 6]) print(a) data = [[1, 2, 3, 4], [5, 6, 7, 8]] arr = np.asarray(data) print(arr)
-
np.arange(起始值(0), 终止值, 步长(1))
import numpy as np b = np.arange(1, 10) print(b)
除np.array之外,还有⼀些函数也可以新建数组。⽐如,zeros和ones分别可以创建指定⻓度或形状的全0或全1数组。empty可以创建⼀个没有任何具体值的数组。
-
np.zeros(数组shape, dtype=‘类型’)
import numpy as np c = np.zeros(10, dtype='int32') print(c, c.dtype)
-
np.ones(数组shape, dtype=‘类型’)
import numpy as np d = np.ones((2, 3), dtype='float32') print(d, d.shape, d.dtype)
-
扩展 np.zeros_like() np.ones_like()
zeros_like 和 ones_like 以另一个数组为参数,并根据其形状shape和 dtype 创建一个全 0 或 1 数组。
print(np.zeros_like(d)) print(np.ones_like(d))
-
总结:Numpy数组创建函数
函数 说明 array 将输入数据(列表、元祖、数组或其他序列类型)转换为 ndarray。要么推断出 dtype,要么特别指定 dtype。默认直接复制输入数据。 asarray 将输入转换为 ndarray。 arange 类似于内置的 range 函数,但返回的是一个 ndarray 而不是列表 ones,ones_like 根据指定的形状和 dtype 创建一个全 1 数组。ones_like 以另一个数组为参数,并根据其形状和 dtype 创建一个全 1 数组。 zeros,zeros_like 类似于ones 和 ones_like, 产生的是全 0 数组。 empty,empty_like 创建新数组,只分配内存空间但并不填充任何值 full,full_like 用 fill value 中的所有值,根据指定形状和 dtype 创建一个数组。full_like 使用另一个数组,用相同的形状和 dtype 创建
numpy 属性的基本操作
-
**数组的维度:**np.ndarray.shape 和 np.ndarray.reshape
数组对象(…, 页, 行, 列)
一维:(列)
二维:(行,列)
三维:(页, 行,列)
n 维:(…, 页, 行, 列)
import numpy as np # shape a = np.arange(12) print(a, a.shape) # 修改数组维度:reshape b = a.reshape((4,3)) print(b, b.shape)
-
**数组维度的数量:**np.ndarray.ndim
arr = np.arange(32).reshape((2, 2, 2, 4)) print(arr, arr.ndim)
-
**元素的数据类型:**np.ndarray.dtype 和 np.ndarray.astype
dtype(数据类型)是⼀个特殊的对象,它含有ndarray将⼀块内存解释为特定数据类型所需的信息。
import numpy as np arr1 = np.array([1, 2, 3], dtype=np.float64) arr2 = np.array([1, 2, 3], dtype=np.int32) print(arr1.dtype) print(arr2.dtype) # 修改数据类型:astype arr = np.array([1, 2, 3, 4, 5]) print(arr.dtype) float_arr = arr.astype(np.float64) print(float_arr.dtype)
Numpy的数据类型:
类型 类型代码 说明 int8、uint8 i1、u1 有符号和无符号的 8 位(1 个字节)整型 int16、uint16 I2、u2 有符号和无符号的 16 位(2 个字节)整型 int32、uint32 I4、u4 有符号和无符号的 32 位(4 个字节)整型 int64、uint64 I8、u8 有符号和无符号的 64 位(8 个字节)整型 float16 f2 半精度浮点数 float32 f4 或 f 标准的单精度浮点数 float64 f8 或 d 标准的双精度浮点数 float128 f16 或 g 扩展精度浮点数 complex64、complex128、complex256 c8、c16、c32 分别用两个 32 位、64 位、或 128 位浮点数表示的复数 bool ? 存储 True 和 False 值的布尔类型 object O python 对象类型 string_ S 固定长度的字符串类型(每个字符1 个字节) unicode_ U 固定长度的 unicode 类型(字节数由平台决定) numpy 的 dtype 体系:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SF8n5KQF-1605441982975)(images/image-20200306000859016.png)]
-
**数组元素的个数:**np.ndarray.size
import numpy as np ary = np.array([ [1,2,3,4], [5,6,7,8] ]) print(ary.shape) print(ary.size) # size相当于shape 中 n*m 的值
-
总结:NumPy 的数组中比较重要 ndarray 对象属性有:
属性 说明 ndarray.ndim 秩,即轴的数量或维度的数量 ndarray.shape 数组的维度,对于矩阵,n 行 m 列 ndarray.size 数组元素的总个数,相当于 .shape 中 n*m 的值 ndarray.dtype ndarray 对象的元素类型 ndarray.itemsize ndarray 对象中每个元素的大小,以字节为单位 ndarray.flags ndarray 对象的内存信息 ndarray.real ndarray元素的实部 ndarray.imag ndarray 元素的虚部 ndarray.data 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。 练习:
import numpy as np a = np.array([[1 + 1j, 2 + 4j, 3 + 7j], [4 + 2j, 5 + 5j, 6 + 8j], [7 + 3j, 8 + 6j, 9 + 9j]]) print(a.ndim) print(a.shape) print(a.size) print(a.dtype) print(a.itemsize) print(a.flags) print(a.real) print(a.imag)
数组的运算——广播机制
⼴播(broadcasting)指的是不同形状的数组之间的算术运算的执⾏⽅式。将标量值跟数组合并时就会发⽣最简单的⼴播:
import numpy as np
ary = np.array([1, 2, 3, 4, 5, 6])
print(ary)
print(ary * 3)
print(ary > 3)
print(ary + ary)
广播的原则:
如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符或其中一方的长度为 1,则认为他们是广播兼容的。广播会在缺失和(或)长度为 1 的维度上进行。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rpS5cCU3-1605441982977)(images/image-20200724184444568.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lojagd1x-1605441982979)(images/image-20200724184404084.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JDt5JeKe-1605441982980)(images/image-20200724184504246.png)]
a = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2], [3, 3, 3]])
b = np.array([1, 2, 3])
c = np.array([1, 2, 3, 4]).reshape(4, 1)
a+b
a+c
e = np.arange(24).reshape(3, 4, 2)
f = np.arange(8).reshape(4, 2)
e + f
自定义复合类型
# 自定义复合类型
import numpy as np
data = [('zs', [80, 60, 75], 19),
('ls', [99, 97, 96], 20),
('ww', [98, 98, 98], 21)]
# 第一种设置dtype的方式
a = np.array(data, dtype='U2, 3int32, int32')
print(a)
print(a[1][1])
# 第二种设置dtype的方式
a = np.array(data, dtype=[('name', 'str', 2), # 2个字符的字符串
('scores', 'int32', 3), # 3个int32的子数组
('age', 'int32',(1,))]) # 1个int32的子数组
print(a)
print(a[2]['age'])
# 第三种设置dtype的方式
a = np.array(data, dtype={
'names': ['name', 'scores', 'age'],
'formats': ['U2', '3int32', 'int32']})
print(a)
print(a[1]['name'])
补充:jupyter notebook 中设置cell 同时输出多行
# cell 同时输出多行
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
###############################
数组的变维
-
数组的重塑 reshape
import numpy as np arr = np.arange(8) print(arr) print(arr.reshape((4, 2))) # 多维数组的重塑 print(arr.reshape((4, 2)).reshape((2, 4)))
-
作为参数的形状的其中⼀维可以是 -1,它表示该维度的⼤⼩由数据本身推断⽽来。
arr = np.arange(15) print(arr.reshape((5, -1)))
-
按C顺序(按⾏)和按Fortran顺序(按列)进⾏重塑
import numpy as np # shape a = np.arange(12) print(a, a.shape) # 按C顺序(按⾏)和按Fortran顺序(按列)进⾏重塑 b = a.reshape((4,3),order="C") # 先行后列 print(b, b.shape) d = a.reshape((4,3),order="F") # 先列后行 print(d, d.shape)
C和Fortran顺序的关键区别就是维度的⾏进顺序:
C/⾏优先顺序:先经过更⾼的维度(例如,轴1会先于轴0被处理)。
Fortran/列优先顺序:后经过更⾼的维度(例如,轴0会先于轴1被处理)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RdRnBaiK-1605441982982)(images/image-20200305232818251.png)]
-
与reshape将⼀维数组转换为多维数组的运算过程相反的运算通常称为扁平化(flattening)或散开(raveling)。
-
ravel() 视图变维 对源数据进行维度改变
arr = np.arange(15).reshape((5, 3)) print(arr) print(arr.ravel())
如果结果中的值与原始数组相同,ravel不会产⽣源数据的副本。
flatten⽅法的⾏为类似于ravel,只不过它总是返回数据的副本。
-
flatten() 复制变维 不会对源数据进行改变,返回副本。
print(arr.flatten())
-
numpy.flatten() 与 numpy.ravel()的区别
首先声明两者所要实现的功能是一致的(将多维数组降位一维),两者的区别在于返回拷贝(copy)还是返回视图(view),numpy.flatten()返回一份拷贝,对拷贝所做的修改不会影响(reflects)原始矩阵,而numpy.ravel()返回的是视图(view,也颇有几分C/C++引用reference的意味),会影响(reflects)原始矩阵。
x = np.array([[1, 2], [3, 4]]) x.flatten()[1] = 100 x array([[1, 2], [3, 4]]) # flatten:返回的是拷贝 x.ravel()[1] = 100 x array([[ 1, 100], [ 3, 4]])
-
resize() 改变维度和size
给定一个数组和特定维度,将会返回一个特定维度的新数组。resize() 生成的新数组跟原数组并不共用一个内存。
当新维度超出原维度时,它会重复填充原数组的内容.
arr1 = np.arange(8) arr2 = np.resize(arr1, (3, 4)) print(arr2) b = np.array([[0, 1], [2, 3]]) b.resize(3, 3) print(b)
当新维度比原维度小时,它会从原数组中读取出所需元素个数,然后按行填充.
arr3 = np.resize(arr1, (2, 2)) print(arr3)
-
看一下官网这么说
https://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html#indexing-arrays
方法 说明 ndarray.reshape
(shape[, order])Returns an array containing the same data with a new shape. ndarray.ravel
([order])Return a flattened array. ndarray.flatten
([order])Return a copy of the array collapsed into one dimension. ndarray.resize
(new_shape[, refcheck])Change shape and size of array in-place.
-
-
C/行和Fortran/列顺序
arr = np.arange(12).reshape((3, 4)) print(arr) print(arr.ravel('C')) # 先行后列 print(arr.ravel('F')) # 先列后行
数组的索引和切⽚
1.元素索引
- 一维数组
arr = np.arange(10)
print(arr)
print(arr[5])
print(arr[5:8])
# 将⼀个标量值赋值给⼀个切⽚时
arr[5:8] = 12
print(arr)
跟列表最重要的区别在于,数组切⽚是原始数组的视图。这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上。
arr_slice = arr[5:8]
arr_slice
arr_slice[1] = 12345
arr
# 切⽚[:]会给数组中的所有值赋值
arr_slice[:] = 64
arr
# 如果你想要得到的是ndarray切⽚的⼀份副本⽽⾮视图
arr[5:8].copy()
- 二维数组
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr2d
arr2d[2]
arr2d[2,2]
# 下⾯两种⽅式是等价的:
arr2d[0][2]
arr2d[0, 2]
- 三维数组
arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
arr3d
# arr3d[0]是⼀个2×3数组
arr3d[0] # 页
# 标量值和数组都可以被赋值给arr3d[0]
old_values = arr3d[0].copy()
arr3d[0] = 42
arr3d
arr3d[0] = old_values
arr3d
# arr3d[1,0]可以访问索引以(1,0)开头的那些值(以⼀维数组的形式返回)
arr3d[1, 0] # 页,行
2.切片索引(Indexing with slices):
# 一维数组
arr
arr[1:6]
# 二维数组
arr2d
arr2d[:2]
arr2d[:2, 1:]
arr2d[1, :2]
arr2d[:2, 2]
arr2d[:, :1]
# 赋值之后会怎样
arr2d[:2, 1:] = 0
arr2d
# 三维数组
arr3d
arr3d[0,:2,1:]
3.布尔型索引 (Boolean Indexing)
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
# 用numpy.random中的randn函数⽣成⼀些标准正态分布的随机数据
data = np.random.randn(7, 4)
names
data
# 进行布尔型索引
# 注意:布尔型数组的⻓度必须跟被索引的轴⻓度⼀致
names == 'Bob' # 掩码
data[names == 'Bob']
# 将布尔型数组跟切⽚、整数(整数序列)混合使用
data[names == 'Bob', 2:]
data[names == 'Bob', 3]
# 要选择除"Bob"以外的其他值,既可以使⽤不等于符号(!=),也可以通过~对条件进⾏否定
names != 'Bob'
data[~(names == 'Bob')]
# ~操作符⽤来反转条件
cond = names == 'Bob'
data[~cond]
# 选取这三个名字中的两个需要组合应⽤多个布尔条件,使⽤ &(和)、|(或)之类的布尔算术运算符
mask = (names == 'Bob') | (names == 'Will')
mask
data[mask]
# 注意:Python关键字and和or在布尔型数组中⽆效。要⽤符号 & 与 |
# 通过布尔型数组设置值
data[data < 0] = 0
data
data[names != 'Joe'] = 7
data
4.花式索引 (Fancy Indexing)
花式索引是利⽤整数数组进⾏索引。花式索引跟切⽚不⼀样,它总是将数据复制到新数组中。
arr = np.empty((8, 4))
for i in range(8):
arr[i] = i
arr
# 以特定顺序选取⾏⼦集
arr[[4, 3, 0, 6]]
# arr[[行]]
# 使⽤负数索引将会从末尾开始选取⾏:
arr[[-3, -5, -7]]
# 一维花式索引
arr = np.arange(32).reshape((8, 4))
arr
arr[[1, 5, 7, 2], [0, 3, 1, 2]]
# arr[[行], [列]]
# 最终选出的是元素(1,0)、(5,3)、(7,1)和(2,2)
'''
array([ 4, 23, 29, 10])
'''
# 二维花式索引
arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]
# arr [[行]] [:,[列]]
# 先按行顺序筛选,之后选取所有筛选出来的行,再按列顺序进行排列
'''
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
'''
# 三维花式索引
a3 = np.arange(64).reshape(4,4,4)
a3
a3[[1,2,0,3]][:, [0,2,1,3]][:, :, [2,3,1,0]]
# arr[[页]] [:, [行]] [:, :, [列]]
'''
array([[[18, 19, 17, 16],
[26, 27, 25, 24],
[22, 23, 21, 20],
[30, 31, 29, 28]],
[[34, 35, 33, 32],
[42, 43, 41, 40],
[38, 39, 37, 36],
[46, 47, 45, 44]],
[[ 2, 3, 1, 0],
[10, 11, 9, 8],
[ 6, 7, 5, 4],
[14, 15, 13, 12]],
[[50, 51, 49, 48],
[58, 59, 57, 56],
[54, 55, 53, 52],
[62, 63, 61, 60]]])
'''
数组的合并和拆分
-
concatenate((a1, a2, …), axis=0)
可以按指定轴将⼀个由数组组成的序列(如元组、列表等)连接到⼀起。(在原有的轴上进行合并)
arr1 = np.array([[1, 2, 3], [4, 5, 6]]) arr2 = np.array([[7, 8, 9], [10, 11, 12]]) np.concatenate([arr1, arr2], axis=0) np.concatenate([arr1, arr2], axis=1)
-
对于常⻅的连接操作,NumPy提供了⼀些⽐较⽅便的⽅法(如vstack、hstack 和 dstack)。
# 垂直方向 vertical 0 轴 np.vstack((arr1, arr2)) # 水平方向 horizontal 1 轴 np.hstack((arr1, arr2)) # 深度方向 depth 2 轴 np.dstack((arr1, arr2))
-
split⽤于将⼀个数组沿指定轴在指定位置拆分为多个数组
arr = np.random.randn(5, 2) arr first, second, third = np.split(arr, [1, 3], axis=0) first second third
-
stack() 在新轴上进行组合
a = np.arange(1, 7).reshape(2, 3) b = np.arange(7, 13).reshape(2, 3) d = np.arange(14, 20).reshape(2, 3) a b d # 在新轴上进行组合 c = np.stack((a, b, d)) c c.shape
-
数组连接和拆分的函数
函数 说明 concatenate 最一般化的连接,沿一条轴连接一组数组, 在原有轴上进行拼接 vstack、row_stack 以面向行的方式对数组进行堆叠(沿 0 轴) hstack 以面向列的方式对数组进行堆叠(沿 1 轴) column_stack 类似于 hstack,但是会先将一维数组转换为二维列向量 dstack 以面向“深度”的方式对数组进行堆叠(沿 2 轴) split 沿指定轴在指定位置拆分数组 hsplit、vsplit、dsplit split 的便捷化函数,分别沿 0 轴,1 轴,2 轴进行拆分 -
练习题
import numpy as np a = np.arange(1, 7).reshape(2, 3) b = np.arange(7, 13).reshape(2, 3) print(a, '--> a') print(b, '--> b') # 水平方向操作 c = np.hstack((a, b)) print(c, '--> c') a, b = np.hsplit(c, 2) print(a, '--> a') print(b, '--> b') # 垂直方向操作 c = np.vstack((a, b)) print(c, '--> c') a, b = np.vsplit(c, 2) print(a, '--> a') print(b, '--> b') # 深度方向操作 c = np.dstack((a, b)) print(c, '--> dc') a, b = np.dsplit(c, 2) print(a, '--> da') print(b, '--> db') # 一维数组的组合方案 a = np.arange(1, 9) b = np.arange(9, 17) print(a) print(b) print(np.row_stack((a, b))) # 形成两行 print(np.column_stack((a, b))) # 形成两列
numpy官网 :
方法 | 说明 |
---|---|
split | Split an array into multiple sub-arrays of equal or near-equal size. Does not raise an exception if an equal division cannot be made. |
hsplit | Split array into multiple sub-arrays horizontally (column-wise). |
vsplit | Split array into multiple sub-arrays vertically (row wise). |
dsplit | Split array into multiple sub-arrays along the 3rd axis (depth). |
concatenate | Join a sequence of arrays along an existing axis. |
stack | Join a sequence of arrays along a new axis. |
hstack | Stack arrays in sequence horizontally (column wise). |
vstack | Stack arrays in sequence vertically (row wise). |
dstack | Stack arrays in sequence depth wise (along third dimension). |
day01 (上)的作业:
用 np.empty(), np.empty_like(), np.full(), np.full_like() 创建数组
day01 (中) 的作业:
用三维数组做切片索引
day01 (下)的作业:
用 vstack、hstack 和 dstack,hsplit、vsplit、dsplit 做数组的拼接和拆分