前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Tensorflow之基础篇

Tensorflow之基础篇

作者头像
Ed_Frey
发布2020-12-30 16:12:45
7860
发布2020-12-30 16:12:45
举报
文章被收录于专栏:奔跑的键盘侠奔跑的键盘侠

这是奔跑的键盘侠的第188篇文章

作者|我是奔跑的键盘侠

来源|奔跑的键盘侠(ID:runningkeyboardhero)

转载请联系授权(微信ID:ctwott)

终于有点时间学一下之前碎碎念的TensorFlow,主要代码为主,内容来源于《简明的TensorFlow2》作者 李锡涵 李卓恒 朱金鹏,人民邮电出版社2020.9第1版。

这本书虽然确实很简明,但是需要一定基础,比如机器学习的基本算法,比如python的基本能力。敲了前面几个简单的神经网络,代码都可以正常运行,不过部分入门代码未注释,如果想系统学习tensorflow的话,还是要多多print(help)或者网上查阅相关资料。

1

关于安装

略……

自行百度

2

常用语法代码

代码语言:javascript
复制
## 1.1 TensorFlow 1+1
import tensorflow as tf

#定义一个随机数(标量)
random_float = tf.random.uniform(shape=())
#定义一个有3个元素的零向量
zero_vector = tf.zeros(shape=(3),dtype=tf.int32)

print(random_float)
print(zero_vector)
A = tf.constant([[1.,2.],[3.,4.]])
B = tf.constant([[5.,6.],[7.,8.]])

#张量的重要属性是形状、类型和值,它们分别可以通过张量的shape、dtype属性和numpy()方法获得。
print(A.shape)
print(B.dtype)
print(A.numpy())
#张量的numpy()方法是将张量的值转换为一个Numpy数组。

输出结果:

代码语言:javascript
复制
tf.Tensor(0.79740083, shape=(), dtype=float32)
tf.Tensor([0 0 0], shape=(3,), dtype=int32)
(2, 2)
<dtype: 'float32'>
[[1. 2.]
 [3. 4.]]
代码语言:javascript
复制
#计算矩阵A与B的和,A与B的乘积。
C = tf.add(A,B)
D = tf.matmul(A,B)

print(C.numpy())
print(D)

输出结果:

代码语言:javascript
复制
[[ 6.  8.]
 [10. 12.]]
tf.Tensor(
[[19. 22.]
 [43. 50.]], shape=(2, 2), dtype=float32)
代码语言:javascript
复制
## 1.2 自动求导机制
import tensorflow as tf

x = tf.Variable(initial_value=3.)
#x是一个变量,使用tf.Variable()声明,与普通张量一样,该变量同样具有形状、类型和值这3种属性。参数设定初始值为3.0,浮点数。
#变量x与普通张量的区别是,变量默认能够被TensorFlow的自动求导机制求导,so常用于定义机器学习模型的参数。

#tf.GradientTape()是一个自动求导记录器,变量和计算步骤都会被自动记录。
with tf.GradientTape() as tape:
    y = tf.square(x)

# y=x**2被自动记录,可以通过y_grad=tape.gradient(y,x)求张量y对变量x的导数。
y_grad = tape.gradient(y,x)
#计算y关于x的导数
print([y,y_grad])

运行结果:

代码语言:javascript
复制
[<tf.Tensor: shape=(), dtype=float32, numpy=9.0>, <tf.Tensor: shape=(), dtype=float32, numpy=6.0>]
代码语言:javascript
复制
#同理,我们可以用tf.GradientTape()计算函数L(w,b)=||Xw+b-y||**2 在w=[[1],[2]]列向量,b=1时分别对w,b的偏导数,
#其中X=[[1,2],[3,4]]   y=[[1],[2]]:
X = tf.constant([[1.,2.],[3.,4.]])
y = tf.constant([[1.],[2.]])
w = tf.Variable(initial_value=[[1.],[2.]])
b = tf.Variable(initial_value=1.)
with tf.GradientTape() as tape:
    L = tf.reduce_sum(tf.square(tf.matmul(X,w)+b-y))
w_grad, b_grad = tape.gradient(L, [w,b])
print(L, w_grad, b_grad)
### tf.squre()用于对输入张量的每一个元素求平方,不改变张量的形状。
tf.reduce_sum()用于对输入张量的所有元素求和。TensorFlow中有大量的张量操作API,包括数学运算、张量形状操作,如tf.reshape(),切片和连接,如tf.concat()等多种类型。可通过查阅TensorFlow官方API文档了解。

运行结果:

代码语言:javascript
复制
tf.Tensor(125.0, shape=(), dtype=float32) tf.Tensor(
[[ 70.]
 [100.]], shape=(2, 1), dtype=float32) tf.Tensor(30.0, shape=(), dtype=float32)

3

线性回归

代码语言:javascript
复制
## 1.3 TensorFlow下的线性回归

使用tape.gradient(ys,xs)自动计算梯度
使用optimizer.apply_gradients(grads_and_vars)自动更新模型参数。

tf.keras.optimizers.SGD(learning_rate=1e-3)声明了一个梯度下降优化器(optimizer),其学习率为1e-3
优化器可以帮我们根据计算出的求导结果更新模型参数,从而最小化某个特定的损失函数。

而更新模型参数的方法optimizer.apply_gradients()中需要提供参数grads_and_vars,即待更新的变量(variables)和损失函数关于
这些变量的偏导数(如grads)。具体而言,这里需要传入一个Python列表list,list中的每个元素是一个(变量的偏导数,变量)对,比如这里是
[(grad_a,a),(grad_b,b)]。我们通过grads=tape.gradient(loss,variables)求出tape中记录的loss关于variables=[a,b]中每个变量的偏导数,也就是grads=[grad_a,grad_b]再使用python的zip()函数将grads=[grad_a,grad_b]和variables=[a,b]拼装在一起,就可以组合出所需要的参数了。
代码语言:javascript
复制
import tensorflow as tf
import numpy as np

X_raw = np.array([2013,2014,2015,2016,2017],dtype=np.float32)
y_raw = np.array([12000,14000,15000,16500,17500],dtype=np.float32)

X = (X_raw - X_raw.min())/(X_raw.max()-X_raw.min())
y = (y_raw - y_raw.min())/(y_raw.max()-y_raw.min())


X = tf.constant(X)
y = tf.constant(y)


a = tf.Variable(initial_value=0.)
b = tf.Variable(initial_value=0.)
# print(X.numpy())
variables = [a,b]

num_epoch = 10000
optimizer = tf.keras.optimizers.SGD(learning_rate=1e-3)
for e in range(num_epoch):
#   使用tf.GradientTape()记录损失函数的梯度信息
    with tf.GradientTape() as tape:
        y_pred = a*X + b
        loss = tf.reduce_sum(tf.square(y_pred - y))
#   TensorFlow自动计算损失函数关于自变量(模型参数)的梯度
    grads = tape.gradient(loss, variables)
#   TensorFlow自动根据梯度更新参数
    optimizer.apply_gradients(grads_and_vars=zip(grads, variables))
    
print(a.numpy(),b.numpy())

运行结果如下:

代码语言:javascript
复制
0.9817748 0.0545703
代码语言:javascript
复制
代码语言:javascript
复制
再补充一段可视化代码:
代码语言:javascript
复制
import matplotlib.pyplot as plt
import numpy as np

X_raw = np.array([2013,2014,2015,2016,2017],dtype=np.float32)
y_raw = np.array([12000,14000,15000,16500,17500],dtype=np.float32)
X = (X_raw - X_raw.min())/(X_raw.max()-X_raw.min())
y = (y_raw - y_raw.min())/(y_raw.max()-y_raw.min())
m = X
n = y

plt.scatter(m,n,s=75,alpha=.5)
plt.xlim((0,3))
plt.xticks([0,2,1])#ignore xticks
plt.ylim((0,3))
plt.yticks([0,2,1])#ignore xticks

m = np.linspace(0, 2, num=50, endpoint=True, retstep=False, dtype=None, axis=0)
n = a.numpy()*m + b.numpy()

plt.figure(num=1,figsize=(10,5))
plt.plot(m,n,color='r',linewidth=2,linestyle='--')

plt.show()

4

线性回归的模型玩法

## 上一节的线性回归模型,可以通过该模型实现,代码如下

代码语言:javascript
复制
import tensorflow as tf

X = tf.constant([[1.,2.,3.],[4.,5.,6]])
y = tf.constant([[10.],[20.]])

class Linear(tf.keras.Model):
### 继承tf.keras.Model类后,可以使用父类若干方法和属性。
#列入实例化类model = Model()后,可以通过model.variables
#这一属性直接获得模型的所有变量,免去我们一个个显式的指定变量的麻烦。
    def __init__(self):
        super().__init__()
        self.dense =tf.keras.layers.Dense(
            units=1,
            activation=None,
            kernel_initializer=tf.zeros_initializer(),
            bias_initializer=tf.zeros_initializer()
        )
    def call(self,input):
        output = self.dense(input)
        return output
    

#以下是调用代码:
model = Linear()
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
for i in range(100):
    with tf.GradientTape() as tape:
        y_pred = model(X)
        loss = tf.reduce_sum(tf.square(y_pred-y))
    grads = tape.gradient(loss,model.variables)
    
    optimizer.apply_gradients(grads_and_vars=zip(grads,model.variables))
print(model.variables)
# 在这里我们并没有显式的声明a和b两个变量,也没有写出 y_pred=a*X+b
# 这一线性变换,而是建立了一个继承了tf.keras.Model模型类Linear。
# 该类在初始化部分实例化了一个全连接层(tf.keras.layers.Dense),
# 并在call()方法中队这个层进行调用,实现了线性变换计算。

运算结果如下:

代码语言:javascript
复制
[<tf.Variable 'linear_6/dense_3/kernel:0' shape=(3, 1) dtype=float32, numpy=
array([[0.16730985],
       [1.14391   ],
       [2.1205118 ]], dtype=float32)>, <tf.Variable 'linear_6/dense_3/bias:0' shape=(1,) dtype=float32, numpy=array([0.97660047], dtype=float32)>]

## Keras的全连接层:线性变化+激活函数

#### 全连接层(tf.keras.layers.Dense)是Keras中最基础和常用的层之一,能够对输入矩阵A进行f(AW+b)的线性变化+激活函数操作。如果不指定激活函数,就是纯粹的线性变换AW+b。具体而言,给定输入张量input=[batch_size,input_dim],该层对输入张量首先进行tf.matmul(input,kernel)+bias的线性变化(kernel和bias是层中可训练的变量),然后将线性变换后张量的每个元素通过激活函数activation进行计算,从而输出形状为[batch_size,units]的二维张量。

-END-

© Copyright

奔跑的键盘侠原创作品 | 尽情分享朋友圈 | 转载请联系授权

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 奔跑的键盘侠 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档