[译] Python Numpy学习资料 (3)

原文来自http://cs231n.github.io/python-numpy-tutorial/#python-containers

Broadcasting

Broadcasting是进行算术运算时的强大机制,可以让numpy处理不同shape的数组。通常地,我们有一个较小的数组和一个较大的数组,我们想用较小的数组多次在大数组上进行运算。
比如,假设我们想让矩阵的每一行加上一个常数向量。我们可以这样做:

import numpy as np

# 我们将向量v加到矩阵x的每一行上
# 计算结果存储在矩阵y中
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
y = np.empty_like(x)   # 创建一个与x的shape相同的空矩阵

# 用一个明确的循环,将向量v加到矩阵x的每一行上
for i in range(4):
    y[i, :] = x[i, :] + v

# 现在y如下
# [[ 2  2  4]
#  [ 5  5  7]
#  [ 8  8 10]
#  [11 11 13]]
print(y)

该方法可行;但是如果x是一个非常大的矩阵,在Python中作一个明确的循环可能相当慢。注意,将向量v加到矩阵x的每一行上,相当于通过垂直堆栈v的多个复制品,形成一个矩阵vv,然后将x与vv相加。我们可以如下实施该方法:

import numpy as np

# 我们将向量v加到矩阵x的每一行上,并将结果存储在矩阵y中
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
vv = np.tile(v, (4, 1))   # 堆栈了4个v的复制品
print(vv)                 # 输出 "[[1 0 1]
                          #       [1 0 1]
                          #       [1 0 1]
                          #       [1 0 1]]"
y = x + vv  # 将x与vv相加
print(y)  # 输出 "[[ 2  2  4
          #       [ 5  5  7]
          #       [ 8  8 10]
          #       [11 11 13]]"

Numpy broadcasting让我们可以不需要创建v的许多复制品来进行操作。考虑到这个版本,如下运用broadcasting:

import numpy as np

# 我们将向量v加到矩阵x的每一行上,并将结果存储在矩阵y中
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
v = np.array([1, 0, 1])
y = x + v  # 运用broadcasting将向量v加到矩阵x的每一行上
print(y)  # 输出 "[[ 2  2  4]
          #       [ 5  5  7]
          #       [ 8  8 10]
          #       [11 11 13]]"

虽然x的shape是(4,3),而v的shape是(3,),但是y=x+v还是可以工作,因为有broadcasting;如果v的shape是(4,3),每一行是v的复制品,那么则进行元素的和的计算。
两个数组的Broadcasting遵循下列规则:
1. 如果数组的秩不同,则假设低秩数组的shape为1,直到两个shapes的长度相同。
2. 如果两个数组在某个维度上的size相同,则称这两个数组在这个维度上兼容,或者如果其中一个数组在该维度上的size为1。
3. 如果两个数组在所有维度上兼容,则他们能被一起broadcast。
4. Broadcasting之后,假设每个数组的shape和两个输入数组最大的shape等价。
5. 在任意维度上如果一个数组的size为1,而另外一个数组的size大于1,则第一个数组想从该维度复制过来的一样操作。
下面是broadcasting的一些应用:

import numpy as np

# 计算向量的外积
v = np.array([1,2,3])  # v的shape为 (3,)
w = np.array([4,5])    # w 的shape为 (2,)
#为计算外积,首先改变v的形状使其成为一个shape为(3, 1) 的列向量
# 然后能将其与w一起broadcast , 产生一个shape 为(3, 2)的输出,这是v与w的外积
# [[ 4  5]
#  [ 8 10]
#  [12 15]]
print(np.reshape(v, (3, 1)) * w)

# 在矩阵的每一行上加上一个向量
x = np.array([[1,2,3], [4,5,6]])
# x的shape为 (2, 3),v的shape为 (3,) ,所以他们一起broadcast 到 (2, 3),
# 给出如下矩阵:
# [[2 4 6]
#  [5 7 9]]
print(x + v)

#在矩阵的每一行上加上一个向量
# x的shape为 (2, 3),w的shape为 (2,).
# 如果我们将x转置,则它的shape将变成 (3, 2),可以和w一起broadcast,产生shape为(3, 2)的结果
# 再将结果转置得到shape为(2, 3) 矩阵,正是将向量w加到矩阵x的每一列上的结果
# 给出如下矩阵:
# [[ 5  6  7]
#  [ 9 10 11]]
print((x.T + w).T)
# 另一种方法是改变w的形状,使其成为shape为(2, 1)的列向量;
# 然后我们可以将其直接broadcast产生相同的结果
print(x + np.reshape(w, (2, 1)))

# 将矩阵乘以一个常数:
# x的shape为 (2, 3). Numpy将标量按照shape为()的数组来处理;
# 这些能被一起broadcast到shape为 (2, 3), 输出一下数组
# [[ 2  4  6]
#  [ 8 10 12]]
print(x * 2)

Broadcasting通常会让你的代码更加准确、快速,所以应该尽可能地去使用它。

Numpy Documentation

上面的简要概述涵盖了关于numpy你需要了解的一些重要事项,但是这是很不完整的。如果要了解更多关于numpy,请访问https://docs.scipy.org/doc/numpy/reference/

SciPy

Numpy提供了高性能的多维数组,以及数组计算与操作的基本工具。Scipy正是基于此,提供了诸多操作numpy数组的函数,可用于不同种类的科学及工程应用。
熟悉Scipy的最好方法是参看文献:https://docs.scipy.org/doc/scipy/reference/index.html

Image operations图像操作

SciPy提供了处理图像的基本函数。比如,它提供一些函数,可以从磁盘中读取图像并变成numpy数组,或者将numpy数组转化为图像写入磁盘,或者调整图像的大小。下面是展示这些函数的一个简单例子:
from scipy.misc import imread, imsave, imresize

# 读取一副JPEG图像并转化为numpy数组
img = imread('assets/cat.jpg')
print(img.dtype, img.shape)  # 输出 "uint8 (400, 248, 3)"

#通过一个常数来缩放每个颜色通道,我们可以给图像调色
# 此图像的shape为 (400, 248, 3);
# 我们将其乘以shape为(3,)的数组[1, 0.95, 0.9];
# numpy broadcasting意味着使红色通道不变,将绿色通道乘以0.95,将蓝色通道乘以0.9
img_tinted = img * [1, 0.95, 0.9]

# 将调色后的图像调整到300*300像素的大小.
img_tinted = imresize(img_tinted, (300, 300))

# 将改变后的图像重新写入到磁盘
imsave('assets/cat_tinted.jpg', img_tinted)

MATLAB files

函数scipy.io.loadmat和scipy.io.savemat让你可以读写MATLAB文件,你可以查看https://docs.scipy.org/doc/scipy/reference/io.html

Distance between points

SciPy 定义了一些用于计算点集之间的距离。
函数scipy.spatial.distance.pdist计算给定集合中所有pairs of points之间的距离。

import numpy as np
from scipy.spatial.distance import pdist, squareform

# 创建以下数组,其中每一行是2D空间中的一个点:
# [[0 1]
#  [1 0]
#  [2 0]]
x = np.array([[0, 1], [1, 0], [2, 0]])
print(x)

# 计算x的所有行之间的欧几里得距离.
# d[i, j] 是x[i, :]和x[j, :]之间的欧几里得距离,d是接下来的数组
# [[ 0.          1.41421356  2.23606798]
#  [ 1.41421356  0.          1.        ]
#  [ 2.23606798  1.          0.        ]]
d = squareform(pdist(x, 'euclidean'))
print(d)

一个类似的函数(scipy.spatial.distance.cdist)计算了两个点的集合的所有对之间的距离。

Matplotlib

Matplotlib 是一个绘图库。这一节简单介绍了matplotlib.pyplot模块,它提供了一个类似MATLAB的绘图系统。

Plotting绘图

Matplotlib中最重要的函数是plot,可以让你绘制2D数据。下面是一个简单的例子:

import numpy as np
import matplotlib.pyplot as plt

# 计算正弦曲线上的点的x、y坐标
x = np.arange(0, 3 * np.pi, 0.1)
y = np.sin(x)

# 用matplotlib绘制点
plt.plot(x, y)
plt.show()  # 必须调用plt.show() 使图像出现.

代码运行后产生以下绘图:

再有一点点工作我们就能够简单绘制多条线,并且加上标题、图例和轴标签。

import numpy as np
import matplotlib.pyplot as plt

#计算正弦曲线和余弦曲线上的点的x、y坐标
x = np.arange(0, 3 * np.pi, 0.1)
y_sin = np.sin(x)
y_cos = np.cos(x)

# 用matplotlib绘制点
plt.plot(x, y_sin)
plt.plot(x, y_cos)
plt.xlabel('x axis label')
plt.ylabel('y axis label')
plt.title('Sine and Cosine')
plt.legend(['Sine', 'Cosine'])
plt.show()

这里写图片描述

Subplots创建子图

运用subplot函数,你可以在同一幅图像中绘制不同的东西。如下:

import numpy as np
import matplotlib.pyplot as plt

#计算正弦曲线和余弦曲线上的点的x、y坐标
x = np.arange(0, 3 * np.pi, 0.1)
y_sin = np.sin(x)
y_cos = np.cos(x)

# 设定一个子图网格,高度为2,宽度为1
# 并设定第一个这样的子图为active
plt.subplot(2, 1, 1)

# 绘制第一张子图
plt.plot(x, y_sin)
plt.title('Sine')

# 设定第二张子图为active,绘制第二张图
plt.subplot(2, 1, 2)
plt.plot(x, y_cos)
plt.title('Cosine')

# 显示图像
plt.show()

这里写图片描述

Images

你可以运用imshow函数来显示图像,示例如下:

import numpy as np
from scipy.misc import imread, imresize
import matplotlib.pyplot as plt

img = imread('assets/cat.jpg')
img_tinted = img * [1, 0.95, 0.9]

# 显示原始图像
plt.subplot(1, 2, 1)
plt.imshow(img)

# 显示有色图像
plt.subplot(1, 2, 2)

# 简单的用imshow可能会产生奇怪的结果,这可能是因为数据不是uint8格式的
# 我们可以精确地将图像变成uint8格式,然后再显示图像
plt.imshow(np.uint8(img_tinted))
plt.show()

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值