Python
Python是一種高級(jí)的、動(dòng)態(tài)類型的多范型編程語(yǔ)言。Python代碼通常被認(rèn)為是偽代碼,因?yàn)樗试S您在非常可讀的幾行代碼中表達(dá)非常強(qiáng)大的思想。作為一個(gè)例子,下面是Python中經(jīng)典的快速排序算法的實(shí)現(xiàn):
def quicksort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quicksort(left) + middle + quicksort(right)
print(quicksort([3,6,8,10,1,2,1]))
# Prints "[1, 1, 2, 3, 6, 8, 10]"
Python版本
目前有兩種不同的Python版本,分別是2.7和3.5。Python 3.0引入了許多對(duì)語(yǔ)言不兼容的更改,因此為2.7編寫的代碼可能不能在3.5下工作。
您可以通過運(yùn)行Python-version來(lái)檢查命令行中的Python版本。
基本數(shù)據(jù)類型
與大多數(shù)語(yǔ)言一樣,Python有許多基本類型,包括整數(shù)、浮點(diǎn)數(shù)、布爾值和字符串。這些數(shù)據(jù)類型的使用方式與其他編程語(yǔ)言很相似。
數(shù)字:整數(shù)和浮點(diǎn)數(shù)可以從其他語(yǔ)言中得到:
x = 3
print(type(x)) # Prints "<class 'int'>"
print(x) # Prints "3"
print(x + 1) # Addition; prints "4"
print(x - 1) # Subtraction; prints "2"
print(x * 2) # Multiplication; prints "6"
print(x ** 2) # Exponentiation; prints "9"
x += 1
print(x) # Prints "4"
x *= 2
print(x) # Prints "8"
y = 2.5
print(type(y)) # Prints "<class 'float'>"
print(y, y + 1, y * 2, y ** 2) # Prints "2.5 3.5 5.0 6.25"
注意,與許多語(yǔ)言不同的是,Python不支持增量(x++)或遞減(x--)操作符。
Python也有用于復(fù)數(shù)的內(nèi)置類型;您可以在文檔中找到所有的細(xì)節(jié)。
布爾值:Python實(shí)現(xiàn)了布爾邏輯的所有常用操作符,但使用的是英語(yǔ)單詞而不是符號(hào)(&&等等):
t = True
f = False
print(type(t)) # Prints "<class 'bool'>"
print(t and f) # Logical AND; prints "False"
print(t or f) # Logical OR; prints "True"
print(not t) # Logical NOT; prints "False"
print(t != f) # Logical XOR; prints "True"
字符串:Python對(duì)字符串有很大的支持:
hello = 'hello' # String literals can use single quotes
world = "world" # or double quotes; it does not matter.
print(hello) # Prints "hello"
print(len(hello)) # String length; prints "5"
hw = hello + ' ' + world # String concatenation
print(hw) # prints "hello world"
hw12 = '%s %s %d' % (hello, world, 12) # sprintf style string formatting
print(hw12) # prints "hello world 12"
String對(duì)象有很多有用的方法;例如:
s = "hello"
print(s.capitalize()) # Capitalize a string; prints "Hello"
print(s.upper()) # Convert a string to uppercase; prints "HELLO"
print(s.rjust(7)) # Right-justify a string, padding with spaces; prints " hello"
print(s.center(7)) # Center a string, padding with spaces; prints " hello "
print(s.replace('l', '(ell)')) # Replace all instances of one substring with another;
# prints "he(ell)(ell)o"
print(' world '.strip()) # Strip leading and trailing whitespace; prints "world"
您可以在文檔中找到所有字符串方法
容器
Python包括幾個(gè)內(nèi)置的容器類型:列表、字典、集合和元組。
列表
列表是Python的一個(gè)數(shù)組,但是可以調(diào)整,并且可以包含不同類型的元素:
xs = [3, 1, 2] # Create a list
print(xs, xs[2]) # Prints "[3, 1, 2] 2"
print(xs[-1]) # Negative indices count from the end of the list; prints "2"
xs[2] = 'foo' # Lists can contain elements of different types
print(xs) # Prints "[3, 1, 'foo']"
xs.append('bar') # Add a new element to the end of the list
print(xs) # Prints "[3, 1, 'foo', 'bar']"
x = xs.pop() # Remove and return the last element of the list
print(x, xs) # Prints "bar [3, 1, 'foo']"
切片(Slicing):除了每次訪問列表元素一次,Python還提供了訪問子列表的簡(jiǎn)明語(yǔ)法;這就是所謂的切片:
nums = list(range(5)) # range is a built-in function that creates a list of integers
print(nums) # Prints "[0, 1, 2, 3, 4]"
print(nums[2:4]) # Get a slice from index 2 to 4 (exclusive); prints "[2, 3]"
print(nums[2:]) # Get a slice from index 2 to the end; prints "[2, 3, 4]"
print(nums[:2]) # Get a slice from the start to index 2 (exclusive); prints "[0, 1]"
print(nums[:]) # Get a slice of the whole list; prints "[0, 1, 2, 3, 4]"
print(nums[:-1]) # Slice indices can be negative; prints "[0, 1, 2, 3]"
nums[2:4] = [8, 9] # Assign a new sublist to a slice
print(nums) # Prints "[0, 1, 8, 9, 4]"
循環(huán):您可以對(duì)列表的元素進(jìn)行循環(huán)/遍歷:
animals = ['cat', 'dog', 'monkey']
for animal in animals:
print(animal)
# Prints "cat", "dog", "monkey", each on its own line.
如果您想要訪問循環(huán)體中的每個(gè)元素的索引,請(qǐng)使用內(nèi)置的枚舉(enumerate)函數(shù):
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
列表理解:在編程時(shí),我們經(jīng)常需要將一種類型的數(shù)據(jù)轉(zhuǎn)換為另一種類型。作為一個(gè)簡(jiǎn)單的例子,考慮下面的代碼計(jì)算平方數(shù):
nums = [0, 1, 2, 3, 4]
squares = []
for x in nums:
squares.append(x ** 2)
print(squares) # Prints [0, 1, 4, 9, 16]
您可以使用列表理解來(lái)簡(jiǎn)化這段代碼:
nums = [0, 1, 2, 3, 4]
squares = [x ** 2 for x in nums]
print(squares) # Prints [0, 1, 4, 9, 16]
列表理解也可以包含條件:
nums = [0, 1, 2, 3, 4]
even_squares = [x ** 2 for x in nums if x % 2 == 0]
print(even_squares) # Prints "[0, 4, 16]"
字典
字典存儲(chǔ)(鍵、值)對(duì),類似于Java中的映射或Javascript中的對(duì)象。你可以這樣使用它:
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"
循環(huán):在字典中對(duì)鍵進(jìn)行迭代是很容易的:
d = {'person': 2, 'cat': 4, 'spider': 8}
for animal in d:
legs = d[animal]
print('A %s has %d legs' % (animal, legs))
# Prints "A person has 2 legs", "A cat has 4 legs", "A spider has 8 legs"
如果您想要訪問鍵值(keys)及其對(duì)應(yīng)的值,請(qǐng)使用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"
字典的理解:這些類似于列表的理解,但是允許你輕松地構(gòu)造字典。例如:
nums = [0, 1, 2, 3, 4]
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}"
集合
集合是不同元素的無(wú)序集合。作為一個(gè)簡(jiǎn)單的例子,請(qǐng)考慮以下內(nèi)容:
animals = {'cat', 'dog'}
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"
循環(huán):在一個(gè)集合上的迭代與遍歷列表的語(yǔ)法相同;然而,由于集合是無(wú)序的,所以您不能對(duì)您訪問集合元素的順序作出假設(shè):
animals = {'cat', 'dog', 'fish'}
for idx, animal in enumerate(animals):
print('#%d: %s' % (idx + 1, animal))
# Prints "#1: fish", "#2: dog", "#3: cat"
集合:像列表和字典一樣,我們可以用集合的理解來(lái)輕松地構(gòu)建集合:
from math import sqrt
nums = {int(sqrt(x)) for x in range(30)}
print(nums) # Prints "{0, 1, 2, 3, 4, 5}"
元組
tuple是一個(gè)(不可變的)有序的值列表。元組在許多方面與列表相似;最重要的區(qū)別之一是,元組可以用作字典中的鍵,也可以作為集合的元素,而列表則不能。這里有一個(gè)簡(jiǎn)單的例子:
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[t]) # Prints "5"
print(d[(1, 2)]) # Prints "1"
方法/函數(shù)
Python函數(shù)是使用def關(guān)鍵字定義的。例如:
def sign(x):
if x > 0:
return 'positive'
elif x < 0:
return 'negative'
else:
return 'zero'
for x in [-1, 0, 1]:
print(sign(x))
# Prints "negative", "zero", "positive"
我們通常會(huì)定義一些函數(shù)來(lái)選擇可選的關(guān)鍵字參數(shù),比如:
def hello(name, loud=False):
if loud:
print('HELLO, %s!' % name.upper())
else:
print('Hello, %s' % name)
hello('Bob') # Prints "Hello, Bob"
hello('Fred', loud=True) # Prints "HELLO, FRED!"
類
在Python中定義類的語(yǔ)法很簡(jiǎn)單:
class Greeter(object):
# Constructor
def __init__(self, name):
self.name = name # Create an instance variable
# Instance method
def greet(self, loud=False):
if loud:
print('HELLO, %s!' % self.name.upper())
else:
print('Hello, %s' % self.name)
g = Greeter('Fred') # Construct an instance of the Greeter class
g.greet() # Call an instance method; prints "Hello, Fred"
g.greet(loud=True) # Call an instance method; prints "HELLO, FRED!"
Numpy
Numpy是Python中科學(xué)計(jì)算的核心庫(kù)。它提供了高性能多維數(shù)組對(duì)象和用于處理這些數(shù)組的工具。如果你已經(jīng)熟悉了MATLAB,你可能會(huì)發(fā)現(xiàn)這個(gè)教程很有用,可以從Numpy開始。
數(shù)組
numpy數(shù)組是一個(gè)值網(wǎng)格,所有類型都是相同類型的,并且被一個(gè)非負(fù)整數(shù)的元組索引。維數(shù)是數(shù)組的秩;數(shù)組的形狀是一個(gè)數(shù)組的數(shù)組,它在每個(gè)維度上給出數(shù)組的大小。
我們可以從嵌套的Python列表中初始化numpy數(shù)組,并使用方括號(hào)訪問元素:
import numpy as np
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"
Numpy還提供了許多用于創(chuàng)建數(shù)組的函數(shù):
import numpy as np
a = np.zeros((2,2)) # Create an array of all zeros
print(a) # Prints "[[ 0. 0.]
# [ 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.]
# [ 7. 7.]]"
d = np.eye(2) # Create a 2x2 identity matrix
print(d) # Prints "[[ 1. 0.]
# [ 0. 1.]]"
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]]"
您可以在文檔中閱讀關(guān)于數(shù)組創(chuàng)建的其他方法。
數(shù)組索引
Numpy提供了幾種索引數(shù)組的方法。
切片:類似于Python列表,可以將numpy數(shù)組切片。由于數(shù)組可能是多維的,所以您必須為數(shù)組的每個(gè)維度指定一個(gè)切片:
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"
您還可以將整型索引與片索引相混合。但是,這樣做會(huì)產(chǎn)生比原始數(shù)組更低級(jí)的數(shù)組。注意,這與MATLAB處理數(shù)組切片的方式有很大的不同:
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 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:
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)"
整數(shù)數(shù)組索引:當(dāng)您使用分段索引到numpy數(shù)組時(shí),生成的數(shù)組視圖將始終是原始數(shù)組的子數(shù)組。相反,整數(shù)數(shù)組索引允許使用來(lái)自另一個(gè)數(shù)組的數(shù)據(jù)構(gòu)造任意的數(shù)組。這是一個(gè)例子:
import numpy as np
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]"
整數(shù)數(shù)組索引的一個(gè)有用的技巧是在矩陣的每一行中選擇或變化(mutating )一個(gè)元素:
import numpy as np
# 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],
# [ 4, 5, 6],
# [ 7, 8, 9],
# [10, 11, 12]])"
# 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
a[np.arange(4), b] += 10
print(a) # prints "array([[11, 2, 3],
# [ 4, 5, 16],
# [17, 8, 9],
# [10, 21, 12]])
布爾數(shù)組索引:布爾數(shù)組索引可以讓你挑選出一個(gè)數(shù)組的任意元素。通常,這種類型的索引用于選擇滿足某些條件的數(shù)組的元素。這是一個(gè)例子:
import numpy as np
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]
# [ 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_idx
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]"
為了簡(jiǎn)潔,我省略了很多關(guān)于numpy數(shù)組索引的細(xì)節(jié);如果你想知道更多,你應(yīng)該閱讀文檔。
數(shù)據(jù)類型
每個(gè)numpy數(shù)組都是相同類型的元素的網(wǎng)格。Numpy提供了一組大型的數(shù)字?jǐn)?shù)據(jù)類型,您可以使用它們來(lái)構(gòu)造數(shù)組。Numpy試圖在創(chuàng)建數(shù)組時(shí)猜測(cè)數(shù)據(jù)類型,但構(gòu)造數(shù)組的功能通常也包括一個(gè)可選的參數(shù),以顯式地指定數(shù)據(jù)類型。這是一個(gè)例子:
import numpy as np
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"
您可以在文檔中閱讀所有關(guān)于numpy數(shù)據(jù)類型的信息。
矩陣運(yùn)算
基本的數(shù)學(xué)函數(shù)在數(shù)組上操作元素,并且可以作為操作符重載和在numpy模塊中的函數(shù):
import numpy as np
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
# [[ 6.0 8.0]
# [10.0 12.0]]
print(x + y)
print(np.add(x, y))
# Elementwise difference; both produce the array
# [[-4.0 -4.0]
# [-4.0 -4.0]]
print(x - y)
print(np.subtract(x, y))
# Elementwise product; both produce the array
# [[ 5.0 12.0]
# [21.0 32.0]]
print(x * y)
print(np.multiply(x, y))
# Elementwise division; both produce the array
# [[ 0.2 0.33333333]
# [ 0.42857143 0.5 ]]
print(x / y)
print(np.divide(x, y))
# Elementwise square root; produces the array
# [[ 1. 1.41421356]
# [ 1.73205081 2. ]]
print(np.sqrt(x))
注意,與MATLAB不同的是,*是元素的乘法,而不是矩陣乘法。我們用dot函數(shù)來(lái)計(jì)算向量的內(nèi)積,將一個(gè)向量乘以一個(gè)矩陣,再乘以矩陣。dot既可以作為numpy模塊中的函數(shù),也可以作為數(shù)組對(duì)象的實(shí)例方法:
import numpy as np
x = 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 219
print(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為在數(shù)組中執(zhí)行計(jì)算提供了許多有用的函數(shù);其中一個(gè)最有用的就是:sum
import numpy as np
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]"
您可以在文檔中找到numpy提供的數(shù)學(xué)函數(shù)的完整列表。
除了使用數(shù)組計(jì)算數(shù)學(xué)函數(shù)外,我們還經(jīng)常需要對(duì)數(shù)組中的數(shù)據(jù)進(jìn)行重構(gòu)或處理。這類操作最簡(jiǎn)單的例子就是轉(zhuǎn)置矩陣;要轉(zhuǎn)置矩陣,只需使用數(shù)組對(duì)象的T屬性:
import numpy as np
x = 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]"
Numpy為操縱數(shù)組提供了更多的函數(shù);您可以在文檔中看到完整的列表。
廣播
廣播是一種強(qiáng)大的機(jī)制,它允許numpy在執(zhí)行算術(shù)運(yùn)算時(shí)使用不同形狀的數(shù)組。通常我們有一個(gè)更小的數(shù)組和一個(gè)更大的數(shù)組,我們希望使用較小的數(shù)組多次來(lái)對(duì)更大的數(shù)組執(zhí)行一些操作。
例如,假設(shè)我們想要在矩陣的每一行中添加一個(gè)常數(shù)向量。我們可以這樣做:
import numpy as np
# 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]])
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 loop
for 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)
然而,當(dāng)矩陣x非常大時(shí),在Python中計(jì)算一個(gè)顯式循環(huán)可能會(huì)比較慢。請(qǐng)注意,將向量v添加到矩陣x的每一行中,就相當(dāng)于將v垂直地堆疊起來(lái),從而形成一個(gè)矩陣vv,然后執(zhí)行x和vv的元素求和。我們可以這樣來(lái)實(shí)現(xiàn)這個(gè)方法:
import numpy as np
# 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]])
v = np.array([1, 0, 1])
vv = np.tile(v, (4, 1)) # Stack 4 copies of v on top of each other
print(vv) # Prints "[[1 0 1]
# [1 0 1]
# [1 0 1]
# [1 0 1]]"
y = x + vv # Add x and vv elementwise
print(y) # Prints "[[ 2 2 4
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]"
:Numpy廣播允許我們?cè)诓粚?shí)際創(chuàng)建v的多個(gè)拷貝的情況下進(jìn)行計(jì)算,使用廣播:
import numpy as np
# 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]])
v = np.array([1, 0, 1])
y = x + v # Add v to each row of x using broadcasting
print(y) # Prints "[[ 2 2 4]
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]"
代碼y=x+v,盡管x有形狀(4,3),v有形狀(3,)因?yàn)閺V播;這行代碼就像v實(shí)際上有形狀(4,3),每一行都是v的拷貝,并且求和是在元素上進(jìn)行的。
廣播兩個(gè)數(shù)組遵循以下規(guī)則:
1.如果數(shù)組沒有相同的秩,則在兩個(gè)形狀都有相同長(zhǎng)度的情況下,將較低級(jí)別數(shù)組的形狀提前結(jié)束。
2.如果兩個(gè)數(shù)組在維度中具有相同的大小,或者在維度中有一個(gè)數(shù)組的大小為1,那么這兩個(gè)數(shù)組在維度上是兼容的。
3.如果在所有維度上兼容,陣列就可以進(jìn)行廣播。
4.在廣播之后,每個(gè)陣列的表現(xiàn)就好像它的形狀等于兩個(gè)輸入陣列的元素最基本的形狀。
5.在任何維度中,一個(gè)數(shù)組的大小是1而另一個(gè)數(shù)組的大小大于1。
如果這種解釋沒有意義,請(qǐng)嘗試從文檔或解釋中閱讀解釋。
支持廣播的功能被稱為通用功能。您可以在文檔中找到所有通用函數(shù)的列表。
以下是一些廣播的應(yīng)用:
import numpy as np
# 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:
# [[ 4 5]
# [ 8 10]
# [12 15]]
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:
# [[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 column 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)
廣播通常會(huì)使您的代碼更加簡(jiǎn)潔和快速,因此您應(yīng)該盡可能地使用它。
Numpy文檔
這個(gè)簡(jiǎn)短的概述涉及了許多您需要了解的關(guān)于numpy的重要內(nèi)容,但是還遠(yuǎn)遠(yuǎn)不夠。查看numpy引用,了解更多關(guān)于numpy的內(nèi)容。
SciPy
Numpy提供了一個(gè)高性能多維數(shù)組和基本工具來(lái)計(jì)算和操作這些數(shù)組。SciPy在此基礎(chǔ)上構(gòu)建,并提供了大量的函數(shù),這些函數(shù)可以在numpy數(shù)組中運(yùn)行,并且對(duì)于不同類型的科學(xué)和工程應(yīng)用程序非常有用。
熟悉SciPy的最好方法是瀏覽文檔。
圖像操作
SciPy提供了一些基本功能來(lái)處理圖像。例如,它具有從磁盤讀取圖像到numpy數(shù)組的功能,將numpy數(shù)組寫入磁盤作為圖像,以及調(diào)整圖像大小。下面是一個(gè)展示這些功能的簡(jiǎn)單示例:
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
# 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 disk
imsave('assets/cat_tinted.jpg', img_tinted)


點(diǎn)之間的距離
SciPy定義了一些有用的函數(shù),用于計(jì)算兩點(diǎn)之間的距離。
scipy.spatial.distance的函數(shù)。p主義者計(jì)算給定集合中所有的點(diǎn)之間的距離:
import numpy as np
from 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)