cs231n关于numpy这部分的翻译

来源:互联网 发布:江津加工中心编程招聘 编辑:程序博客网 时间:2024/04/29 00:38

原文请见http://cs231n.github.io/python-numpy-tutorial/#numpy

本文主要是翻译了cs231n课程中关于numpy的介绍,自己在学习的过程中经常会用到numpy,但是对其并不是很熟悉,因此就重新学习了一下,并简单翻译,加上自己的一点理解。欢迎批评指正。

Numpy

numpy是Python科学计算的核心包。它提供了高效的多维数组对象,以及操作这些数组的工具。

Arrays

numpy数组是一个网格数据值,所有的值都是同一个类型,并且以非负整数的元组的形式索引这些值。数组维的个数也就是数组的秩,数组的shape属性是整数的元组,给出了沿着每个维度数组的大小。

我们可以从嵌套的Python列表的形式初始化numpy数组,并使用方括号访问元素:

import numpy as npa = np.array([1, 2, 3])  # Create a rank 1 arrayprint type(a)            # Prints "<type 'numpy.ndarray'>"print a.shape            # Prints "(3,)"print a[0], a[1], a[2]   # Prints "1 2 3"a[0] = 5                 # Change an element of the arrayprint a                  # Prints "[5, 2, 3]"b = np.array([[1,2,3],[4,5,6]])   # Create a rank 2 arrayprint b.shape                     # Prints "(2, 3)"print b[0, 0], b[0, 1], b[1, 0]   # Prints "1 2 4"
numpy同时提供了很多创建数组的函数:

import numpy as npa = np.zeros((2,2))  # Create an array of all zerosprint a              # Prints "[[ 0.  0.]                     #          [ 0.  0.]]"    b = np.ones((1,2))   # Create an array of all onesprint b              # Prints "[[ 1.  1.]]"c = np.full((2,2), 7) # Create a constant arrayprint c               # Prints "[[ 7.  7.]                      #          [ 7.  7.]]"d = np.eye(2)        # Create a 2x2 identity matrixprint d              # Prints "[[ 1.  0.]                     #          [ 0.  1.]]"    e = np.random.random((2,2)) # Create an array filled with random valuesprint e                     # Might print "[[ 0.91940167  0.08143941]                            #               [ 0.68744134  0.87236687]]"
Array Indexing

numpy提供了几种方式来索引数组

Slicing:与Python list类似,numpy数组同样可以被切片。因为数组可能是多维的,必须为数组的每个维度指定切片。

需要注意的是,数组的切片是对相同数据的视图,因此修改它将会修改原数组。

import numpy as np# Create the following rank 2 array with shape (3, 4)# [[ 1  2  3  4]#  [ 5  6  7  8]#  [ 9 10 11 12]]a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])# Use slicing to pull out the subarray consisting of the first 2 rows# and columns 1 and 2; b is the following array of shape (2, 2):# [[2 3]#  [6 7]]b = a[:2, 1:3]# A slice of an array is a view into the same data, so modifying it# will modify the original array.print a[0, 1]   # Prints "2"b[0, 0] = 77    # b[0, 0] is the same piece of data as a[0, 1]print a[0, 1]   # Prints "77"
您还可以混合整数索引与切片索引。 然而,这样做将产生比原始数组低秩的数组。

import numpy as np# Create the following rank 2 array with shape (3, 4)# [[ 1  2  3  4]#  [ 5  6  7  8]#  [ 9 10 11 12]]a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])# Two ways of accessing the data in the middle row of the array.# Mixing integer indexing with slices yields an array of lower rank,# while using only slices yields an array of the same rank as the# original array:row_r1 = a[1, :]    # Rank 1 view of the second row of a  row_r2 = a[1:2, :]  # Rank 2 view of the second row of aprint row_r1, row_r1.shape  # Prints "[5 6 7 8] (4,)"print row_r2, row_r2.shape  # Prints "[[5 6 7 8]] (1, 4)"# We can make the same distinction when accessing columns of an array:col_r1 = a[:, 1]col_r2 = a[:, 1:2]print col_r1, col_r1.shape  # Prints "[ 2  6 10] (3,)"print col_r2, col_r2.shape  # Prints "[[ 2]                            #          [ 6]                            #          [10]] (3, 1)"
当使用切片将索引索引到numpy数组时,生成的数组视图将始终是原始数组的子数组。 相比之下,整数数组索引允许使用另一个数组的数据构造任意数组。 这里是一个例子:

import numpy as npa = np.array([[1,2], [3, 4], [5, 6]])# An example of integer array indexing.# The returned array will have shape (3,) and print a[[0, 1, 2], [0, 1, 0]]  # Prints "[1 4 5]"# The above example of integer array indexing is equivalent to this:print np.array([a[0, 0], a[1, 1], a[2, 0]])  # Prints "[1 4 5]"# When using integer array indexing, you can reuse the same# element from the source array:print a[[0, 0], [1, 1]]  # Prints "[2 2]"# Equivalent to the previous integer array indexing exampleprint np.array([a[0, 1], a[0, 1]])  # Prints "[2 2]"
Integer array indexing: 整数数组索引的一个有用的技巧是从矩阵的每一行中选择或改变一个元素:

import numpy as np# Create a new array from which we will select elementsa = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])print a  # prints "array([[ 1,  2,  3],         #                [ 4,  5,  6],         #                [ 7,  8,  9],         #                [10, 11, 12]])"# Create an array of indicesb = np.array([0, 2, 0, 1])# Select one element from each row of a using the indices in bprint a[np.arange(4), b]  # Prints "[ 1  6  7 11]"# Mutate one element from each row of a using the indices in ba[np.arange(4), b] += 10print a  # prints "array([[11,  2,  3],         #                [ 4,  5, 16],         #                [17,  8,  9],         #                [10, 21, 12]])
Boolean array indexing: 布尔数组索引允许您挑选数组的任意元素。 通常,这种类型的索引用于选择满足一些条件的数组的元素。 这里是一个例子:
import numpy as npa = np.array([[1,2], [3, 4], [5, 6]])bool_idx = (a > 2)  # Find the elements of a that are bigger than 2;                    # this returns a numpy array of Booleans of the same                    # shape as a, where each slot of bool_idx tells                    # whether that element of a is > 2.            print bool_idx      # Prints "[[False False]                    #          [ True  True]                    #          [ True  True]]"# We use boolean array indexing to construct a rank 1 array# consisting of the elements of a corresponding to the True values# of bool_idxprint a[bool_idx]  # Prints "[3 4 5 6]"# We can do all of the above in a single concise statement:print a[a > 2]     # Prints "[3 4 5 6]"
Datatypes
每个numpy数组是一个相同类型的元素的网格。 Numpy提供了一组大量的数字数据类型,可以用来构造数组。 Numpy尝试在创建数组时猜测数据类型,但是构造数组的函数通常还包括一个可选参数,以显式指定数据类型。 这里是一个例子:

import numpy as npx = np.array([1, 2])  # Let numpy choose the datatypeprint x.dtype         # Prints "int64"x = np.array([1.0, 2.0])  # Let numpy choose the datatypeprint x.dtype             # Prints "float64"x = np.array([1, 2], dtype=np.int64)  # Force a particular datatypeprint x.dtype                         # Prints "int64"
Array math

基本数学函数对数组进行逐元素操作,并且既可以作为运算符重载,也可以作为numpy模块中的函数使用:

import numpy as npx = np.array([[1,2],[3,4]], dtype=np.float64)y = np.array([[5,6],[7,8]], dtype=np.float64)# Elementwise sum; both produce the array# [[ 6.0  8.0]#  [10.0 12.0]]print x + yprint np.add(x, y)# Elementwise difference; both produce the array# [[-4.0 -4.0]#  [-4.0 -4.0]]print x - yprint np.subtract(x, y)# Elementwise product; both produce the array# [[ 5.0 12.0]#  [21.0 32.0]]print x * yprint np.multiply(x, y)# Elementwise division; both produce the array# [[ 0.2         0.33333333]#  [ 0.42857143  0.5       ]]print x / yprint np.divide(x, y)# Elementwise square root; produces the array# [[ 1.          1.41421356]#  [ 1.73205081  2.        ]]print np.sqrt(x)
我们使用dot函数来计算相量的内积,矩阵乘以相量或者矩阵乘以矩阵。dot可以通过numpy模块中的函数来调用,或者数组对象的一个实例中的函数:

import numpy as npx = np.array([[1,2],[3,4]])y = np.array([[5,6],[7,8]])v = np.array([9,10])w = np.array([11, 12])# Inner product of vectors; both produce 219print v.dot(w)print np.dot(v, w)# Matrix / vector product; both produce the rank 1 array [29 67]print x.dot(v)print np.dot(x, v)# Matrix / matrix product; both produce the rank 2 array# [[19 22]#  [43 50]]print x.dot(y)print np.dot(x, y)
Numpy提供许多有用的函数来执行数组上的计算; 其中最有用的是sum:

import numpy as npx = np.array([[1,2],[3,4]])print np.sum(x)  # Compute sum of all elements; prints "10"print np.sum(x, axis=0)  # Compute sum of each column; prints "[4 6]"print np.sum(x, axis=1)  # Compute sum of each row; prints "[3 7]"
除了使用数组计算数学函数之外,我们经常需要重新整形或以其他方式处理数组中的数据。 这种类型的操作的最简单的例子是转置矩阵; 要转置矩阵,只需使用数组对象的T属性:

import numpy as npx = np.array([[1,2], [3,4]])print x    # Prints "[[1 2]           #          [3 4]]"print x.T  # Prints "[[1 3]           #          [2 4]]"# Note that taking the transpose of a rank 1 array does nothing:v = np.array([1,2,3])print v    # Prints "[1 2 3]"print v.T  # Prints "[1 2 3]"
broadcasting
广播是一种强大的机制,允许numpy在执行算术运算时使用不同形状的数组。 通常我们有一个较小的数组和一个较大的数组,我们想要使用较小的数组多次对较大的数组执行一些操作。
例如,假设我们要向矩阵的每一行添加一个常量向量。 我们可以这样做:
import numpy as np# We will add the vector v to each row of the matrix x,# storing the result in the matrix yx = 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)   # Create an empty matrix with the same shape as x# Add the vector v to each row of the matrix x with an explicit loopfor i in range(4):    y[i, :] = x[i, :] + v# Now y is the following# [[ 2  2  4]#  [ 5  5  7]#  [ 8  8 10]#  [11 11 13]]print y
这没什么问题; 然而当矩阵x非常大时,在Python中计算显式循环可能很慢。 注意向矩阵x的每行添加向量v等同于通过垂直地堆叠v的多个副本来形成矩阵vv,然后执行x和vv的元素求和。 我们可以这样实现这种方法:
import numpy as np# We will add the vector v to each row of the matrix x,# storing the result in the matrix yx = 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))  # Stack 4 copies of v on top of each otherprint vv                 # Prints "[[1 0 1]                         #          [1 0 1]                         #          [1 0 1]                         #          [1 0 1]]"y = x + vv  # Add x and vv elementwiseprint y  # Prints "[[ 2  2  4         #          [ 5  5  7]         #          [ 8  8 10]         #          [11 11 13]]"
Numpy广播允许我们执行这个计算,而不实际创建v的多个副本。考虑这个版本,使用广播:

import numpy as np# We will add the vector v to each row of the matrix x,# storing the result in the matrix yx = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])v = np.array([1, 0, 1])y = x + v  # Add v to each row of x using broadcastingprint y  # Prints "[[ 2  2  4]         #          [ 5  5  7]         #          [ 8  8 10]         #          [11 11 13]]"

即使x具有形状(4,3)和v具有形状(3,),由于广播,线y = x + v也起作用; 这行工作原理好像v实际上有形状(4,3),其中每行是v的副本,并且和是以元素方式执行的。

将两个数组一起广播遵循以下规则:
1.如果阵列不具有相同的秩,则将具有1的较低秩阵列的形状加前缀,直到两个形状具有相同的长度。
2.如果两个数组在维度中具有相同的大小,或者其中一个数组在该维度中具有大小1,则称这两个数组在维度中是兼容的。
3.如果阵列在所有维度上都兼容,则可以一起广播阵列。
4.在广播之后,每个阵列表现为其形状等于两个输入阵列的形状的元素最大值。
5.在任何维度中,一个数组的大小为1,另一个数组的大小大于1,则第一个数组的行为就像是沿着该维度复制

import numpy as np# Compute outer product of vectorsv = np.array([1,2,3])  # v has shape (3,)w = np.array([4,5])    # w has shape (2,)# To compute an outer product, we first reshape v to be a column# vector of shape (3, 1); we can then broadcast it against w to yield# an output of shape (3, 2), which is the outer product of v and w:# [[ 4  5]#  [ 8 10]#  [12 15]]print np.reshape(v, (3, 1)) * w# Add a vector to each row of a matrixx = np.array([[1,2,3], [4,5,6]])# x has shape (2, 3) and v has shape (3,) so they broadcast to (2, 3),# giving the following matrix:# [[2 4 6]#  [5 7 9]]print x + v# Add a vector to each column of a matrix# x has shape (2, 3) and w has shape (2,).# If we transpose x then it has shape (3, 2) and can be broadcast# against w to yield a result of shape (3, 2); transposing this result# yields the final result of shape (2, 3) which is the matrix x with# the vector w added to each column. Gives the following matrix:# [[ 5  6  7]#  [ 9 10 11]]print (x.T + w).T# Another solution is to reshape w to be a row vector of shape (2, 1);# we can then broadcast it directly against x to produce the same# output.print x + np.reshape(w, (2, 1))# Multiply a matrix by a constant:# x has shape (2, 3). Numpy treats scalars as arrays of shape ();# these can be broadcast together to shape (2, 3), producing the# following array:# [[ 2  4  6]#  [ 8 10 12]]print x * 2
Scipy

Numpy提供了一个高性能的多维数组和基本工具来计算和操作这些数组。 SciPy基于此构建,并提供了大量对numpy数组进行操作的函数,对不同类型的科学和工程应用程序非常有用。

Image Operations

SciPy提供了一些基本功能来处理图像。 例如,它具有将图像从磁盘读入numpy数组,将numpy数组写入磁盘作为图像,以及调整图像大小的功能。 这里是一个简单的例子,展示这些功能:

from scipy.misc import imread, imsave, imresize# Read an JPEG image into a numpy arrayimg = imread('assets/cat.jpg')print img.dtype, img.shape  # Prints "uint8 (400, 248, 3)"# We can tint the image by scaling each of the color channels# by a different scalar constant. The image has shape (400, 248, 3);# we multiply it by the array [1, 0.95, 0.9] of shape (3,);# numpy broadcasting means that this leaves the red channel unchanged,# and multiplies the green and blue channels by 0.95 and 0.9# respectively.img_tinted = img * [1, 0.95, 0.9]# Resize the tinted image to be 300 by 300 pixels.img_tinted = imresize(img_tinted, (300, 300))# Write the tinted image back to diskimsave('assets/cat_tinted.jpg', img_tinted)

Distance between Points

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

import numpy as npfrom scipy.spatial.distance import pdist, squareform# Create the following array where each row is a point in 2D space:# [[0 1]#  [1 0]#  [2 0]]x = np.array([[0, 1], [1, 0], [2, 0]])print x# Compute the Euclidean distance between all rows of x.# d[i, j] is the Euclidean distance between x[i, :] and x[j, :],# and d is the following array:# [[ 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 npimport matplotlib.pyplot as plt# Compute the x and y coordinates for points on a sine curvex = np.arange(0, 3 * np.pi, 0.1)y = np.sin(x)# Plot the points using matplotlibplt.plot(x, y)plt.show()  # You must call plt.show() to make graphics appear.

只需一点点额外的工作,我们就可以轻松地绘制多条线,并添加一个标题,图例和轴标签:

import numpy as npimport matplotlib.pyplot as plt# Compute the x and y coordinates for points on sine and cosine curvesx = np.arange(0, 3 * np.pi, 0.1)y_sin = np.sin(x)y_cos = np.cos(x)# Plot the points using matplotlibplt.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 npimport matplotlib.pyplot as plt# Compute the x and y coordinates for points on sine and cosine curvesx = np.arange(0, 3 * np.pi, 0.1)y_sin = np.sin(x)y_cos = np.cos(x)# Set up a subplot grid that has height 2 and width 1,# and set the first such subplot as active.plt.subplot(2, 1, 1)# Make the first plotplt.plot(x, y_sin)plt.title('Sine')# Set the second subplot as active, and make the second plot.plt.subplot(2, 1, 2)plt.plot(x, y_cos)plt.title('Cosine')# Show the figure.plt.show()

Images

可以使用imshow()函数显示图片,这里是一个例子:

import numpy as npfrom scipy.misc import imread, imresizeimport matplotlib.pyplot as pltimg = imread('assets/cat.jpg')img_tinted = img * [1, 0.95, 0.9]# Show the original imageplt.subplot(1, 2, 1)plt.imshow(img)# Show the tinted imageplt.subplot(1, 2, 2)# A slight gotcha with imshow is that it might give strange results# if presented with data that is not uint8. To work around this, we# explicitly cast the image to uint8 before displaying it.plt.imshow(np.uint8(img_tinted))plt.show()

0 0