深度学习python及numpy等第三方包基础
文章目录
- python deep learning基础
- 一,python 容器类型
- 1,列表
- 1.1,列表,就是python中的数组,长度可变,且能包含不同类型元素,
- 1.2,切片操作,可用切片方式获取列表中的元素
- 1.3 循环Loops:enumerate 函数访问每个循环元素指针
- 1.4 列表推导List comprehensions,转换数据类型时可以简化代码
- 1.5 List列表常用函数:index(x),extend(L),insert(i, x),count(x),remove(x),pop([i]),sort(cmp=None, key=None, reverse=False),sort(cmp=None, key=None, reverse=False)等
- 1.6 更多函数如popleft,del a【0】,map,用作堆栈,函数工具栏等更多信息详见以下网址
- 2,字典
- 2.1,字典存储键对值,d['fish'] = 'wet' ,fish为键,wet为值
- 2.2,循环loops,在字典中,用键来迭代更加容易。如果你想要访问键和对应的值,那就使用iteritems方法:
- 2.3, ,字典推导Dictionary comprehensions:和列表推导类似,但是允许你方便地构建字典。
- 2.4字典常用操作:d[key]=value(key 作,为声明变量),del,key in d,clear,copy,iteritems,append,pop,popitem,values,viewvalues等,更多见网址:
- 3,集合
- 3.1,合集是不同个体的无序集合
- 3.2,循环Loops:在集合中循环的语法和在列表中一样,但是集合是无序的,所以你在访问集合的元素的时候,不能做关于顺序的假设。
- 3.3,集合推导Set comprehensions:和字典推导一样,可以很方便地构建集合:
- 3.4常用函数如 set<=other,set>=other,isdisjoint(other),union(*others),intersection(*others),c,symmetric_difference(other),copy,update(*others),difference_update(*others),pop,discarld,remove,add
- 4,元组Tuples
- 4.1 元组是一个值的有序列表(不可改变)。
- 4.2 从很多方面来说,元组和列表都很相似。和列表最重要的不同在于,元组可以在字典中用作键,还可以作为集合的元素,而列表不行。
- Sequence Types — list, tuple, range常用函数
- 其他常用函数如cmp等及range,class,function,File,memoryview等目标详见网址:
- 补充1:string
- 补充2:int,float,complex常用操作
- 第一部分附录
- 二,Numpy
- 1,创建数组
- 2,访问数组
- 3,数据类型
- 4,数组计算
- 4.1,基本数学计算函数会对数组中元素逐个进行计算,既可以利用操作符重载,也可以使用函数方式:
- 4.2*是逐个相乘而不是矩阵乘法
- 4.3更多sum(),.T等函数参看如下网址
- 4.4,python的广播机制(无需循环一个个操作,或复制创建一个同样大小矩阵再操作)
- 5,更多Numpy文献
- 三,Scipy模块
- 四,Matplotlib
python deep learning基础
一,python 容器类型
1,列表
1.1,列表,就是python中的数组,长度可变,且能包含不同类型元素,
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
x = xs.pop() #除去元素 Remove and return the last element of the list
print x, xs # Prints "bar [3, 1, 'foo']"
1.2,切片操作,可用切片方式获取列表中的元素
nums = 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]"
1.3 循环Loops:enumerate 函数访问每个循环元素指针
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
1.4 列表推导List comprehensions,转换数据类型时可以简化代码
nums = [0, 1, 2, 3, 4]
even_squares = [x ** 2 for x in nums if x % 2 == 0]# x ** 2 是操作,if x % 2 == 0是条件
print even_squares # Prints "[0, 4, 16]"
1.5 List列表常用函数:index(x),extend(L),insert(i, x),count(x),remove(x),pop([i]),sort(cmp=None, key=None, reverse=False),sort(cmp=None, key=None, reverse=False)等
>>> a = [66.25, 333, 333, 1, 1234.5]
>>> print a.count(333), a.count(66.25), a.count('x')
2 1 0
>>> a.insert(2, -1)
>>> a.append(333)
>>> a
[66.25, 333, -1, 333, 1, 1234.5, 333]
>>> a.index(333)
1
>>> a.remove(333)
>>> a
[66.25, -1, 333, 1, 1234.5, 333]
>>> a.reverse()
>>> a
[333, 1234.5, 1, 333, -1, 66.25]
>>> a.sort()
>>> a
[-1, 1, 66.25, 333, 333, 1234.5]
>>> a.pop()
1234.5
>>> a
[-1, 1, 66.25, 333, 333]
1.6 更多函数如popleft,del a【0】,map,用作堆栈,函数工具栏等更多信息详见以下网址
https://docs.python.org/2/tutorial/datastructures.html#using-lists-as-queues
2,字典
2.1,字典存储键对值,d[‘fish’] = ‘wet’ ,fish为键,wet为值
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') # 不存在默认N/A,"fish" is no longer a key; prints "N/A"
2.2,循环loops,在字典中,用键来迭代更加容易。如果你想要访问键和对应的值,那就使用iteritems方法:
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 spider has 8 legs", "A cat has 4 legs"
如果你想要访问键和对应的值,那就使用iteritems方法:
d = {'person': 2, 'cat': 4, 'spider': 8}
for animal, legs in d.iteritems():
print 'A %s has %d legs' % (animal, legs)
# Prints "A person has 2 legs", "A spider has 8 legs", "A cat has 4 legs"
可操作后再循环
>>> for i in reversed(xrange(1,10,2)):
... print i
2.3, ,字典推导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 # Prints "{0: 0, 2: 4, 4: 16}"
2.4字典常用操作:d[key]=value(key 作,为声明变量),del,key in d,clear,copy,iteritems,append,pop,popitem,values,viewvalues等,更多见网址:
https://docs.python.org/2/library/stdtypes.html#dict
>>> class Counter(dict):
... def __missing__(self, key):
... return 0
>>> c = Counter()
>>> c['red']
0
>>> c['red'] += 1
>>> c['red']
1
3,集合
3.1,合集是不同个体的无序集合
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}"
3.2,循环Loops:在集合中循环的语法和在列表中一样,但是集合是无序的,所以你在访问集合的元素的时候,不能做关于顺序的假设。
animals = {'cat', 'dog', 'fish'}
for idx, animal in enumerate(animals):
print '#%d: %s' % (idx + 1, animal)
# Prints "#1: fish", "#2: dog", "#3: cat"
3.3,集合推导Set comprehensions:和字典推导一样,可以很方便地构建集合:
from math import sqrt
nums = {int(sqrt(x)) for x in range(30)}
print nums # Prints "set([0, 1, 2, 3, 4, 5])"
3.4常用函数如 set<=other,set>=other,isdisjoint(other),union(*others),intersection(*others),c,symmetric_difference(other),copy,update(*others),difference_update(*others),pop,discarld,remove,add
参看中文翻译博客
https://blog.****.net/rubikchen/article/details/80800375
4,元组Tuples
4.1 元组是一个值的有序列表(不可改变)。
4.2 从很多方面来说,元组和列表都很相似。和列表最重要的不同在于,元组可以在字典中用作键,还可以作为集合的元素,而列表不行。
例子如下:
d = {(x, x + 1): x for x in range(10)} # Create a dictionary with tuple keys
print d
t = (5, 6) # Create a tuple
print type(t) # Prints "<type 'tuple'>"
print d[t] # Prints "5"
print d[(1, 2)] # Prints "1"
元组数据不可修改;
>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])
Sequence Types — list, tuple, range常用函数
其他常用函数如cmp等及range,class,function,File,memoryview等目标详见网址:
https://docs.python.org/2/library/functions.html#
补充1:string
常用函数:str.join(iterable),参考以下网址:
https://www.cnblogs.com/shenbuer/p/7833953.html
补充2:int,float,complex常用操作
其中c.conjugate()返回复数c的共轭
divmod(x, y),返回的是a//b(商)以及a%b(余数),返回结果类型为tuple
实例:
>>> divmod(9,2)
(4, 1)
>>> divmod(9,2)[0]
4
>>> divmod(9,2)[1]
1
第一部分附录
1,以上参考https://docs.python.org/3.6/library/stdtypes.html#boolean-operations-and-or-not中的python3.6
及2.7https://docs.python.org/2/library/stdtypes.html#sequence-types-str-unicode-list-tuple-bytearray-buffer-xrange官方文档
2,更多python标准库,常用函数及第三库介绍可参考https://docs.python.org/3.6/library/index.html
3,官方教程,语法库及官方文档见https://docs.python.org/3.6/
二,Numpy
1,创建数组
1.1,从列表创建数组
import numpy as np
a = np.array([1, 2, 3]) # Create a rank 1 array
print 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 array
print a # Prints "[5, 2, 3]"
b = np.array([[1,2,3],[4,5,6]]) # Create a rank 2 array
print b # 显示一下矩阵b
print b.shape # Prints "(2, 3)"
print b[0, 0], b[0, 1], b[1, 0] # Prints "1 2 4"
1.2,其他方法创建数组
import numpy as np
a = np.zeros((2,2)) # 0数组,Create an array of all zeros
print a # Prints "[[ 0. 0.]
# [ 0. 0.]]"
b = np.ones((1,2)) # 1数组,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]]"
2,访问数组
2.1,切片操作访问(a:b这种)
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赋值相当于操作原数组,b[0, 0] is the same piece of data as a[0, 1]
print a[0, 1] # Prints "77"
可以同时使用整型和切片语法来访问数组。但是,这样做会产生一个比原数组低阶的新数组。需要注意的是,这里和MATLAB中的情况是不同的:
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)"
2.2,整型数组访问(a,b,c这种)
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]"
``
更改每一行元素操作(整型)
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]])
2.3 布尔型访问数组(条件)
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]]"
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]"
3,数据类型
Numpy会尝试猜测数组的数据类型,你也可以通过参数直接指定数据类型,例子如下:
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"
4,数组计算
4.1,基本数学计算函数会对数组中元素逐个进行计算,既可以利用操作符重载,也可以使用函数方式:
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)
4.2*是逐个相乘而不是矩阵乘法
4.3更多sum(),.T等函数参看如下网址
https://docs.scipy.org/doc/numpy/reference/routines.math.html
4.4,python的广播机制(无需循环一个个操作,或复制创建一个同样大小矩阵再操作)
对两个数组使用广播机制要遵守下列规则:
- 如果数组的秩不同,使用1来将秩较小的数组进行扩展,直到两个数组的尺寸的长度都一样。
如果两个数组在某个维度上的长度是一样的,或者其中一个数组在该维度上长度为1,那么我们就说这两个数组在该维度上是相容的。
如果两个数组在所有维度上都是相容的,他们就能使用广播。
如果两个输入数组的尺寸不同,那么注意其中较大的那个尺寸。因为广播之后,两个数组的尺寸将和那个较大的尺寸一样。
在任何一个维度上,如果一个数组的长度为1,另一个数组长度大于1,那么在该维度上,就好像是对第一个数组进行了复制。
直接运算
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]]"
下面是一些广播机制的使用例子
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 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
更多参考广播机制的文档和解释
https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html
http://scipy.github.io/old-wiki/pages/EricsBroadcastingDoc
5,更多Numpy文献
https://docs.scipy.org/doc/numpy/reference/
三,Scipy模块
0 最好方法是阅读官方文档
https://docs.scipy.org/doc/scipy/reference/index.html
1,图像操作
提供了将图像从硬盘读入到数组的函数,也提供了将数组中数据写入的硬盘成为图像的函数
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)"
操作图像,改变通道,尺寸和保存
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)
2,scipy有很多计算两点之间的距离
scipy.spatial.distance.pdist计算所有两点距离
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
四,Matplotlib
1,matplotlib.pyplot模块绘图
最重要的函数是Plot
更多关于plothttps://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot
import numpy as np
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)
y = np.sin(x)
# Plot the points using matplotlib
plt.plot(x, y)
plt.show() # You must call plt.show() to make graphics appear.
只需要少量工作,就可以一次画不同的线,加上标签,坐标轴标志等。
import numpy as np
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)
y_sin = np.sin(x)
y_cos = np.cos(x)
# Plot the points using 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()
subplot绘制多个图像
可以使用subplot函数来在一幅图中画不同的东西:
import numpy as np
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)
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 plot
plt.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()
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]
# Show the original image
plt.subplot(1, 2, 1)
plt.imshow(img)
# Show the tinted image
plt.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()