1. 深度学习是什么?
通常应用程序并不需要收集真实世界中的数据,也不需要系统地提取这些数据特征,只要有充足的时间,我们的常识与编程技巧足够让我们完成任务,比如你写一个邮箱系统,或者写一个微波炉程序。但有时候不仅仅只有编程技巧所能搞定的,比如判断一张图片中有没有猫的程序,先简化该问题,假设所有图像的高度和宽度都是400像素大小,一个像素点由红绿蓝3个值构成,那么一张图像就由近50w个数值表示(400*400*3),我们需要从这些数据中寻找特征,如边缘、质地、形状、眼睛、鼻子等,最终才能判断图像中是否有猫。
解决这个问题需要逆向思考,与其设计一个解决问题的程序,不如从最终的需求入手寻找一个解决方案:“用数据编程”,这是目前机器学习和深度学习的核心思想,即与其枯坐房间里苦思如何设计一个识别猫的程序,不如利用人类肉眼在图像中识别猫的能力,我们收集一些已知包含猫和不包含猫的图像,然后我们的目标就转化成如何从这些图像入手得到一个可以推断图像中是否有猫的函数。这个函数通过我们的知识来针对特定问题选定,例如,我们使用一个二次函数来判断图像中是否有猫,但是像二次函数的参数具体值是通过数据来确定的。
通俗来说,机器学习是一门讨论各式各样的适用于不同问题的函数形式,以及如何使用数据来有效地获取函数具体值的学科。
通俗来说,机器学习是一门讨论各式各样的适用于不同问题的函数形式,以及如何使用数据来有效地获取函数具体值的学科。
通俗来说,机器学习是一门讨论各式各样的适用于不同问题的函数形式,以及如何使用数据来有效地获取函数具体值的学科。
《重要的事说3遍,你品你细品》
深度学习是机器学习中的一类函数,它的形式通常为多层神经网络,近年来,仰仗大数据和强大的硬件,深度学习已逐渐成为处理图像、文本语料和声音信号等复杂高维度数据的主要方法。
2. 名词解释
conda:一个流行的python包管理软件
MXNet:深度学习包,里面也包含一些张量运算库,分为CPU和GPU版本
jupyter:一种在线编辑和执行Python代码的工具
3. 数据操作
from mxnet import nd # 从mxnet包中导入nd模块
x = nd.arange(12)
nd为NDArray的简写,它是一个类,用于存储和变换数据的主要工具,它与numpy很类似,由于提供了GPU计算和自动求梯度等更多功能,所以相对numpy,它更适合深度学习。
nd.arange(12):生成一个size为12的一维数组,并从0到11逐步填充数据,可以使用shape属性来查看它的属性
nd.arange(12).shape. ----->. (12,)
使用size属性查看它的大小:nd.arange(12).size. -------> 12
使用reshape()函数可以一维向量变更为二维矩阵:nd.arange(12).reshape(3,4) 把size为12的一维向量变更为3行4列的矩阵
0,1,2,3,4,5,6,7,8,9,10,11 --------> [[0,1,2,3],
[4,5,6,7],
[8,9,10,11]]
上面由于知道了具体元数个数,所以可以写为(3,4),也可以推断比如nd.arange(12).reshape(-1,4) 让NDArray去推测有几行,或者nd.arange(12).reshape(3, -1),让NDArray去推测每行有几列数据
使用NDArray也可以创建一个各元素为0,形状为(2,3,4)的张量:nd.zeros((2,3,4))
使用NDArray也可以创建一个各元素为1,形状为(3,4)的张量:nd.ones((3,4))
也可以通过Python的列表(list)指定需要创建的NDArray中每个元素的值:y=nd.array([[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3]])
备注:比较神奇的是,即便没有from mxnet import nd,上述代码也可以执行
有些情况下,我们需要随机生成张量中的值:nd.random.normal(0,1, shape=(3,4))
这里创建一个形状为(3,4)的NDArray,它的每个元素都采用均值为0,标准差为1的正态分布值填充
4. NDArray运算:NDArray支持大量的运算符
x = [[0, 1, 2, 3]. Y = [[2, 1, 4, 3],
[4, 5, 6, 7], [1,2,3,4]
[8,9,10,11]] [4,3,2,1]]
那么X+Y、X/Y、Y.exp()、nd.dot(X, Y.T), nd.concat(X,Y, dim=0), nd.concat(X, Y, dim=1)均可实现
dot函数做矩阵乘法nd.dot(X, Y.T), Y.T为矩阵Y的转置
concat(X,Y, dim=0):把两个矩阵连接起来,dim=0表示矩阵长度连接,dim=1表示矩阵宽度连接
dim=0: [ [0,1,2,3], [4,5,6,7], [8,9,10,11], [2,1,4,3], [1,2,3,4], [4,3,2,1]]
dim=1: [[0,1,2,3,2,1,4,3],
[4,5,6,7,1,2,3,4],
[8,9,10,11,4,3,2,1]]
还可以判断X==Y : 在X和Y相同的位置做求真运算(相同为1,否则为0)
5. 上面张量运算都是两个形状相同的NDArray运算,对于两个形状不同的运算,可能会触发广播机制
x = nd.arange(3).reshape((3,1)) # 3行1列的矩阵
x=[[0],
[1],
[2]]
y = nd.arange(2).reshape((1,2)) #1行2列的矩阵
y=[[0,1]]
此时:x+y,由于它们的形状不同,所以触发广播机制,即都自动扩展为2*3矩阵
x + y = (0) (1, 2)
(1) +
(2)
= (0, 0) (1, 2) # x的第一列被广播到了第二列,即把第1列的值复制到第2列
(1, 1) + (1, 2) # y的第1行2个元素被广播到第2、3行,即把第1行的值复制到第2、3行
(2, 2) (1, 2)
= (1, 2)
(2, 3)
(3, 4)
6. 索引
代表了元素的位置,索引从0开始逐一递增,分为行索引和列索引
x = [[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11]]
则x[1:3]表示: 按行索引,取第1行和第2行
[[4, 5, 6, 7],
[8, 9, 10, 11]]
则x[1,2] = 9, 表示取第1行第2列的值
则x[1:3, :] = 12,表示把矩阵的第2、3行,所有列的数据都修改为12
则x[1:3, 1:3] = 12,表示把矩阵的第2,3行,第2,3列的数据都修改为12
7. 内存与id()函数
Y = X + Y, 其中X和Y都是矩阵,执行这个运算之后,Y指向了新的地址,这点与Java的基础类型的运算不同
from mxnet import nd
x = nd.arange(12).reshape(3,4)
y = nd.ones((3,4))
before = id(y)
print(before) # 打印张量y的地址:
140389110238512
y = y + x
after = id(y)
print(after) # 打印张量y的地址:
140389110236832
可以看到尽管是同一个变量,但前后地址已发生变化。 如果想指定结果到特定内存,可以如下操作
z = y.zeros_like() # 初始化一个与y形状相同的矩阵,但使用0填充
before = id(z) # 记录z的地址
z[:] = x + y # 执行矩阵加,并使用索引把矩阵和填充到z中
after = id(z) # 再获取z的地址
before == after # 比较地址的前后变化
true
这里的z[:] = x + y还是开了临时内存来存储计算结果,再复制到z对应的内存。如果想避免这个临时内存开销,可以使用运算符全名函数中的out参数:
nd.elemwise_add(x, y, out = z)
id(z) == before
另外,也可以适当考虑不使用要的矩阵,例如x初始化之后不再使用,完全可以把x复用起来,减少内存的开销,如x[:]=x+y,或者x += y
8. ndarray与numpy
ndarray是mxnet中存储和变换数据的主要工具,开发者可以轻松地对ndarray创建、运算、指定索引、并与numpy进行变换
import numpy as np
p = np.ones((2,3)) # 使用np创建2*3的矩阵
d = nd.array(p) #使用ndarray把numpy创建的2*3矩阵转换为ndarray的2*3矩阵
[[1,1,1],
[1,1,1]]
d.asnumpy(). # 把ndarray矩阵转换为numpy矩阵