基于TensorFlow和Python的机器学习(笔记1)
Keras和TensorFlow比较
项目
Keras
TensorFlow
学习难度
简单
困难
使用弹性
中等
高
开发效率
执行性能
适合用户
初学者
老油条
张量运算
不用自行设计
需要自行设计
模型概述summary
Model:"sequential"
_________________________________________________________________
Layer(type)OutputShapeParam#
=================================================================
dense(Dense)(None,256)200960
dense_1(Dense)(None,10)2570
Totalparams:203,530
Trainableparams:203,530
Non-trainableparams:0
None
神经网络参数(可训练)量计算公式
数据集
强化学习和深度学习
keras和tf.keras
keras
tf.keras
作为独立工具,就称为Keras
作为TensorFlow的一个高阶API,就称为tf.keras
tf.keras是KerasAPI规范的Tensorflow特定实现。它为该框架增加了对许多Tensorflow特定功能的支持,例如:对tf.data.Dataset作为输入对象的完美支持,对急切执行的支持
fromkeras.modelsimportSequential
fromkeras.modelsimportload_model
fromtensorflow.keras.modelsimportSequential
fromtensorflow.keras.modelsimportload_model
fromkeras.layers.poolingimportMaxPooling2D
fromtensorflow.keras.layersimportMaxPooling2D
fc=keras.layers.Dense(64,activation='relu')
fc=tf.keras.layers.Dense(64,activation='relu')
基本概念
池化层
PoolingLayer
用一个数代表一个感受野中的很多数
可以减少参数量
最大池化MaxPooling:池中的最大值代表该池子
平均池化AveragePooling:池中的平均值代表该池子
激活函数
Activationfunctions
给神经元引入了非线性因素
使模型可以适配非线性模型
感受野
receptivefield
视觉感受的一个范围;
数据矩阵中的一部分;
交叉熵
CrossEntropy
用来描述语言模型的性能
用来描述模型对文本识别的难度
卷积
convolution
卷积的“卷”是指翻转平移操作,“积”是指积分运算
采用权值相乘累加的方式提取特征信息
过拟合
Overfitting
模型在训练集上面表现较好,但是在未见的样本上表现不佳
也就是模型泛化能力偏弱,这种现象叫作过拟合
欠拟合
Underfitting
训练集上表现不佳,同时在未见的样本上表现也不佳
模型不能够很好地学习到训练集数据的模态,这种现象叫作欠拟合
泛化能力
机器学习的主要目的是从训练集上学习到数据的真实模型,从而能够在未见过的测试集上也能够表现良好,我们把这种能力叫做泛化能力。通常来说,训练集和测试集都采样自某个相同的数据分布。采样到的样本是相互独立的,但是又来自于相同的分布,我们把这种假设叫做独立同分布假设(IndependentIdenticalDistributionassumption,简称i.i.d.)。
数据增强
除了上述介绍的方式可以有效检测和抑制过拟合现象之外,增加数据集规模是解决过拟合最重要的途径。但是收集样本数据和标签往往是代价昂贵的,在有限的数据集上,通过数据增强技术可以增加训练的样本数量,获得一定程度上的性能提升。数据增强(DataAugmentation)是指在维持样本标签不变的条件下,根据先验知识改变样本的特征,使得新产生的样本也符合或者近似符合数据的真实分布。
表达能力
前面已经提到了模型的表达能力,也称之为模型的容量(Capacity)。当模型的表达能力偏弱时,比如单一线性层,它只能学习到线性模型,无法良好地逼近非线性模型;但模型的表达能力过强时,它就有可能把训练集的噪声模态也学到,导致在测试集上面表现不佳的现象(泛化能力偏弱)。因此针对不同的任务,设计合适容量的模型算法才能取得较好的泛化性能。
容量
通俗地讲,模型的容量或表达能力,是指模型拟合复杂函数的能力。一种体现模型容量的指标为模型的假设空间(HypothesisSpace)大小,即模型可以表示的函数集的大小。假设空间越大越完备,从假设空间中搜索出逼近真实模型的函数也就越有可能;反之,如果假设空间非常受限,就很难从中找到逼近真实模型的函数。
当模型的容量过大时,网络模型除了学习到训练集数据的模态之外,还把额外的观测误差也学习进来,导致学习的模型在训练集上面表现较好,但是在未见的样本上表现不佳,也就是模型泛化能力偏弱,我们把这种现象叫作过拟合(Overfitting)。当模型的容量过小时,模型不能够很好地学习到训练集数据的模态,导致训练集上表现不佳,同时在未见的样本上表现也不佳,我们把这种现象叫作欠拟合(Underfitting)
防止过拟合
提前终止训练、稀疏化参数、添加正则项、减小网络层数、减小每层的参数量、
增加数据规模(数据增强)、
正则化=范数=稀疏性惩罚项
L0正则化/范数
所有非零元素个数
不可导
用的不多
L1正则化/范数
所有元素绝对值之和
连续可导
使用广泛
L2正则化/范数
所有元素平方和
validation英[vlden]美[vlden]
batch英[bt]美[bt]n.一批,一批生产量v.分批处理
sparse_categorical_accuracy=稀疏-绝对-精确性
sparse_categorical_crossentropy=稀疏-绝对-交叉-熵函数
accuracy英[kjrsi]美[kjrsi]
entropy英[entrpi]美[entrpi]
cross-entropy交叉熵互熵
categorical英[ktɡrk()l]美[ktɡrk()l]
adj.绝对的(名词categoricalness,副词categorically,异体字categoric);直截了当的;无条件的;属于某一范畴的分类的绝对的无条件的
sparse英[spɑs]美[spɑrs]
adj.稀少的,稀疏的;简朴的稀少的稀疏的创建稀疏矩阵
iris英[ars]美[ars]n.鸢[yuān]尾,鸢[yuān]尾属植物
shuffle英[f()l]美[f()l]打乱
Sequential英[skwen()l]美[skwen()l]存放模型的容器
adj.连续的,按顺序的;依次发生的,相继发生的;(主计算机)顺序的
Dense英[dens]美[dens]全连接层
adj.稠密的;浓密的,浓重的;密度大的;
optimizer英[ptmaz]n.[计]优化程序;最优控制器
activation英[ktven]美[ktven]激活函数
regularizer正则化矩阵正则化项正则项
L0范数
L0范数是指向量中非0的元素的个数。如果我们用L0范数来规则化一个参数矩阵W的话,就是希望W的大部分元素都是0。这太直观了,太露骨了吧,换句话说,让参数W是稀疏的。OK,看到了"稀疏"二字,大家都应该从当下风风火火的"压缩感知"和"稀疏编码"中醒悟过来,原来用的漫山遍野的"稀疏"就是通过这玩意来实现的。但你又开始怀疑了,是这样吗?看到的papers世界中,稀疏不是都通过L1范数来实现吗?脑海里是不是到处都是||W||1影子呀!几乎是抬头不见低头见。没错,这就是这节的题目把L0和L1放在一起的原因,因为他们有着某种不寻常的关系。那我们再来看看L1范数是什么?它为什么可以实现稀疏?为什么大家都用L1范数去实现稀疏,而不是L0范数呢?
L1范数
L1范数是指向量中各个元素绝对值之和,也有个美称叫"稀疏规则算子"(Lassoregularization)。现在我们来分析下这个价值一个亿的问题:为什么L1范数会使权值稀疏?有人可能会这样给你回答"它是L0范数的最优凸近似"。实际上,还存在一个更美的回答:任何的规则化算子,如果他在Wi=0的地方不可微,并且可以分解为一个"求和"的形式,那么这个规则化算子就可以实现稀疏。这说是这么说,W的L1范数是绝对值,|w|在w=0处是不可微,但这还是不够直观。这里因为我们需要和L2范数进行对比分析。所以关于L1范数的直观理解,请待会看看第二节。
L2范数
除了L1范数,还有一种更受宠幸的规则化范数是L2范数:||W||2。它也不逊于L1范数,它有两个美称,在回归里面,有人把有它的回归叫"岭回归"(RidgeRegression),有人也叫它"权值衰减weightdecay"。这用的很多吧,因为它的强大功效是改善机器学习里面一个非常重要的问题:过拟合。至于过拟合是什么,上面也解释了,就是模型训练时候的误差很小,但在测试的时候误差很大,也就是我们的模型复杂到可以拟合到我们的所有训练样本了,但在实际预测新的样本的时候,糟糕的一塌糊涂。通俗的讲就是应试能力很强,实际应用能力很差。擅长背诵知识,却不懂得灵活利用知识。
核范数
核范数||W||*是指矩阵奇异值的和,英文称呼叫NuclearNorm。这个相对于上面火热的L1和L2来说,可能大家就会陌生点。那它是干嘛用的呢?霸气登场:约束Low-Rank(低秩)。
正则化
中文名正则化外文名regularization出处线性代数理论用途求解不适定问题
不适定问题
经典的数学物理方程定解问题中,人们只研究适定问题。适定问题是指定解满足下面三个要求的问题:①解是存在的;②解是唯一的;③解连续依赖于定解条件,即解是稳定的。这三个要求中,只要有一个不满足,则称之为不适定问题。
中文名不适定问题外文名ill-posedproblem相对概念适定问题属性数学物理方程定解问题示例拉普拉斯方程的柯西问题适用领域地球物理、连续介质力学等定义不满足解是存在的、唯一的、稳定的
监督机器
还有几种角度来看待规则化的。规则化符合奥卡姆剃刀(Occam'srazor)原理。这名字好霸气,razor!不过它的思想很平易近人:在所有可能选择的模型中,我们应该选择能够很好地解释已知数据并且十分简单的模型。从贝叶斯估计的角度来看,规则化项对应于模型的先验概率。民间还有个说法就是,规则化是结构风险最小化策略的实现,是在经验风险上加一个正则化项(regularizer)或惩罚项(penaltyterm)。
范数
范数(norm)是数学中的一种基本概念。在泛函分析中,它定义在赋范线性空间中,并满足一定的条件,即①非负性;②齐次性;③三角不等式。它常常被用来度量某个向量空间(或矩阵)中的每个向量的长度或大小。
定义范数的矢量空间是赋范矢量空间;同样,定义半范数的矢量空间就是赋半范矢量空间。
注:在二维的欧氏几何空间R中定义欧氏范数,在该矢量空间中,元素被画成一个从原点出发的带有箭头的有向线段,每一个矢量的有向线段的长度即为该矢量的欧氏范数。
泛函
泛函就是定义域是一个函数集,而值域是实数集或者实数集的一个子集,推广开来,泛函就是从任意的向量空间到标量的映射。也就是说,它是从函数空间到数域的映射。
设{y}是给定的函数集,如果对于这个函数集中任一函数y(x)恒有某个确定的数与之对应,记为П(y(x)),则П(y(x))是定义于集合{y(x)}上的一个泛函。
泛函定义域内的函数为可取函数或容许函数,y(x)称为泛函П的变量函数。
泛函П(y(x))与可取函数y(x)有明确的对应关系。泛函的值是由一条可取曲线的整体性质决定的。
泛函也是一种“函数”,它的独立变量一般不是通常函数的“自变量”,而是通常函数本身。泛函是函数的函数。由于函数的值是由自变量的选取而确定的,而泛函的值是由自变量函数确定的,故也可以将其理解为函数的函数
泛函的自变量是函数,泛函的自变量称为宗量。
简言之,泛函就是函数的函数。
用TensorFlowAPI:tf.Keras搭建网络八股
1
import
导入依赖包
2
datasets
train(x_train、y_train)test
3
classMyModel(Model)
model=Mymodel()
创建模型类并实例化对象
4
model.compile
拼装
5
model.fit
训练
6
model.summary
描述
举例
importtensorflowastf#创建模型
importnumpyasnp#计算库
下载数据集
x_train=datasets.load_iris().data#下载数据
y_train=datasets.load_iris().target#下载标签
seed=116#种子
np.random.seed(seed)#设置种子
np.random.shuffle(x_train)#打乱数据
np.random.shuffle(y_train)#打乱数据
tf.random.set_seed(seed)
model
创建模型
model=tf.keras.Sequential([#用Sequential容器创建模型
tf.keras.layers.Dense(3,#全连接层
activation=tf.keras.activations.softmax,#激活函数
kernel_regularizer=tf.keras.regularizers.l2)#正则化器
])
compile
装配模型
model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.1),
#优化器SGD学习率0.1
#损失函数
loss=tf.keras.losses.sparse_categorical_crossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy']
)
fit
训练模型
model.fit(x_train,y_train,batch_size=32,
epochs=500,validation_split=0.2,validation_freq=20)
#输入数据x_train和标签y_train
#批次大小32一般取2的幂
#训练次数500次
summary
模型概述
model.summary()
密集向量和稀疏向量的区别:密集向量的值就是一个普通的Double数组而稀疏向量由两个并列的数组indices和values组成例如:向量(1.0,0.0,1.0,3.0)用密集格式表示为[1.0,0.0,1.0,3.0],用稀疏格式表示为(4,[0,2,3],[1.0,1.0,3.0])第一个4表示向量的长度(元素个数),[0,2,3]就是indices数组,[1.0,1.0,3.0]是values数组表示向量0的位置的值是1.0,2的位置的值是1.0,而3的位置的值是3.0,其他的位置都是0
中文名稀疏向量表示方法通常用两部分表示:一部分是顺序向量,另一部分是值向量
稀疏向量[1]通常用两部分表示:一部分是顺序向量,另一部分是值向量。例如稀疏向量(4,0,28,53,0,0,4,8)可用值向量(4,28,53,4,8)和顺序向量(1,0,1,1,0,0,1,1)表示。
scikit-learnMachineLearninginPython
scikit-learn是一个Python的机器学习项目。是一个简单高效的数据挖掘和数据分析工具。基于NumPy、SciPy和matplotlib构建。
Gitee指数为27,超过42%的开源项目
简单有效的工具进行预测数据分析
每个人都可以访问,并且可以在各种情况下重用
基于NumPy,SciPy和matplotlib构建
开源,可商业使用-BSD许可证
姓名判男女,基于统计和规则
path=r'C:\Users\Administrator\Desktop\name.txt'
f=open(path,mode='r',encoding='utf-8')
lines=f.readlines()
dic=dict()
forlineinlines:
name,sex=line.split('\t')
name=name[1:]
forziinname:
ifziindic:#字典中已经存在该键
if'男'insex:
dic[zi]+=1
else:
dic[zi]-=1
else:#字典不存在该键
dic[zi]=1
dic[zi]=-1
print(len(dic))
test_path=r'C:\Users\Administrator\Desktop\testname.txt'
ff=open(test_path,mode='r',encoding='utf-8')
test=ff.readlines()
print(len(test))
fornameintest:
name=name.replace('\n','')
iflen(name)==3:
name2=name[1:]
eliflen(name)==4:
name2=name[2:]
score=0
forziinname2:
ifziindic:
score+=dic[zi]
sex='男'ifscore>0else'女'
print(f'name={name},sex={sex},score={score}\n')
name=龚尧莞,sex=女,score=-25
name=齐新燕,sex=女,score=-121
name=车少飞,sex=男,score=1038
name=龙家铸,sex=男,score=1770
name=赖鸿华,sex=男,score=2228
name=龙宣霖,sex=男,score=805
name=连丽英,sex=女,score=-1120
name=齐晓巍,sex=男,score=351
name=连俊勤,sex=男,score=2408
name=齐明星,sex=男,score=2784
name=黄相杰,sex=男,score=2019
name=龚小虎,sex=男,score=499
name=连传杰,sex=男,score=2273
name=宇文献花,sex=女,score=-83
name=龙川凤,sex=男,score=60
name=黄益泉,sex=男,score=434
name=黄益波,sex=男,score=705
name=米培燕,sex=女,score=-366
name=连保健,sex=男,score=652
name=齐旺梅,sex=女,score=-205
进程已结束,退出代码0
N-Gram语言模型
对中文而言,我们称之为汉语语言模型(CLM,ChineseLanguageModel)。汉语语言模型利用上下文中相邻词间的搭配信息,可以实现到汉字的自动转换,
中文名汉语语言模型外文名N-Gram定义计算出具有最大概率的句子
汉语语言模型利用上下文中相邻词间的搭配信息,在需要把连续无空格的拼音、笔划,或代表字母或笔划的数字,转换成汉字串(即句子)时,可以计算出具有最大概率的句子,从而实现到汉字的自动转换,无需用户手动选择,避开了许多汉字对应一个相同的拼音(或笔划串,或数字串)的重码问题。
常用的是二元的Bi-Gram和三元的Tri-Gram。
深度学习(英语:deeplearning),是一个多层神经网络是一种机器学习方法。在深度学习出现之前,由于诸如局部最优解和梯度消失之类的技术问题,没有对具有四层或更多层的深度神经网络进行充分的训练,并且其性能也不佳。但是,近年来,Hinton等人通过研究多层神经网络,提高学习所需的计算机功能以及通过Web的开发促进培训数据的采购,使充分学习成为可能。结果,它显示出高性能,压倒了其他方法,解决了与语音,图像和自然语言有关的问题,并在2010年代流行。
机器学习(MachineLearning,ML)是人工智能的子领域,也是人工智能的核心。它囊括了几乎所有对世界影响最大的方法(包括深度学习)。机器学习理论主要是设计和分析一些让计算机可以自动学习的算法。
机器学习和深度学习的区别
区别
深度学习
机器学习
特征提取
自动提取
手工设计
应用场景
深度学习主要应用于文字识别、人脸技术、语义分析、智能监控等领域。目前在智能硬件、教育、医疗等行业也在快速布局。
机器学习在指纹识别、特征物体检测等领域的应用基本达到了商业化的要求
数据依赖
如果数据量迅速增加,那么深度学习的效果将更加突出,这是因为深度学习算法需要大量数据才能完美理解。
机器学习能够适应各种数据量,特别是数据量较小的场景。
性能
当数据量很少的时候,深度学习的性能并不好,因为深度学习算法需要大量数据才能很好理解其中蕴含的模式。
机器学习在训练数据的时候费时较少,同时只需几秒到几小时。
特征1
深度学习与传统模式识别方法的最大不同在于它所采用的特征是从大数据中自动学习得到,而非采用手工设计。好的特征可以提高模式识别系统的性能。
过去几十年,在模式识别的各种应用中,手工设计的特征一直处于统治地位。手工设计主要依靠设计者的先验知识,很难利用大数据的优势。由于依赖手工调参数,因此特征的设计中所允许出现的参数数量十分有限。深度学习可以从大数据中自动学习特征的表示,可以包含成千上万的参数。
特征2
一个模式识别系统包括特征和分类器两部分。在传统方法中,特征和分类器的优化是分开的。而在神经网络的框架下,特征表示和分类器是联合优化的,可以最大程度地发挥二者联合协作的性能。
解决问题的方法
深度学习则以集中方式解决问题,而不必进行问题拆分。
机器学习算法遵循标准程序以解决问题。它将问题拆分成数个部分,对其进行分别解决,而后再将结果结合起来以获得所需的答案。
结构层次
深度学习模型的“深”字意味着神经网络的结构深,由很多层组成。而支持向量机和Boosting等其他常用的机器学习模型都是浅层结构。三层神经网络模型(包括输入层、输出层和一个隐含层)可以近似任何分类函数。既然如此,为什么需要深层模型呢
研究表明,针对特定的任务,如果模型的深度不够,其所需要的计算单元会呈指数增加。这意味着虽然浅层模型可以表达相同的分类函数,但其需要的参数和训练样本要多得多。
浅层模型提供的是局部表达。它将高维图像空间分成若干个局部区域,每个局部区域至少存储一个从训练数据中获得的模板,如图1(a)所示。浅层模型将一个测试样本和这些模板逐一匹配,根据匹配的结果预测其类别。随着分类问题复杂度的增加,需要将图像空间划分成越来越多的局部区域,因而需要越来越多的参数和训练样本。尽管目前许多深度模型的参数量已经相当巨大,但如果换成浅层神经网络,其所需要的参数量要大出多个数量级才能达到相同的数据拟合效果,以至于很难实现。
矩阵乘法
tf.matmul=matrixmultiply
函数:tf.matmul
表示:将矩阵a乘以矩阵b,生成a*b
numpy.matmul=matrixmultiply
原型:numpy.matmul(a,b,out=None)两个numpy数组的矩阵相乘
(1)如果两个参数a,b都是2维的,做普通的矩阵相乘。
(2)如果某个参数是N(N>2)维的,该参数被理解为一些矩阵的stack,计算时会相应的广播。
首先对于a,它会被理解成为两个2*4的矩阵的stack。
对于b,它会被理解成为两个4*2的矩阵的stack。
a=tf.random.uniform([4,3,28,32])
b=tf.random.uniform([4,3,32,22])
c=a@b
print(c)#shape=(4,3,28,22)
a=tf.random.uniform([4,3])
b=tf.random.uniform([3,7])
print(c)#shape=(4,7)
#a的列数必须等于b的行数,否则报错Matrixsize-incompatible
#相乘之后的结果是a的行数和b的列数的矩阵;
a=tf.random.uniform([4,3,22])
b=tf.random.uniform([22,7])
c=a@b#shape=(4,3,7)
print(c)#broadcast自动扩展b为[4,22,7]然后再相乘
#独热码OneHot
y_onehot=tf.one_hot(3,10)
#共10个分类(元素),下标3的元素(第4个元素)值为1,其余为0
print(y_onehot)
#tf.Tensor([0.0.0.1.0.0.0.0.0.0.],shape=(10,),dtype=float32)
平均值
tf.reduce_mean()函数用于计算张量tensor沿着指定的数轴(tensor的某一维度)上的平均值,主要用作降维或者计算tensor(图像)的平均值。
tf.reduce_mean(
input_tensor,
axis=None,
keep_dims=False,
name=None,
reduction_indices=None
参数:
input_tensor:输入的待降维的tensor
axis:指定的轴,如果不指定,则计算所有元素的均值
keep_dims:是否降维度,默认False。设置为True,输出的结果保持输入tensor的形状,设置为False,输出结果会降低维度;如果输入是二维,输出也是二维,维度不变
name:操作的名称
reduction_indices:在以前版本中用来指定轴,已弃用
类似函数还有:
tf.reduce_sum:计算tensor指定轴方向上的所有元素的累加和;
tf.reduce_max:计算tensor指定轴方向上的各个元素的最大值;
tf.reduce_all:计算tensor指定轴方向上的各个元素的逻辑和(and运算);
tf.reduce_any:计算tensor指定轴方向上的各个元素的逻辑或(or运算);
importtensorflowastf
x=[[1,2,3],[4,5,6]]#二维列表
print(type(x))#
print(x)#[[1,2,3],[4,5,6]]
y=tf.cast(x,dtype=tf.float32)#将二维列表转换为张量
#默认keepdims=False输出结果降维
mean_all=tf.reduce_mean(y)#所有元素平均值
print(mean_all)#tf.Tensor(3.5,shape=(),dtype=float32)
mean_0=tf.reduce_mean(y,axis=0)#同一列上元素求平均
print(mean_0)#tf.Tensor([2.53.54.5],shape=(3,),dtype=float32)
mean_1=tf.reduce_mean(y,axis=1)#同一行上元素求平均
print(mean_1)#tf.Tensor([2.5.],shape=(2,),dtype=float32)
#keepdims=True输出结果维度与输入维度相同
mean_all=tf.reduce_mean(y,keepdims=True)
print(mean_all)#tf.Tensor([[3.5]],shape=(1,1),dtype=float32)
mean_0=tf.reduce_mean(y,axis=0,keepdims=True)
print(mean_0)#tf.Tensor([[2.53.54.5]],shape=(1,3),dtype=float32)
mean_1=tf.reduce_mean(y,axis=1,keepdims=True)
print(mean_1)#tf.Tensor([[2.][5.]],shape=(2,1),dtype=float32)
求导
tf.GradientTape梯度带/胶带/磁带
定义在tensorflow/python/eager/backprop.py文件中,从文件路径也可以大概看出,GradientTape是eager模式下计算梯度用的,而eager模式(eager模式的具体介绍请参考文末链接)是TensorFlow2.0的默认模式,因此tf.GradientTape是官方大力推荐的用法。下面就来具体介绍GradientTape的原理和使用。
Tape在英文中是胶带,磁带的含义,用在这里是由于eager模式带来的影响。在TensorFlow1.x静态图时代,我们知道每个静态图都有两部分,一部分是前向图,另一部分是反向图。反向图就是用来计算梯度的,用在整个训练过程中。而TensorFlow2.0默认是eager模式,每行代码顺序执行,没有了构建图的过程(也取消了control_dependency的用法)。但也不能每行都计算一下梯度吧?计算量太大,也没必要。因此,需要一个上下文管理器(contextmanager)来连接需要计算梯度的函数和变量,方便求解同时也提升效率。
默认情况下GradientTape的资源在调用gradient函数后就被释放,再次调用就无法计算了。所以如果需要多次计算梯度,需要开启persistent=True属性
WARNING:tensorflow:CallingGradientTape.gradientonapersistenttapeinsideitscontextissignificantlylessefficientthancallingitoutsidethecontext(itcausesthegradientopstoberecordedonthetape,leadingtoincreasedCPUandmemoryusage).OnlycallGradientTape.gradientinsidethecontextifyouactuallywanttotracethegradientinordertocomputehigherorderderivatives.
警告:tensorflow:调用GradientTape。在其上下文中对持久磁带进行梯度操作的效率比在上下文中调用梯度操作的效率要低得多(它导致梯度操作被记录在磁带上,导致CPU和内存使用增加)。
在一个持久胶带(persistentGradientTape)外面求导,效率更高;
一般在网络中使用时,不需要显式调用watch函数,使用默认设置,GradientTape会监控可训练变量;
x=tf.constant(3.)
print(x)#tf.Tensor(3.0,shape=(),dtype=float32)
#用GradientTape梯度带求导数
withtf.GradientTape()asg:
g.watch(x)#看着点X,
y=x*x#y=x^2
dy_dx=g.gradient(y,x)#y’=2*x=2*3=6
print(dy_dx)#
#例子中的watch函数把需要计算梯度的变量x加进来了。
#GradientTape默认只监控由tf.Variable创建的traiable=True属性(默认)的变量。
#上面例子中的x是constant,因此计算梯度需要增加g.watch(x)函数。
#当然,也可以设置不自动监控可训练变量,完全由自己指定,
#设置watch_accessed_variables=False就行了(一般用不到)。
#GradientTape也可以嵌套多层用来计算高阶导数
g.watch(x)
withtf.GradientTape()asgg:#嵌套梯度带
gg.watch(x)#看着点X
y=x*x*x#y=x^3
dy_dx=gg.gradient(y,x)#y'=3*x^2=3*3^2=27
print(dy_dx)#tf.Tensor(27.0,shape=(),dtype=float32)
d2y_dx2=g.gradient(dy_dx,x)#y''=(3*x^2)'=3*2*x=6*x=18
print(d2y_dx2)#tf.Tensor(18.0,shape=(),dtype=float32)
#默认情况下GradientTape的资源在调用gradient函数后就被释放,再次调用就无法计算了。
#所以如果需要多次计算梯度,需要开启persistent=True属性
#RuntimeError:Anon-persistentGradientTapecanonlybeused
#tocomputeonesetofgradients(orjacobians)
#RuntimeError:一个非持久的GradientTape只能用于计算一组梯度(或雅可比矩阵)
#持久性胶带,粘得更牢
withtf.GradientTape(persistent=True)asg:
y=x*x#y=x^2,
z=y*y#z=y^2=x^4
dy_dx=g.gradient(y,x)#y'=2*x=2*3=6
print(dy_dx)#tf.Tensor(6.0,shape=(),dtype=float32)
dz_dx=g.gradient(z,x)#z'=4*x^3=4*27=108
print(dz_dx)#tf.Tensor(108.0,shape=(),dtype=float32)
delg#持久性胶带,用完后要删除,非降解材料,不会自动消失
张量和变量的区别(Tensor和Variable)
tf.Tensor不需计算梯度
tf.Variable需计算梯度
l为了区分需要计算梯度信息的张量与不需要计算梯度信息的张量,TensorFlow增加了一种专门的数据类型来支持梯度信息的记录:tf.Variable。
ltf.Variable类型在普通的张量类型基础上添加了name,trainable等属性来支持计算图的构建。
t=tf.constant([1,2,3])#创建常量张量
v=tf.Variable(t)#将张量转换为变量Variable(待优化张量、可变张量)
print(t)#tf.Tensor([123],shape=(3,),dtype=int32)
print(v)#
print(v.name)#Variable:0Variable特有属性
print(v.trainable)#TrueVariable特有属性
v=tf.Variable([[1,2],[3,4]])#直接创建Variable张量
print(v)#
ls=[11,22,33]#创建list列表
print(type(ls))#
t=tf.convert_to_tensor(ls)#将列表转换为张量
print(t)#tf.Tensor([112233],shape=(3,),dtype=int32)
importnumpyasnp
arr=np.array([[6.6,7.7],[100,200]])#创建一个numpy数组ndarray
print(type(arr))#
t=tf.convert_to_tensor(arr)#将ndarray转换为张量
print(t)#tf.Tensor([[6.67.7][100.200.]],shape=(2,2),dtype=float64)
t=tf.range(5)
print(t)#tf.Tensor([01234],shape=(5,),dtype=int32)
关键词
compile装配
Dense全连接层
fit训练
ReLU激活函数层
最后,一般在网络中使用时,不需要显式调用watch函数,使用默认设置,GradientTape会监控可训练变量;
第一个机器学习demo
importkeras
model=keras.Sequential([keras.layers.Dense(units=1,input_shape=[1])])
model.compile(optimizer='sgd',loss='mean_squared_error')
#输入x(训练集)
xs=np.array([-1.0,0.0,1.0,2.0,3.0,4.0],dtype=float)
#标签y
ys=np.array([-3.0,-1.0,1.0,3.0,5.0,7.0],dtype=float)
#讲数据输入,开始训练,共训练500遍
model.fit(xs,ys,epochs=500)
print(f'当x为10.0时,y的预测值为')
print(model.predict([10.0]))
print(f'当x为-3.0时,y的预测值为')
print(model.predict([-3.0]))
'''
Epoch1/500
1/1[==============================]-0s291ms/step-loss:28.4334
Epoch2/500
1/1[==============================]-0s999us/step-loss:22.6760
Epoch3/500
1/1[==============================]-0s999us/step-loss:18.1401
Epoch4/500
1/1[==============================]-0s1000us/step-loss:14.5652
Epoch5/500
1/1[==============================]-0s996us/step-loss:11.7467
Epoch6/500
1/1[==============================]-0s1ms/step-loss:9.5233
Epoch7/500
1/1[==============================]-0s998us/step-loss:7.7683
Epoch8/500
1/1[==============================]-0s998us/step-loss:6.3818
Epoch9/500
1/1[==============================]-0s1ms/step-loss:5.2855
Epoch10/500
1/1[==============================]-0s999us/step-loss:4.4175
1/1[==============================]-0s1000us/step-loss:5.2602e-05
Epoch499/500
1/1[==============================]-0s999us/step-loss:5.1522e-05
Epoch500/500
1/1[==============================]-0s1ms/step-loss:5.0463e-05
当x为10.0时,y的预测值为
1/1[==============================]-0s87ms/step
[[18.986246]]
当x为-3.0时,y的预测值为
1/1[==============================]-0s33ms/step
[[-6.98784]]
张量
importnumpy
t=tf.ones([2,3])
print(t)#2行3列的张量,每个元素都是1
t=tf.zeros([3,4])
print(t)#3行4列的张量,每个元素都是0
t=tf.fill([3,6],99)
print(t)#3行6列的张量,每个元素都是99
t=tf.zeros_like(t)
print(t)#形状同t,行数列数都相同,每个元素都是0
t=tf.ones_like(t)
print(t)#形状同t,行数列数都相同,每个元素都是1
t=tf.one_hot(3,4)#共4个元素,下标3的元素为1,其余为0
print(t)#独热码tf.Tensor([0.0.0.1.],shape=(4,),dtype=float32)
t=tf.constant([[1,2,3],[9,8,7]])
print(t)#tf.Tensor([[123][987]],shape=(2,3),dtype=int32)
#定义常数张量,指定数据的张量
t=tf.linspace(start=0.0,stop=3.0,num=6)
print(t)#tf.Tensor([0.0.61.21.80000012.43.],shape=(6,),dtype=float32)
#等距切分张量,0-0.6-1.2-1.8-2.4-3.0,以0为起始元素,以3为结束元素,等分成6份
t=tf.range(start=0,limit=5,delta=1)
#指定区间为[0,5)前闭后开,相邻元素差值为1
t=tf.range(start=0.5,limit=2,delta=0.3)
print(t)#tf.Tensor([0.50.81.11.40000011.7],shape=(5,),dtype=float32)
#指定区间[0.5,2),相邻元素差值0.3(步距)
t=tf.random.uniform([3,4],minval=0,maxval=2)
print(t)#随机值下限为0上限为2的均匀分布,3行4列
print(numpy.mean(t))#0.8071537
t=tf.random.normal([3,4],mean=10,stddev=1)
print(t)#均值为10标准差为1的正态分布,3行4列
print(numpy.mean(t))#9.724729
t=tf.random.truncated_normal([3,4],mean=2,stddev=1)
print(t)#均值为2,标准差为1的截断正态分布,3行4列
print(numpy.mean(t))#2.0792353
截断正态分布的定义可以分为两步,给定一个参数为μ和σ2
(1)无截断的情况:∞=a,b=+∞;
(2)下界截断的情况:∞ (3)上界截断的情况:∞=a,b<+∞;