动手学深度学习(tensorflow)---学习笔记整理(一、预备知识篇)

67 篇文章 11 订阅
30 篇文章 8 订阅

学习视频来源为b站动手学深度学习系列视频:https://space.bilibili.com/209599371/channel/detail?cid=23541

由于上述视频为MXNet/Gluon框架编写,所以代码部分参考网站为:https://trickygo.github.io/Dive-into-DL-TensorFlow2.0/#/

本文主要是学习该系列视频所整理笔记,可能很多内容直接原文整理,如有需要可以去上述两个网站进行学习。

深度学习是什么?

这个问题不同人有不同的理解,我粗浅的理解就是,模拟人脑的结构对数据进行观察,并发现数据潜在的特征。

这样说可能不太形象,举个例子:一个桶里有铁屑和木屑,机器学习是通过一种方法来进行分离,例如SVM思想,往桶里倒入水,就可以将木屑和铁屑从二维平面映射到三维空间,从而实现分离;而深度学习例如人去观察铁屑和木屑的不同,然后提取出特征,然后快速识别出来(人一个一个把铁屑挑出来的感觉,当然计算机模拟的人脑挑的速度足够快)。

以上是个人理解,欢迎大家纠正等。

tensorflow基础:

这里其实课程中主要讲述了一些实践,详细原理没怎么说。

引入tensorflow库,并命名为tf。(可以不命名,但是命名比较方便,试试就能体会出来)

import tensorflow as tf

输出tensorflow版本

print(tf.__version__)

然后定义一个tf矩阵/张量

x = tf.constant([1,2,3,4,5,6,7,8,9,10,11,12])

这里解释下张量的概念,类型名Tensor,如果大家使用过numpy或者pandas可以发现,创建或者读取的矩阵是这两个裤特有的类型,同样tensorflow的变量也有一个特殊的称呼,叫做张量,可以理解成tensorflow的特有结构,其本质就是个矩阵...不太理解就当成矩阵就好。(下属可能说张量/矩阵时直接以矩阵代替)

张量/矩阵的改变形状/维度

X = tf.reshape(x,(3,4))
#输出结果Tensor("Reshape:0", shape=(3, 4), dtype=int32)
#上面的x.reshape((3, 4))也可写成x.reshape((-1, 4))或x.reshape((3, -1))。
# 由于x的元素个数是已知的,这里的-1是能够通过元素个数和其他维度的大小推断出来的。

(x原本为[1,2,3,4,5,6,7,8,9,10,11,12],现在改变成3*4的矩阵了)

创建0、1矩阵

#创建0向量,纬度为2*3*4
x=tf.zeros((2,3,4))
print(x)
#创建1向量,纬度为2*3*4
x=tf.ones((2,3,4))
print(x)

创建自定义矩阵

x = tf.constant([1,2,3,4,5,6,7,8,9,10,11,12])

输出矩阵形状/维度

print(x.shape)

张量类型转换

#cast数据类型转换
Y = tf.cast(Y, tf.float32)

按元素进行矩阵加减乘除以及指数运算等

#元素加法
print("加法",X+Y)
#元素乘法除法
print("乘法",X*Y)
print("除法",X/Y)
#按元素元素指数运算
Y = tf.cast(Y, tf.float32)
print("指数",tf.exp(Y))

(元素类型不同是没法操作的,使用前先用cast函数统一类型哟~~)

广播机制:当对两个形状不同的tensor按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使这两个tensor形状相同后再按元素运算。(copy自上述引文)

假设A和B分别是3行1列和1行2列的矩阵,如果要计算A + B,那么A中第一列的3个元素被广播(复制)到了第二列,而B中第一行的2个元素被广播(复制)到了第二行和第三行。如此,就可以对2个3行2列的矩阵按元素相加。

矩阵乘法、连结等操作

#矩阵乘法
print("矩阵除法",tf.matmul(X, tf.transpose(Y)))
#矩阵连结,二维的包括行连结和列连结,由axis决定,高维度的可以其他维度连结
print("行连结",tf.concat([X,Y],axis = 0))
print("列连结",tf.concat([X,Y],axis = 1))

判断两矩阵是否相等

#判断两个元素是否相等
print(tf.equal(X,Y))

张量元素求和

sess = tf.Session()
print("张量",tf.reduce_sum(X))
print("张量值",sess.run(tf.reduce_sum(X)))

注意!输出张量和输出张量值是不一样的,前者输出的是这个张量的各种信息,例如张量名称、形状、类型等,后者即为张量的值,也就是矩阵的值,上述一直输出的都是张量,而不是张量值。本模块进行输出就可以发现区别了(本文编译器为pycharm,好像jupyter可以直接输出张量值...)

按索引输出

print("索引",sess.run(X[0:2]))
print("索引",sess.run(X[0:2][1]))
print("索引",sess.run(X[0:2][1][1]))

(自己动手输出一下就知道多加[]是什么意思了~很有趣)

修改矩阵数值

X = tf.Variable(X)
init = tf.global_variables_initializer()
sess.run(init)
#修改X变量,但是需要进行初始化才能进行操作
#修改某1,2位置数为19
print(sess.run(X[1,2].assign(19)))
#修改第一列为99
print(sess.run(X[1:2,:].assign(tf.ones(X[1:2,:].shape, dtype = tf.int32)*99)))

(此处需要了解一些tensorflow的初始化机制,本文就不具体介绍了,其实我目前也不是很了解哈~都是报错后才想起来(小声音嘟嘟,我比较菜~))

关于内存开销的相关理论:

在前面的例子里我们对每个操作新开内存来存储运算结果。举个例子,即使像Y = X + Y这样的运算,我们也会新开内存,然后将Y指向新内存。为了演示这一点,我们可以使用Python自带的id函数:如果两个实例的ID一致,那么它们所对应的内存地址相同;反之则不同。(copy自引文)

验证程序:

#内存开销
X = tf.Variable(X)
Y = tf.cast(Y, dtype=tf.int32)
before = id(Y)
Y = Y + X
print(id(Y) == before)
#输出为否

两种避免的写法:

如果想指定结果到特定内存,我们可以使用前面介绍的索引来进行替换操作。在下面的例子中,我们先通过zeros_like创建和Y形状相同且元素为0的tensor,记为Z。接下来,我们把X + Y的结果通过[:]写进Z对应的内存中。

Z = tf.Variable(tf.zeros_like(Y))
before = id(Z)
Z[:].assign(X + Y)
print(id(Z) == before)
#输出为真

实际上,上例中我们还是为X + Y开了临时内存来存储计算结果,再复制到Z对应的内存。如果想避免这个临时内存开销,我们可以使用assign_{运算符全名}函数。

before = id(X)
X.assign_add(Y)
print(id(X) == before)
#输出为真

tensorflow和numpy的转换

其实通过发现num的数据类型和tensorflow的数据类型虽然不一样,其本质都是矩阵(包括pandas),所以有特定的函数进行类型转化

np转tf

P = np.ones((2,3))
D = tf.constant(P)

tf转np

np.array(D)

自动求梯度

神经网络中最不可缺少的就是自动求梯度这一方法~(懂的应该深有体会...)

设y=2*x*x,其导数应为4x。

求解过程如下:

import tensorflow as tf
sess = tf.Session()
#新建一个矩阵
x = tf.reshape(tf.Variable([1,2,3,4], dtype=tf.float32),(4,1))
print(x)
with tf.GradientTape() as t:
    t.watch(x)
    y = 2 * tf.matmul(tf.transpose(x), x)

dy_dx = t.gradient(y, x)
#如果不初始化是无法run的
init = tf.global_variables_initializer()
sess.run(init)
print(sess.run(dy_dx))

再写一个z、y公式详见代码内

with tf.GradientTape(persistent=True) as g:
    g.watch(x)
    y = x * x
    z = y * y
    dz_dx = g.gradient(z, x)  # 108.0 (4*x^3 at x = 3)
    dy_dx = g.gradient(y, x)  # 6.0
print(sess.run(dz_dx),sess.run(dy_dx))

教程中还提供一个方法,我没怎么看懂。。。挂个代码,大家自己研究研究吧

#控制流求梯度
def f(a):
    b = a * 2
    while tf.norm(b) < 1000:
        b = b * 2
    if tf.reduce_sum(b) > 0:
        c = b
    else:
        c = 100 * b
    return c

查询函数文档相关操作

经常我们使用各种框架或者函数,不了解参数、返回值或者含义等就可以进行查询其文档来了解具体含义

当我们想知道一个模块里面提供了哪些可以调用的函数和类的时候,可以使用dir函数。下面我们打印dtypesrandom模块中所有的成员或属性。(copy自引文)

print(dir(tf.dtypes))
print(dir(tf.random))

想了解某个函数或者类的具体用法时,可以使用help函数。让我们以ones函数为例,查阅它的用法。(copy自引文)

print(help(tf.ones))

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值