本文主要根据 斯坦福CS231n课程的Python 教程进行整理,原文地址为http://cs231n./python-numpy-tutorial/,官方Python指南网址https://www./doc/
Python是本身是一个通用的编程语言,但其具有一些库(numpy,scipy,matplotlib)用于科学运算,原文的Python的版本是3.5。
本文先进行Python的基本介绍(数据、容器、函数、类)然后再介绍Numpy库、SciPy库以及MatPlotlib库的常用方法。
Python基本数据类型
- 整型 int ,浮点型 float (注:Python没有i++这种语句,乘方用x**i)
- 布尔型 booleans (注:Python 使用 and 、or、not替代C语言的&&、||、!;t!=f表示t和f的异或)
- 字符串型 strings (注:Python中字符串可以用单引号或双引号表示,一些常用的函数如大小写、去除空格、字符串替换、空格位置调整等,去掉空格s.strip()字符串替换s.replace('l','ell')具体使用什么函数可以现查)
Python容器
- 列表 list,与数组相同但是可变大小(注:下标从0开始算,与maltab从1开始算不同)
xs = [3, 1, 2] # Create a list print(xs, xs[2]) # Prints "[3, 1, 2] 2" 注意小标从0开始 print(xs[-1]) # 负数下标从后往前数; prints "2" xs[2] = 'foo' # 列表的元素可以类型不同 print(xs) # Prints "[3, 1, 'foo']" print(xs) # Prints "[3, 1, 'foo', 'bar']" print(x, xs) # Prints "bar [3, 1, 'foo']"
切片:list使用中的一个重要方法(注:切片的下标左边界包含,右边界不包含,与matlab两边界都包含不同)
nums = list(range(5)) # 利用list()函数生成列表 print(nums) # Prints "[0, 1, 2, 3, 4]" print(nums[2:4]) # 切片下标2到(4-1); prints "[2, 3]" print(nums[2:]) # 切片下标2到最后; prints "[2, 3, 4]" print(nums[:2]) # 切片开始到下标(2-1); prints "[0, 1]" print(nums[:]) # 切片全部; prints "[0, 1, 2, 3, 4]" print(nums[:-1]) # 切片开始到(-1-1); prints "[0, 1, 2, 3]" nums[2:4] = [8, 9] # 将下标2,3的值替换成8,9 print(nums) # Prints "[0, 1, 8, 9, 4]"
列表元素循环(与matlab相同)
animals = ['cat', 'dog', 'monkey']
也可以利用内建函数enumerate(Lists)取得下标(从0开始)和元素
animals = ['cat', 'dog', 'monkey'] for idx, animal in enumerate(animals): print('#%d: %s' % (idx + 1, animal)) # Prints "#1: cat", "#2: dog", "#3: monkey", each on its own line
列表解析:一种生成新的列表的方式,举两个例子
squares = [x ** 2 for x in nums] print(squares) # Prints [0, 1, 4, 9, 16]
even_squares = [x ** 2 for x in nums if x % 2 == 0] print(even_squares) # Prints "[0, 4, 16]"
- 字典 dictionaries,存储键值对(key,value)
d = {'cat': 'cute', 'dog': 'furry'} # Create a new dictionary with some data print(d['cat']) # Get an entry from a dictionary; prints "cute" print('cat' in d) # Check if a dictionary has a given key; prints "True" d['fish'] = 'wet' # Set an entry in a dictionary print(d['fish']) # Prints "wet" # print(d['monkey']) # KeyError: 'monkey' not a key of d print(d.get('monkey', 'N/A')) # Get an element with a default; prints "N/A" print(d.get('fish', 'N/A')) # Get an element with a default; prints "wet" del d['fish'] # Remove an element from a dictionary print(d.get('fish', 'N/A')) # "fish" is no longer a key; prints "N/A"
字典循环
d = {'person': 2, 'cat': 4, 'spider': 8} print('A %s has %d legs' % (animal, legs)) # Prints "A person has 2 legs", "A cat has 4 legs", "A spider has 8 legs"
也可以利用内建函数d.items()取得键和值
d = {'person': 2, 'cat': 4, 'spider': 8} for animal, legs in d.items(): print('A %s has %d legs' % (animal, legs)) # Prints "A person has 2 legs", "A cat has 4 legs", "A spider has 8 legs"
字典解析,利用表达式生成字典
even_num_to_square = {x: x ** 2 for x in nums if x % 2 == 0} print(even_num_to_square) # Prints "{0: 0, 2: 4, 4: 16}"
print('cat' in animals) # Check if an element is in a set; prints "True" print('fish' in animals) # prints "False" animals.add('fish') # Add an element to a set print('fish' in animals) # Prints "True" print(len(animals)) # Number of elements in a set; prints "3" animals.add('cat') # Adding an element that is already in the set does nothing print(len(animals)) # Prints "3" animals.remove('cat') # Remove an element from a set print(len(animals)) # Prints "2"
集合循环,与数组循环语法相同,但是注意其无序性。
animals = {'cat', 'dog', 'fish'} for idx, animal in enumerate(animals): print('#%d: %s' % (idx + 1, animal)) # Prints "#1: fish", "#2: dog", "#3: cat"
集合解析:利用解析表达式生成集合
nums = {int(sqrt(x)) for x in range(30)} print(nums) # Prints "{0, 1, 2, 3, 4, 5}"
- 元组 tuple,与数组类似,但其实不可变的列表,因此可以作为字典dictionary中的键key或集合set的元素(注:列表由于可变无法成为dictionary的key和set的元素)
d = {(x, x + 1): x for x in range(10)} # Create a dictionary with tuple keys t = (5, 6) # Create a tuple print(type(t)) # Prints "<class 'tuple'>" print(d[(1, 2)]) # Prints "1"
Python函数
利用关键字def,返回使用return
# Prints "negative", "zero", "positive"
参数可以使可选的的例子
def hello(name, loud=False): print('HELLO, %s!' % name.upper()) print('Hello, %s' % name) hello('Bob') # Prints "Hello, Bob" hello('Fred', loud=True) # Prints "HELLO, FRED!"
Python类
定义类的Python语法的格式如下
def __init__(self, name): self.name = name # Create an instance variable def greet(self, loud=False): print('HELLO, %s!' % self.name.upper()) print('Hello, %s' % self.name) g = Greeter('Fred') # 构造Greeter类的实例 g.greet() # 调用类函数;prints "Hello, Fred" g.greet(loud=True) # 调用类函数; prints "HELLO, FRED!"
Numpy
numpy库用于python科学计算,与matlab有相似之处,其核心是对数组arrays的操作。
数组arrays
数组array是numpy提供的容器,能够通过列表list生成,利用方括号取元素(注:下标从0开始)
a = np.array([1, 2, 3]) # Create a rank 1 array print(type(a)) # Prints "<class '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 array print(a) # Prints "[5, 2, 3]" b = np.array([[1,2,3],[4,5,6]]) # Create a rank 2 array print(b.shape) # Prints "(2, 3)" print(b[0, 0], b[0, 1], b[1, 0]) # Prints "1 2 4"
与matlab类似,numpy提供了一些生成特殊数组的函数
a = np.zeros((2,2)) # Create an array of all zeros print(a) # Prints "[[ 0. 0.] b = np.ones((1,2)) # Create an array of all ones print(b) # Prints "[[ 1. 1.]]" c = np.full((2,2), 7) # Create a constant array print(c) # Prints "[[ 7. 7.] d = np.eye(2) # Create a 2x2 identity matrix print(d) # Prints "[[ 1. 0.] e = np.random.random((2,2)) # Create an array filled with random values print(e) # Might print "[[ 0.91940167 0.08143941] # [ 0.68744134 0.87236687]]"
数组切片,利用方括号内的逗号和冒号对每个维度进行索引,基本与matlab相同(注:左包括右不包括)
# Create the following rank 2 array with shape (3, 4) 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): # 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"
与matlab不同的是,切片时使用单个数字索引和使用冒号的索引的结果维度是不同的,例如
# Create the following rank 2 array with shape (3, 4) 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 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 a print(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: print(col_r1, col_r1.shape) # Prints "[ 2 6 10] (3,)" print(col_r2, col_r2.shape) # Prints "[[ 2]
这里有一个较为奇怪的整数索引的方式,但这种表达方便创建数组。
a = 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 example print(np.array([a[0, 1], a[0, 1]])) # Prints "[2 2]"
# Create a new array from which we will select elements a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]]) print(a) # prints "array([[ 1, 2, 3], # Create an array of indices b = np.array([0, 2, 0, 1]) # Select one element from each row of a using the indices in b print(a[np.arange(4), b]) # Prints "[ 1 6 7 11]" # Mutate one element from each row of a using the indices in b print(a) # prints "array([[11, 2, 3],
利用布尔表达式进行索引
a = 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] # We use boolean array indexing to construct a rank 1 array # consisting of the elements of a corresponding to the True values print(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]"
关于数组的索引就只介绍一小部分,当有需要时请查看官方文档深入学习。https://docs./doc/numpy/reference/arrays.indexing.html
数组的元素类型可以根据需求进行定义
x = np.array([1, 2]) # Let numpy choose the datatype print(x.dtype) # Prints "int64" x = np.array([1.0, 2.0]) # Let numpy choose the datatype print(x.dtype) # Prints "float64" x = np.array([1, 2], dtype=np.int64) # Force a particular datatype print(x.dtype) # Prints "int64"
array的数学运算,(注意与matlab不同,乘除法是每一个位置的元素乘除法,不是矩阵运算)
x = 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 # Elementwise difference; both produce the array # Elementwise product; both produce the array # Elementwise division; both produce the array # Elementwise square root; produces the array
矩阵乘法采用dot
x = np.array([[1,2],[3,4]]) y = np.array([[5,6],[7,8]]) # Inner product of vectors; both produce 219 # Matrix / vector product; both produce the rank 1 array [29 67] # Matrix / matrix product; both produce the rank 2 array
一些有用的矩阵运算方法,例如sum
x = 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]"
当需要使用某些函数时,进行搜索https://docs./doc/numpy/reference/routines.math.html
矩阵转置
x = np.array([[1,2], [3,4]]) print(x) # Prints "[[1 2] print(x.T) # Prints "[[1 3] # Note that taking the transpose of a rank 1 array does nothing: print(v) # Prints "[1 2 3]" print(v.T) # Prints "[1 2 3]"
广播机制:numpy中一个重要而有用的机制,可以将小的矩阵进行扩展后与大矩阵进行运算,省for循环,提高运算速度。
# We will add the vector v to each row of the matrix x, # storing the result in the matrix y x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]]) 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 loop
# We will add the vector v to each row of the matrix x, # storing the result in the matrix y x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]]) vv = np.tile(v, (4, 1)) # Stack 4 copies of v on top of each other print(vv) # Prints "[[1 0 1] y = x + vv # Add x and vv elementwise print(y) # Prints "[[ 2 2 4
还能更加简洁
# We will add the vector v to each row of the matrix x, # storing the result in the matrix y x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]]) y = x + v # Add v to each row of x using broadcasting print(y) # Prints "[[ 2 2 4]
我们整理一些广播broadcasting的规则:
1、两个数组的维数不相同,低维度的扩展维度
2、两个数组在某个维度上size相同或小的size是1
3、广播相当于沿着size为1的地方进行复制
下面用例子来展示一下广播
# Compute outer product of vectors v = 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: print(np.reshape(v, (3, 1)) * w) # Add a vector to each row of a matrix x = 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: # 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: # Another solution is to reshape w to be a column vector of shape (2, 1); # we can then broadcast it directly against x to produce the same 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
更多关于Numpy的内容,请看官方文件http://docs./doc/numpy/reference/
SciPy
SciPy库基于Numpy库,提供了许多操作数组array的函数,官方文件http://docs./doc/scipy/reference/index.html
图片操作
from scipy.misc import imread, imsave, imresize # Read an JPEG image into a numpy array img = 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 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 disk imsave('assets/cat_tinted.jpg', img_tinted)
 
读写matlab文件
scipy.io.loadmat 与scipy.io.savemat,用到请看http://docs./doc/scipy/reference/io.html
’计算点间距离
from scipy.spatial.distance import pdist, squareform # Create the following array where each row is a point in 2D space: x = np.array([[0, 1], [1, 0], [2, 0]]) # 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] d = squareform(pdist(x, 'euclidean'))
Matplotlib
matplotlib.pyplot的作图模块,与matlab中的使用类似
import matplotlib.pyplot as plt # Compute the x and y coordinates for points on a sine curve x = np.arange(0, 3 * np.pi, 0.1) # Plot the points using matplotlib plt.show() # You must call plt.show() to make graphics appear.

多条曲线、图标题、图例、坐标等
import matplotlib.pyplot as plt # Compute the x and y coordinates for points on sine and cosine curves x = np.arange(0, 3 * np.pi, 0.1) # Plot the points using matplotlib plt.xlabel('x axis label') plt.ylabel('y axis label') plt.title('Sine and Cosine') plt.legend(['Sine', 'Cosine'])

与matlab相同,利用subplot分区域作图
import matplotlib.pyplot as plt # Compute the x and y coordinates for points on sine and cosine curves x = np.arange(0, 3 * np.pi, 0.1) # Set up a subplot grid that has height 2 and width 1, # and set the first such subplot as active. # Set the second subplot as active, and make the second plot.

显示图像
from scipy.misc import imread, imresize import matplotlib.pyplot as plt img = imread('assets/cat.jpg') img_tinted = img * [1, 0.95, 0.9] # Show the original image # 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))

|