参考书籍《深度学习实战》杨云、杜飞著

第1章 深度学习的发展介绍

介绍

python是一种非常简单易学的解释性语言。由于强大的开源库支持(numpy,scipy,matplotlib),其广泛应用于科学计算中。如果你励志成为一名数据科学家或数据“攻城狮”,那python就是你必须学会的工具之一。接下来我们将简短的介绍下python, numpy, matplotlib的使用。本章教程内容主要参考于斯坦福大学cs228课程的python教程,详情可使用该网址查看 https://github.com/kuleshov/cs228-material/blob/master/tutorials/python/cs228-python-tutorial.ipynb

在本章中,你将逐步学习以下内容:

  • Python基本使用: 基本数据类型(Containers, Lists, Dictionaries, Sets, Tuples), 函数, 类
  • Numpy: 数组, 数组索引, 数据类型,数组运算, 广播
  • Matplotlib: Plotting, Subplots, Images

Python基本用法

Python是一种面向对象的解释型高级编程语言。很多时候,由于其代码具有高可读性,且只需要数行代码就可以表达复杂的功能,Python看起来简直和伪代码一样。如下所示,为Python实现经典的快速排序算法例子:

def quicksort(arr):if len(arr) <= 1:return arrpivot = arr[int(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]))
[1, 1, 2, 3, 6, 8, 10]

Python 版本

Python有两个差异较大的版本,分别是2.7+和3.4+。由于在3.0版本和2.7版本语言不兼容,因此2.7下的代码有时候在3.4下是行不通的。本教程中,我们使用的是3.8版本。你可以使用python --version命令。查看你所下载的python版本,确保你的python版本符合我们的教程需求。

基本数据类型

和大多数编程语言一样,Python拥有一系列的基本数据类型,比如整型、浮点型、布尔型和字符串等。这些基本数据类型的使用方式和其他语言的使用方式类似。

整型和浮点型

x = 3
print(x, type(x))
3 <class 'int'>
print(x + 1)   # 加;
print(x - 1)   # 减;
print(x * 2)   # 乘;
print(x ** 2)  # 幂乘;
4
2
6
9
x += 1
print(x)  # 打印 "4"
x *= 2
print(x)  # 打印 "8"
4
8
y = 2.5
print(type(y)) # 打印 "<type 'float'>"
print(y, y + 1, y * 2, y ** 2) # 打印 "2.5 3.5 5.0 6.25"
<class 'float'>
2.5 3.5 5.0 6.25
#python不支持(x++) 或(x--) 运算.
print(y++)
  File "C:\Users\23820\AppData\Local\Temp/ipykernel_11896/3264599002.py", line 2print(y++)^
SyntaxError: invalid syntax

布尔型

Python实现了所有的布尔逻辑,但使用的是英语单词(“and”,“or”,“not”)等,而不是我们习惯的操作符("&&","||"等)。

t, f = True, False
print(type(t)) # 打印 "<type 'bool'>"
<class 'bool'>

逻辑运算:

print(t and f) # 逻辑 AND;
print(t or f)  # 逻辑 OR;
print(not t)  # 逻辑 NOT;
print(t != f)  # 逻辑 XOR;
False
True
False
True

字符串

hello = 'hello'   # 字符串可以使用单引号
world = "world"   # 也可以使用双引号
print(hello, len(hello),world)
hello 5 world
hw = hello + ' ' + world  # 字符串拼接
print(hw)  # 打印 "hello world"
hello world
hw12 = '%s %s %d' %(hello, world, 12)  # 按格式输出
print(hw12)  # 打印 "hello world 12"
hello world 12

你也可以将字符串当作是一个对象,其有大量的方法。例如:

s = "hello"
print(s.capitalize())  # 将字符串首字母大写; 打印 "Hello"
print(s.upper())       # 将字符串转换成大写; 打印 "HELLO"
print(s.rjust(7))      # 字符串向右对齐, 使用空格进行站位; 打印 "  hello"
print(s.center(7))     # 字符串居中, 使用空格对左右进行站位; 打印 " hello "
print(s.replace('l', '(ell)'))  # 使用子串代替规定处字符# 打印 "he(ell)(ell)o"
print('   wo  rld '.strip())  # 删除空白字符(开头或结尾); 打印 "wor  ld"
Hello
HELLOhellohello
he(ell)(ell)o
wo  rld

更多字符串操作请参考以下网址(https://docs.python.org/2/library/stdtypes.html#string-methods).

容器

Python有以下几种容器类型:列表(lists)、字典(dictionaries)、集合(sets)和元组(tuples)。

列表(Lists)

在Python中,列表相当于数组,但是列表长度可变,且能包含不同类型元素。

xs = [3, 1, 2]   # 创建列表
print(xs, xs[2])
print(xs[-1])     #负值索引相当于从列表的末端进行反向索引; 打印 "2"
[3, 1, 2] 2
2
xs[2] = 'foo'    # 列表可以包含不同的元素
print(xs)
[3, 1, 'foo']
xs.append('bar') # 添加新元素到列表末端
print(xs)
[3, 1, 'foo', 'bar']
x = xs.pop()     # 移除列表末端元素
print(x, xs)
bar [3, 1, 'foo']

更多列表操作请参考以下网址(https://docs.python.org/2/tutorial/datastructures.html#more-on-lists).

切片(Slicing)

为了同时获取列表中的多个元素,Python提供了一种简洁的语法去访问子列表,这就是切片。

nums = list(range(5))    # range是内置的创建整型列表函数
print(nums)         # 打印 "[0, 1, 2, 3, 4]"
print(nums[2:4])    # 获取索引2-4(排除)的子列表; 打印 "[2, 3]"
print(nums[2:])     # 获取索引2到末的子列表; 打印 "[2, 3, 4]"
print(nums[:2])    # 获取索引开始到2(排除)的子列表; 打印 "[0, 1]"
print(nums[:])     # 获取整个列表; 打印 ["0, 1, 2, 3, 4]"
print(nums[:-1])   # 切片也可以使用负号索引; 打印 ["0, 1, 2, 3]"
nums[2:4] = ['s','we'] # 用新子列表替换指定索引列表中的子列表
print(nums)         # 打印 "[0, 1, s, we, 4]"
[0, 1, 2, 3, 4]
[2, 3]
[2, 3, 4]
[0, 1]
[0, 1, 2, 3, 4]
[0, 1, 2, 3]
[0, 1, 's', 'we', 4]

循环(Loops)

我们可以这样遍历列表中的每一个元素:

animals = ['cat', 'dog', 'monkey']
for animal in animals:print(animal)
cat
dog
monkey

如果想要在循环体内访问每个元素的指针,可以使用内置的枚举(enumerate)函数。注意:起始号0

animals = ['cat', 'dog', 'monkey']
for idx, animal in enumerate(animals):print('#%d: %s' %(idx + 1, animal))
#1: cat
#2: dog
#3: monkey

列表解析(List comprehensions):

在编程的时候,我们常常想要将列表中的每一元素使用特定的表达式进行转换。下面是一个简单例子,将列表中的每个元素转换成它的平方。

nums = [0, 1, 2, 3, 4]
squares = []
for x in nums:squares.append(x ** 2)
print(squares)
[0, 1, 4, 9, 16]

你可以使用更简单的列表解析(list comprehension):

nums = [0, 1, 2, 3, 4]
squares = [x ** 2 for x in nums]
print(squares)
[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)
[0, 4, 16]

字典(Dictionaries)

字典用来储存(键, 值)对,这和Java中的Map差不多。你可以这样使用它:

d = {'cat': 'cute', 'dog': 'furry'}  # 为数据创建字典
print(d['cat'])       # 从字典中获取词条(entry); 打印 "cute"
print('cat' in d)     # 检查字典中是否有给定键值(key); 打印 "True"
cute
True
d['fish'] = 'wet'    # 给定键值,创建词条
print(d['fish'])      # 打印 "wet"
wet
print(d['monkey'])  # KeyError: 'monkey' 键值没有在字典中
---------------------------------------------------------------------------KeyError                                  Traceback (most recent call last)~\AppData\Local\Temp/ipykernel_11896/3201959582.py in <module>
----> 1 print(d['monkey'])  # KeyError: 'monkey' 键值没有在字典中KeyError: 'monkey'
print(d.get('monkey', 'N/A'))  # 获取字典中元素默认值; 打印 "N/A"
print(d.get('fish', 'N/A'))    # 获取字典中元素默认值; 打印 "wet"
N/A
wet
del d['fish']        # 从字典中移除元素
print(d.get('fish', 'N/A')) # "fish" 不在是字典中的键值; 打印 "N/A"
N/A

字典的详细用法请参考以下网址:(https://docs.python.org/2/library/stdtypes.html#dict).

迭代字典:

d = {'人': 2, '猫': 4, '蜘蛛': 8}
for animal in d:legs = d[animal]print(' %s 有 %d 腿' %(animal, legs))
 人 有 2 腿猫 有 4 腿蜘蛛 有 8 腿

你也可以使用iteritems方法进行迭代:

d = {'人': 2, '猫': 4, '蜘蛛': 8}
for animal, legs in d.items():print(' %s 有 %d 腿' %(animal, legs))
 人 有 2 腿猫 有 4 腿蜘蛛 有 8 腿

字典解析(Dictionary comprehensions): 和列表解析类似,字典解析允许你轻松的构造字典,例如:

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)
{0: 0, 2: 4, 4: 16}

集合(Sets)

集合存放着无序的不同元素,在python中,集合使用花括号表示,如果将一个序列转换为集合,那该序列的重复元素将会被剔除,并且原有的顺序也将被打散。例如:

animals = {'cat', 'dog'}
print('cat' in animals)   # 检查是否元素在集合中; 打印 "True"
print('fish' in animals)  # 打印 "False"
True
False
animals.add('fish')      # 向集合中添加元素
print('fish' in animals)
print(len(animals) )      # 集合中的元素个数;
True
3
animals.add('cat')       # 添加一个存在的元素进集合中,其没有变化。
print(len(animals) )
animals.remove('cat')    # 从集合中移除一个元素
print(len(animals) )
3
2

集合循环:虽然集合中的循环语法和列表中的一样,但由于集合是无序的,因此访问集合元素的时候,不能做关于顺序的假设:

animals = {'cat', 'dog', 'fish'}
for idx, animal in enumerate(animals):print('#%d: %s' %(idx + 1, animal))
# 打印 "#1: fish", "#2: dog", "#3: cat"
#1: dog
#2: fish
#3: cat

集合解析(Set comprehensions):和字典,列表一样,你可以很方便地使用集合解析构建集合:

from math import sqrt
print({int(sqrt(x)) for x in range(30)})
{0, 1, 2, 3, 4, 5}

元组(Tuples)

元组是一个(不可改变)有序列表。元组和列表在很多方面都很相似,最大的不同在于,元组可以像字典一样使用键/值对,并且还可以作为集合的元素,而列表不行。例如:

d = {(x, x + 1): x for x in range(10)}  # 通过元组键值创建字典
t =(5, 6)       # 创建元组
print(type(t))
print(d[t])
print(d[(1, 2)])
<class 'tuple'>
5
1
t[0] = 1 # TypeError: 'tuple' object does not support item assignment
---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)~\AppData\Local\Temp/ipykernel_11896/2642684736.py in <module>
----> 1 t[0] = 1 # TypeError: 'tuple' object does not support item assignmentTypeError: 'tuple' object does not support item assignment

Functions

Python使用关键词def来定义函数,例如:

def sign(x):if x > 0:return '正'elif x < 0:return '负'else:return '零'for x in [-1, 0, 1]:print(sign(x))
负
零
正

我们也经常使用可选参数来定义函数,例如:

def hello(name, loud=False):if loud:print('HELLO, %s' % name.upper())else:print('Hello, %s!' % name)hello('Bob')
hello('Fred', loud=True)
Hello, Bob!
HELLO, FRED

类(Classes)

在python中,定义类的语法很直接:

class Greeter:# 构造函数def __init__(self, name):self.name = name  # 创建一个变量实例# 实例方法 def greet(self, loud=False):if loud:print('HELLO, %s!' % self.name.upper())else:print('Hello, %s' % self.name)g = Greeter('Fred')  # 创建一个Greeter类实例
g.greet()            # 调用实例方法; 打印 "Hello, Fred"
g.greet(loud=True)   # 调用实例方法; 打印 "HELLO, FRED!"
Hello, Fred
HELLO, FRED!

Numpy

Numpy是Python中用于科学计算的核心库。其提供了高性能的多维数组对象,以及相关工具。其用法和MATLAB相似,详情请参考如下网址:(http://wiki.scipy.org/NumPy_for_Matlab_Users)

要使用Numpy,首先要导入numpy包:

import numpy as np

数组(Arrays)

numpy数组是由相同数据类型组成的网格,其可以通过非负整型的元组访问。数组维度数量也被称为数组的秩或阶(rank),数组的形状是一个由整型数构成的元组,描述数组不同维度上的大小。我们可以从python内嵌的列表中创建数组,然后利用方括号访问其中的元素:

a = np.array([1, 2, 3])  # 创建秩为1的数组
print(type(a), a.shape, a[0], a[1], a[2])
a[0] = 5                 # 改变数组元素
print(a)
<class 'numpy.ndarray'> (3,) 1 2 3
[5 2 3]
b = np.array([[1,2,3],[4,5,6]])   # 创建秩为2的数组
print(b)
[[1 2 3][4 5 6]]
print(b.shape)   # 查看b的维度
print(b[0, 0], b[0, 1], b[1, 0])
(2, 3)
1 2 4

Numpy同样提供了大量的方法创建数组:

a = np.zeros((2,2))  # 创建2*2的零矩阵
print(a)
[[0. 0.][0. 0.]]
b = np.ones((1,2))   # 创建各元素值为1的1*2矩阵
print(b)
[[1. 1.]]
c = np.full((2,2), 7,) # 创建各元素值为7的2*2矩阵
print(c)
[[7 7][7 7]]
d = np.eye(3)        # 创建3*3的单位矩阵
print(d)
[[1. 0. 0.][0. 1. 0.][0. 0. 1.]]
e = np.random.random((3,3)) # 创建3*3的矩阵,使用随机数填充值
print(e)
[[0.9626719  0.66113208 0.71213143][0.04312188 0.54593384 0.61953381][0.03517364 0.11899646 0.29335206]]

数组索引

切片:和Python列表类似,numpy数组可以使用切片语法。因为数组可以是多维的,所以你必须为每个维度指定好切片:

import numpy as np
# 创建秩为2,形状为(3,4)的数组
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
print(a)
#取出第1行,2列开始的,形状为(2,2)的子数组
# [[2 3]
#  [6 7]]
b = a[:2, 1:3]
print(b)
[[ 1  2  3  4][ 5  6  7  8][ 9 10 11 12]]
[[2 3][6 7]]

切取的子数组实际上是原数组的一份浅备份,因此修改子数组,原始数组也将受到修改,例如:

print('原始a:',a[0, 1]  )
b[0, 0] = 77    # b[0, 0] 和a[0, 1]共享同一内存
print('修改b后的a:',a[0, 1] )
原始a: 2
修改b后的a: 77

你也可以混合整数索引以及切片索引访问数组,但是,这会生成一个秩少于原始数组的子数组。注意:这和MATLAB处理的数组切片有些不同。

# 创建形状(3,4)秩为2的numpy数组
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
print(a)
[[ 1  2  3  4][ 5  6  7  8][ 9 10 11 12]]

Numpy有两种数组切片方式:1.混合整数索引和切片,生成低秩子数组;2.仅使用切片,生成原始数组同秩的子数组。

row_r1 = a[1, :]    # 秩为1,数组a的第二行子数组
row_r2 = a[1:2, :]  # 秩为2,数组a的第二行子数组
row_r3 = a[[1], :]  # 秩为2,数组a的第二行子数组
print('秩为1:',row_r1, row_r1.shape )
print('秩为2:',row_r2, row_r2.shape)
print('秩为2:',row_r3, row_r3.shape)
秩为1: [5 6 7 8] (4,)
秩为2: [[5 6 7 8]] (1, 4)
秩为2: [[5 6 7 8]] (1, 4)
# 作用在列上同样适用:
col_r1 = a[:, 1] # 秩为1,数组a的第二列子数组
col_r2 = a[:, 1:2] # 秩为2,数组a的第二列子数组
print('秩为1:',col_r1, col_r1.shape)
print('秩为2:')
print(col_r2, col_r2.shape)
秩为1: [ 2  6 10] (3,)
秩为2:
[[ 2][ 6][10]] (3, 1)

整型数组索引:当我们使用切片索引数组时,得到的总是原数组的子数组。整型数组索引允许我们利用其它数组中的数据构建一个新的数组。例如:

a = np.array([[1,2], [3, 4], [5, 6]])# 整型数组索引示例。
# 返回的数组形状为(3,)
print(a[[0, 1, 2], [0, 1, 0]])# 上述整型数组索引相等于下列索引:
print(np.array([a[0, 0], a[1, 1], a[2, 0]]))
[1 4 5]
[1 4 5]
#当使用整型数组索引时,你可以重复索引同一个数组元素:
print(a[[0, 0], [1, 1]])# 上述整型数组索引相等于下列索引:
print(np.array([a[0, 1], a[0, 1]]))
[2 2]
[2 2]

整型数组索引的一个小技巧是从矩阵的每一行中选择或改变元素:

# 创建新数组用于选择元素
a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
print(a)
# 创建数组索引。
b = np.array([0, 2, 0, 1])
print('使用数组[0, 2, 0, 1]索引矩阵a中的每一行')
# 使用数组b中的索引选择矩阵a每一行中的特定元素。
print(a[np.arange(4), b])  # 打印 "[ 1  6  7 11]"#使用数组b中的索引改变矩阵a每一行中的特定元素。
print('使用数组[0, 2, 0, 1]索引矩阵a中的每一行,将其加10')
a[np.arange(4), b] += 10
print(a)
[[ 1  2  3][ 4  5  6][ 7  8  9][10 11 12]]
使用数组[0, 2, 0, 1]索引矩阵a中的每一行
[ 1  6  7 11]
使用数组[0, 2, 0, 1]索引矩阵a中的每一行,将其加10
[[11  2  3][ 4  5 16][17  8  9][10 21 12]]

布尔型数组索引:布尔型索引让你任意挑选数组中的元素,这种类型索引频繁的用于条件语句下的元素选取。例如:

import numpy as np
a = np.array([[1,2], [3, 4], [5, 1]])
print(a)
bool_idx =(a > 2)
# 寻找大于2的数组元素,返回相同形状的布尔型数组,其每个元素为a > 2的布尔值
print(bool_idx)
[[1 2][3 4][5 1]]
[[False False][ True  True][ True False]]
# 我们可以使用布尔数组索引去构造一个秩为1的数组,其元素与布尔数组的真值相对应。
print(a[bool_idx])# 我们也可以将上述内容简洁的用一行语句表达:
print(a[a > 2])
[3 4 5]
[3 4 5]

数据类型(Datatypes)

Numpy提供了大量的数据类型去构造数组,Numpy会尝试猜测你创建的数组的数据类型,但构造函数的数组通常也会可选择的显式指明其数据类型。例如:

x = np.array([1, 2])  # 让numpy自己选择数据类型
y = np.array([1.0, 2.0])  # 让numpy自己选择数据类型
z = np.array([1, 2], dtype=np.int64)  # 显式的规定数据类型print(x.dtype, y.dtype, z.dtype)
int32 float64 int64

详细的数据类型说明,可参考如下网址:(http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html).

数组数学运算

数组中基本的数学运算操作是按数组元素进行的,并且重载操作以及函数都可以使用:

x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[5,6],[7,8]], dtype=np.float64)# 按元素求和;两种方式都可以使用;
print(x + y)
print(np.add(x, y))
[[ 6.  8.][10. 12.]]
[[ 6.  8.][10. 12.]]
# 按元素相减;
print(x - y)
print(np.subtract(x, y))
[[-4. -4.][-4. -4.]]
[[-4. -4.][-4. -4.]]
# 按元素乘;
print(x * y)
print(np.multiply(x, y))
[[ 5. 12.][21. 32.]]
[[ 5. 12.][21. 32.]]
# 按元素除
# [[ 0.2         0.33333333]
#  [ 0.42857143  0.5       ]]
print(x / y)
print(np.divide(x, y))
[[0.2        0.33333333][0.42857143 0.5       ]]
[[0.2        0.33333333][0.42857143 0.5       ]]
# 按元素取平方根;
# [[ 1.          1.41421356]
#  [ 1.73205081  2.        ]]
print(np.sqrt(x))
[[1.         1.41421356][1.73205081 2.        ]]

注意:和MATLAB不同,*在numpy中是按元素乘,而在MATLAB中是矩阵乘。在numpy中我们使用dot函数计算向量内积(点积),矩阵乘矩阵,以及矩阵乘向量等操作。dot可以当作函数在numpy中使用,也可作为数组对象的实例方法:

x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])v = np.array([9,10])
w = np.array([11, 12])# 向量内积;都将生成219
print(v.dot(w))
print(np.dot(v, w))
219
219
# 矩阵 / 向量乘积; 都将生成秩为1的数组[29 67]。
print(x.dot(v))
print(np.dot(x, v))
[29 67]
[29 67]
# 矩阵 / 矩阵乘积;都将生成秩为2的数组
# [[19 22]
#  [43 50]]
print(x.dot(y))
print(np.dot(x, y))
[[19 22][43 50]]
[[19 22][43 50]]

Numpy还提供了许多有用的数组计算函数;其中最常用的是 sum 函数:

x = np.array([[1,2],[3,4]])print(np.sum(x))  # 计算所有元素的累加和;打印 "10"
print(np.sum(x, axis=0))  # 计算每一列的累加和;打印"[4 6]"
print(np.sum(x, axis=1))  # 计算每一行的累加和;打印"[3 7]"
10
[4 6]
[3 7]

更多numpy的数学函数参见如下网址:(http://docs.scipy.org/doc/numpy/reference/routines.math.html).

除了使用数组进行数学计算,我们还频繁的使用reshape或者其他方法操纵数组数据。例如:要转置一个矩阵,简单的使用数组对象的T属性即可:

print(x)
print(x.T)
[[1 2][3 4]]
[[1 3][2 4]]
v = np.array([[1,2,3]])
print(v)
print(v.T)
[[1 2 3]]
[[1][2][3]]

广播(Broadcasting)

广播提供了强大的机制允许numpy在不同形状的数组中执行数学操作。我们经常会遇到小数组和大数组相乘的情况,比如图片数据矩阵与权重矩阵。使用广播机制将提高你的代码质量以及运算效率。

例如,假设我们想在矩阵的每一行中都加上一个常数向量。我们可以这样做:

# 矩阵x的每一行加上向量v,将结果储存在矩阵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形状相同的空矩阵。# 使用显式循环完成上述操作。
for i in range(4):y[i, :] = x[i, :] + vprint(y)
[[ 2  2  4][ 5  5  7][ 8  8 10][11 11 13]]

这样做是有效的,但当矩阵x特别大时,在Python中计算显式循环就将变得非常缓慢。其实将向量v加到矩阵x的每一行相当于将向量v拷贝多次垂直堆叠成矩阵vv,然后对矩阵x与矩阵vv进行按元素求和。我们也可以这样实现该方法:

vv = np.tile(v,(4, 1))  # 拷贝4次向量v,然后将其堆叠起来。
print(vv)                 # 打印   "[[1 0 1]#          [1 0 1]#          [1 0 1]#          [1 0 1]]"
[[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广播机制允许我们不创建多次向量v备份的情况下执行该计算:

import numpy as np# 矩阵x的每一行加上向量v,将结果储存在矩阵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  # 使用广播将v加到矩阵的每一行上。
print(y)
[[ 2  2  4][ 5  5  7][ 8  8 10][11 11 13]]

由于广播机制的原因,即使x的形状为(4, 3)v 的形状为(3,),表达式y = x + v依然可以执行;这就好像将v拷贝重塑为(4, 3)的矩阵,然后进行按元素相加。
对两个数组使用广播机制要遵守下列规则:

  1. 如果数组的秩不同,将秩较小的数组进行扩展,直到两个数组的尺寸长度都一样。
  2. 如果两个数组在某个维度上的长度是一样的,或者其中一个数组在该维度上长度为1,那么我们就说这两个数组在该维度上是相容的。
  3. 如果两个数组在所有维度上都是相容的,他们就能使用广播。
  4. 广播之后,两个数组的尺寸将和较大的数组尺寸一样。
  5. 在任何一个维度上,如果一个数组的长度为1,另一个数组长度大于1,那么在该维度上,就好像是对第一个数组进行了复制。

如果感觉没有解释清楚,详细文档请参考以下网址:(http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html) 或者更具体的解释(http://wiki.scipy.org/EricsBroadcastingDoc).

支持广播机制的函数也被称为通用函数(universal functions)。你可以更具以下网址查看所有的通用函数(http://docs.scipy.org/doc/numpy/reference/ufuncs.html#available-ufuncs).

以下是广播一些应用:

#计算向量外积
v = np.array([1,2,3])  # v 形状(3,)
w = np.array([4,5])    # w 形状(2,)
# 要计算外积,我们首先要重塑v为一列(3, 1),
# 然后将其与w(2,)相乘,输出一个形状为(3,2)的矩阵,其就是v与w的外积。
print(np.reshape(v,(3, 1)) * w)
[[ 4  5][ 8 10][12 15]]
# 将向量加到矩阵中的每一行
x = np.array([[1,2,3], [4,5,6]])
# x 形状(2, 3) ,v 形状(3,) ,广播之后的形状(2, 3),
print(x + v)
[[2 4 6][5 7 9]]
# 将向量加到矩阵的每一列
# x 形状(2, 3),w 形状(2,).如果我们将x进行转置,那其形状就被重塑为(3, 2),
# 然后将其与w进行广播,就可以生成形状为(3,2)的矩阵;
# 我们最后再将结果进行转置,就可以得到形状为(2,3)的矩阵;
# 其结果就是将向量w加到矩阵x的每一列
print((x.T + w).T)
[[ 5  6  7][ 9 10 11]]
#另一种更简单的方法是将w重塑为形状为(2,1)的行向量;
#然后直接与x进行广播就可产生相同的结果
#注意(2,)表示的是秩为1的向量,(2,1)表示的是秩为2的矩阵
print(x + np.reshape(w,(2, 1)))
[[ 5  6  7][ 9 10 11]]
# 矩阵各元素乘以一个常数:
# x 形状(2, 3). Numpy 将标量作为数组();
print(x * 2)
[[ 2  4  6][ 8 10 12]]

广播使你的代码简洁而高效,因此你应该尽可能的使用广播操作。

以上仅仅是一些numpy的重要用法,但其功能远不止这些。详细的文档请参考如下网址:(http://docs.scipy.org/doc/numpy/reference/)

Matplotlib

Matplotlib是一个绘图工具库。下面我们简短的介绍下matplotlib.pyplot 模块,其用法和MATLAB相似。

import matplotlib.pyplot as plt
#使用以下IPython命令行,可以使得绘图结果嵌入到notebook中
%matplotlib inline

绘制(Plotting)

matplotlib最重要的函数就是绘制函数plot,其允许你绘制2D数据。例如:

# 使用sin三角函数计算x与y的坐标点
x = np.arange(0, 3 * np.pi, 0.1)
y = np.sin(x)
# 使用matplotlib绘制坐标点
plt.plot(x, y)
[<matplotlib.lines.Line2D at 0x20d10089b00>]



添加标题,说明,坐标轴标记到图表中:

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'])
<matplotlib.legend.Legend at 0x20d13595978>



子图(Subplots)

你可以使用subplot函数在一副图中绘制不同的子图。例如:

# 使用sin以及cos函数计算x与y的坐标点
x = np.arange(0, 3 * np.pi, 0.1)
y_sin = np.sin(x)
y_cos = np.cos(x)
# 设置子图网格,其高为2,宽为1.
# 设置使用第一张子图
plt.subplot(2, 1, 1)
# 绘制第一张子图
plt.plot(x, y_sin)
plt.title('Sine')
# 设置使用第二张子图,并绘制。
plt.subplot(2, 1, 2)
plt.plot(x, y_cos)
plt.title('Cosine')
# 显示图表.
plt.show()



更多内容你可以参考如下网址:(http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.subplot).

import numpy as np
from scipy.misc import imresize
from imageio import imread
import matplotlib.pyplot as pltimg = imread('kitten.jpg')
img_tinted = img * [1, 0.95, 0.6]# 显示原始图片
plt.subplot(1, 2, 1)
plt.imshow(img)# 显示着色后的图片
plt.subplot(1, 2, 2)plt.imshow(np.uint8(img_tinted))
plt.show()

《深度学习实战》第1章 深度学习的发展介绍相关推荐

  1. Keras深度学习实战(4)——深度学习中常用激活函数和损失函数详解

    Keras深度学习实战(4)--深度学习中常用激活函数和损失函数详解 常用激活函数 Sigmoid 激活函数 Tanh 激活函数 ReLU 激活函数 线性激活函数 Softmax 激活函数 损失函数 ...

  2. PyTorch强化学习实战(1)——强化学习环境配置与PyTorch基础

    PyTorch强化学习实战(1)--强化学习环境配置与PyTorch基础 0. 前言 1. 搭建 PyTorch 环境 2. OpenAI Gym简介与安装 3. 模拟 Atari 环境 4. 模拟 ...

  3. 深度学习实战 第6章卷积神经网络笔记

    第6章 卷积神经网络 **卷积神经网络(Convolutional Neural Network,CNN)**是在实际应用中最为成功的一种神经网络,其专门用于处理格状结构数据,比如图片数据就可以看成是 ...

  4. HCNP路由交换学习指南(第一章)学习笔记

    什么是路由? IP网络最基本的功能就是为处于网络中不同位置的设备之间实现数据互通. 为了实现这个功能,网络中的设备需具备将IP报文从员转发到目的地的能力. 以路由器为例,当一台路由器收到一个IP报文时 ...

  5. 《机器学习系列教程》第三章 深度学习基础

    @[第三章 深度学习基础] 第三章 深度学习基础 3.1 基本概念 3.1.1 神经网络组成? 为了描述神经网络,我们先从最简单的神经网络说起. 感知机 简单的感知机如下图所示: [外链图片转存失败( ...

  6. 阅码场独家在线课程:《深度学习实战大数据》早鸟报名

    目前市面主流人工智能课程主要分两类,一个是机器学习理论课程,偏理论,晦涩难懂,尤其对于没有相关基础的人入门有一定的门槛:另外一类主要是工具类,主要介绍如何通过主流的工具(如Tensorflow)来搭建 ...

  7. 深度学习必备书籍——《Python深度学习 基于Pytorch》

    作为一名机器学习|深度学习的博主,想和大家分享几本深度学习的书籍,让大家更快的入手深度学习,成为AI达人!今天给大家介绍的是:<Python深度学习 基于Pytorch> 文章目录 一.背 ...

  8. 【强化学习实战】基于gym和tensorflow的强化学习算法实现

    [新智元导读]知乎专栏强化学习大讲堂作者郭宪博士开讲<强化学习从入门到进阶>,我们为您节选了其中的第二节<基于gym和tensorflow的强化学习算法实现>,希望对您有所帮助 ...

  9. 【阅读笔记】联邦学习实战——联邦个性化推荐案例

    联邦学习实战--联邦个性化推荐案例 前言 1. 引言 2. 传统的集中式个性化推荐 2.1 矩阵分解 2.2 因子分解机 3. 联邦矩阵分解 3.1 算法详解 3.2 详细实现 4 联邦因子分解机 4 ...

  10. 一文弄懂元学习 (Meta Learing)(附代码实战)《繁凡的深度学习笔记》第 15 章 元学习详解 (上)万字中文综述

    <繁凡的深度学习笔记>第 15 章 元学习详解 (上)万字中文综述(DL笔记整理系列) 3043331995@qq.com https://fanfansann.blog.csdn.net ...

最新文章

  1. [再寄小读者之数学篇](2014-11-19 等差数列的部分和)
  2. 软考高项之各大管理计划内容-攻坚记忆
  3. 解聘!“双一流”教授被通报批评
  4. C/C++程序员必须熟悉的开源库
  5. 【例1】 给定n(n>=1),用递归的方法计算1+2+3+4+...+(n-1)+n。
  6. 渗透测试之Nmap命令(二)
  7. 解决 ‘Could not fetch URL https://pypi.python.org’的问题
  8. window 服务(三)
  9. dubbo k8s 服务发现_记一次dubbo服务发现导致的OOM
  10. 图片转excel方法
  11. 计算机怎么配置IP地址,如何设置电脑IP地址?
  12. 尚硅谷SpringCloud2020简单学习记录(个人用)65-73集
  13. 直流无刷电机与永磁同步电机区别
  14. arm linux开发板tar移植
  15. kettle工具实现数据的颗粒度转换以及珊瑚橘商务规划计算
  16. 根据面阵相机拍摄的速度和传送带运动的速度将拍摄的实物图片的每一帧进行无缝拼接使其成为一张完整的图片的全部流程以及c++代码
  17. 认识自我,还需吾日三省吾身
  18. c语言 获取文件修改时间,C语言中用于修改文件的存取时间的函数使用
  19. 新兴的外贸获客系统:孚盟360度获客矩阵,高效助力外贸客户开发
  20. ARCore之路-技术原理(一)

热门文章

  1. 《汇编语言》上机实验内容//理解
  2. 竞品分析:抖音搜索VS快手搜索
  3. 第一次写博客,请大家多多包涵...
  4. Hadamard积 学习笔记(张贤达《矩阵分析与应用》)
  5. 错误记录:ERROR: Cannot determine archive format of C:\Users\lbt10\AppData\Local\Temp\pip-req-build-0wduy
  6. 全国计算机设计大赛参后感
  7. [威客任务]¥800.00 JS实现网站联动三级选项
  8. PeopleSoft 代码聚合运算工具类
  9. java如何实现登陆功能_利用javaweb实现登陆功能!
  10. android赛车游戏编写,编程赛车Code Racer