import tensorflow as tf
#1.创建输入张量
a=tf.constant(2.)
b=tf.constant(4.)
#2.直接计算并打印
print('a+b=',a+b)
输出:
'''
深度学习tensorflow深度学习框架的3大核心功能
1.TensorFlow 的重要功能就是利用 GPU 方便地实现并行计算加速功能。
为了演示 GPU 的加速效果,我们通过完成多次矩阵 A 和矩阵 B 的矩阵
相乘运算的平均运算时间来验证。
'''
import tensorflow as tf
import timeit
# import keras.backend as K
# cfg = K.tf.ConfigProto(gpu_options={'allow_growth': True})
# K.set_session(K.tf.Session(config=cfg))
n=100000
#创建在CPU上运算的2个矩阵
with tf.device('/cpu:0'):
cpu_a=tf.random.normal([1,n])#从正态分布生成随机值
cpu_b=tf.random.normal([n,1])
#print(cpu_a,'\n',cpu_b)
print(cpu_a.device,cpu_b.device)
#创建使用GPU运算的2个矩阵
with tf.device('/gpu:0'):
gpu_a=tf.random.normal([1,n])
gpu_b=tf.random.normal([n,1])
print(gpu_a.device,gpu_b.device)
#并通过time.timeit()函数来测量2个矩阵的运算时间:
def cpu_run():
with tf.device('/cpu:0'):
c = tf.matmul(cpu_a,cpu_b)
return c
def gpu_run():
with tf.device('/gpu:0'):
c = tf.matmul(gpu_a,gpu_b)
return c
#第一次计算需要热身,避免将初始化阶段时间结算在内
cpu_time = timeit.timeit(cpu_run,number=10)
print('warmup:',cpu_time)
gpu_time = timeit.timeit(gpu_run,number=10)
print('warmup:',gpu_time)
#正式计算10次,取平均时间
cpu_time = timeit.timeit(cpu_run,number=10)
gpu_time = timeit.timeit(gpu_run,number=10)
print('run time:',gpu_time)
print('run time:',cpu_time)
输出:
'''
2.自动梯度,
在使用 TensorFlow 构建前向计算过程的时候,除了能够获得数值结果,TensorFlow 还
会自动构建计算图,通过 TensorFlow 提供的自动求导的功能,可以不需要手动推导,即可
计算出输出对网络的偏导数。
'''
import tensorflow as tf
import numpy as np
#创建4个张量
a = tf.constant(1.)
b = tf.constant(2.)
c = tf.constant(3.)
w = tf.constant(4.)
with tf.GradientTape() as tape: #创建梯度环境
tape.watch([w]) #将w加入梯度跟踪队列
#构建计算过程
y = a*w**2+b*w+c
#求导
[dy_dw] = tape.gradient(y,[w])
print(dy_dw) #打印出导数
输出:
#线性模型实战
'''
y=1.477*x+0.089
为了能够很好地模拟真实样本的观测误差,
我们给模型添加误差自变量㼿,它采样自均
值为 0,方差为 0.01 的高斯分布:
'''
import numpy as np
#1.采样数据
data = []#保存样本集的列表
for i in range(100):#循环采样100个点
#每次从区间[-10,10]的均匀分布U(0,1)中随机采样数据x
x = np.random.uniform(-10,10.) #随机采样输入x
#采样高斯噪声
#从均值为0,方差为0.1^2的高斯分布采样
eps = np.random.normal(0.,0.1)
#得到模型的输出
y=1.477*x+0.089+eps
data.append([x,y]) #保存样本点
data = np.array(data)#转换为2DNumpy数组
#2.计算误差
def mse(b,w,points):
#根据当前的w,b参数计算均值方差损失
totalError = 0
for i in range(0,len(points)): #循环迭代所有点
x = points[i,0] #获得i号点的输入x
y = points[i,1] #获得i号点的输出y
#计算差的平方,并累加
totalError += (y-(w*x+b))**2
#将累加的误差求平均,得到均方差
return totalError/float(len(points))
#3.计算梯度
'''
根据之前介绍的梯度下降算法,我们需要计算出函数在每一个点上的梯度信息:
我们来推导一下梯度的表达式
'''
def step_gradient(b_current,w_current,points,lr):
#计算误差函数在所有点上的导数,并更新w,b
b_gradient = 0
w_gradient = 0
M = float(len(points)) #总样本数
for i in range(0,len(points)):
x=points[i,0]
y=points[i,1]
#误差函数对b的导数:grad_b=2(wx+b-y)
b_gradient += (2/M) * ((w_current*x+b_current)-y)
#误差函数对w的导数:grad_w=2(wx+b-y)*x
w_gradient += (2/M) * x * ((w_current*x+b_current)-y)
#根据梯度下降算法更新w',b',其中lr为学习率
new_b = b_current -(lr*b_gradient)
new_w = w_current -(lr*w_gradient)
return [new_b,new_w]
#梯度更新
'''
在计算出误差函数在㼿和㼿处的梯度后,
我们可以根据式(2.1)来更新㼿和㼿的值。
我们把对数据集的所有样本训练一次称为一个 Epoch,
共循环迭代 num_iterations 个 Epoch
'''
def gradient_descent(points,starting_b,starting_w,lr,num_iterations):
#循环更新w,b多次
b = starting_b #b的初始值
w = starting_w #w的初始值
#根据梯度下降算法更新多次
for step in range(num_iterations):
#计算梯度并更新一次
b,w = step_gradient(b,w,np.array(points),lr)
loss = mse(b,w,points) #计算当前的均方差,用于监控训练进度
if step%50 ==0:
print(f"iteration:{step},loss:{loss},w:{w},b:{b}")
return [b,w] #返回最后一次的w,b
#主训练函数
if __name__ == '__main__' :
#加载训练集数据,这些数据通过真实模型添加观测误差采样得到的
lr = 0.01 #学习率
initial_b = 0 #初始化b为0
initial_w = 0 #初始化w为0
num_iterations = 1000
#训练优化1000次,返回最优w*,b*和训练Loss的下降过程
[b,w] = gradient_descent(data,initial_b,initial_w,lr,num_iterations)
loss = mse(b,w,data) #计算最优数值解w,b上的均方差
print(f"Final loss:{loss},w:{w},b:{b}")
输出:
对于复杂的非线性模型,通过梯度下降算法求解到的w和b可能是局部极小值而非全局最小值解,这是由模型函数的非凸性决定的。
'''
我们这里利用tensorflow自动在线下载MNIST数据集合=,并转换为Numpy
数组格式
'''
import os
import tensorflow as tf #导入TF子库
from tensorflow import keras #导入TF子库
from tensorflow.keras import layers,optimizers,datasets #导入TF子库
(x,y),(x_val,y_val) = datasets.mnist.load_data() #加载数据集,
#load_data()函数返回两个元组兑现,第一个是训练集,第二个是测试集
#每个tuple的第一个元素是多个训练图片数据X,第二个元素是训练图片对应的类别数字Y
x = 2*tf.convert_to_tensor(x,dtype = tf.float32)/255.-1 #转换为张量,缩放到-1~1
y = tf.convert_to_tensor(y,dtype = tf.int32) #转换为张量
y = tf.one_hot(y,depth = 10)#one-hot 编码
print(x.shape, y.shape)
train_dataset = tf.data.Dataset.from_tensor_slices((x,y))#构建数据集对象
train_dataset = train_dataset.batch(512)#批量训练
#模型构建
'''
One-hot 编码是非常稀疏
(Sparse)的,相对于数字编码来说,占用较多的存储空间,
所以一般在存储时还是采用数字
编码,在计算时,根据需要来把数字编码转换成 One-hot 编码,
通过 tf.one_hot 即可实现:
'''
y = tf.constant([0,1,2,3]) #数字编码
y = tf.one_hot(y,depth=10) #one-hot编码
print(y)
model = keras.Sequential([#3个非线性层的嵌套模型
layers.Dense(256,activation='relu'),
layers.Dense(128,activation='relu'),
layers.Dense(10)
])
#模型训练 得到模型输出O后,通过MSE损失函数计算当前的误差:
with tf.GradientTape() as tape: #构建梯度记录环境
#打平,[b,28,28] => [b,784]
x = tf.reshape(x,(-1,28*28))
#Step1. 得到模型输出outpout
#[b,784] => [b,10]
out = model(x)
grads = tape.gradient(loss,model.trainable_variables)
optimizers.apply_gradients(zip(grads,model.trainable_variables))