├── README.md ├── code ├── 代码2-1 用静态图训练一个具有保存检查点功能的回归模型.py ├── 代码2-2 用动态图训练一个具有保存检查点功能的回归模型.py ├── 代码3-1 从动态图种获取变量.py ├── 代码3-10 用估算器框架进行分布式训练worker.py ├── 代码3-11 keras回归模型.py ├── 代码3-12 keras回归模型2.py ├── 代码3-2 在静态图中使用动态图.py ├── 代码3-3 用估算器框架训练一个回归模型.py ├── 代码3-4 为估算器添加钩子.py ├── 代码3-5 自定义hook.py.py ├── 代码3-6 将估算器模型转为静态图模型.py ├── 代码3-7 用估算器框架进行分布式训练.py ├── 代码3-8 用估算器框架分布式训练ps.py ├── 代码3-9 用估算器框架进行分布式训练chief.py ├── 代码4-1 将模拟数据制作成内存对象数据集.py ├── 代码4-10 将图片文件制作成Dataset数据集-TFa.py ├── 代码4-10 将图片文件制作成Dataset数据集.py ├── 代码4-11 将图片文件制作成Dataset数据集TFa.py ├── 代码4-12 在动态图里读取Dataset数据集.py ├── 代码4-13 在不同场景中使用数据集.py ├── 代码4-2 带迭代的模拟数据集.py ├── 代码4-3 将图片制作成内存对象数据集.py ├── 代码4-4 将Excel文件制作成内存对象数据集.py ├── 代码4-5 将图片文件制作成TFRecord数据集.py ├── 代码4-6 interleave例子.py ├── 代码4-7 Dataset对象的操作方法.py ├── 代码4-8 将内存数据转成DataSet数据集.py ├── 代码4-9 from_tensor_slices的注意事项.py ├── 代码5-1 用feature_column模块处理连续值特征列.py ├── 代码5-10 train.py ├── 代码5-11 data_loader.py ├── 代码5-12 预测飞机发动机的剩余使用寿命-TF2.py ├── 代码5-2 将连续值特征列转化成离散值特征列.py ├── 代码5-3 将离散文本特征列转化为one-hot编码与词向量.py ├── 代码5-4 根据特征列生成交叉列.py ├── 代码5-5 序列特征工程.py ├── 代码5-6 用wide_deep模型预测人口收入.py ├── 代码5-7 用梯度提升树模型预测人口收入.py ├── 代码5-8 preprocess.py ├── 代码5-9 MKRmodel.py ├── 代码6-1 NLP文本预处理.py ├── 代码6-2 TextCNN模型.py ├── 代码6-2 用keras注意力机制模型分析评论者的情绪.py ├── 代码6-3 keras注意力机制模型.py ├── 代码6-3 用TextCNN模型进行文本分类.py ├── 代码6-4 用带有动态路由算法的RNN模型对新闻进行分类.py ├── 代码6-5 pipline方式运行Transformers.py ├── 代码6-6 用BERT模型实现完型填空.py ├── 代码6-7 用GPT2模型生成句子.py ├── 代码6-8 迁移训练BERT模型对中文分类.py ├── 代码7-1 用AI模型识别图像.py ├── 代码7-10 weights.py ├── 代码7-11 yololoss.py ├── 代码7-12 mainyolo.py ├── 代码7-2 用EfficientNet模型识别图像.py ├── 代码7-3 用ResNet识别橘子和苹果.py ├── 代码7-4 annotation.py ├── 代码7-5 generator.py ├── 代码7-6 box.py ├── 代码7-7 darknet53.py ├── 代码7-8 yolohead.py ├── 代码7-9 yolov3.py ├── 代码8-1 用tf.keras实现变分自编码模型.py ├── 代码8-10 mydataset.py ├── 代码8-11 AttGANmodels.py ├── 代码8-12 trainattgan.py ├── 代码8-13 testattgan.py ├── 代码8-14 MINE.py ├── 代码8-15 DIM.py ├── 代码8-2 变分自编码模型的无标签训练.py ├── 代码8-3 将张量损失封装成损失函数.py ├── 代码8-4 在动态图中实现变分自编码.py ├── 代码8-5 以类的方式封装模型损失函数.py ├── 代码8-6 更合理的类封装方式.py ├── 代码8-7 deblurmodel.py ├── 代码8-8 训练deblur.py ├── 代码8-9 使用deblur模型.py ├── 代码9-1 Sinkhorn.py ├── 代码9-2 finetune_resnet.py ├── 代码9-3 feature_extractor.py ├── 代码9-4 ZSL_train.py └── 代码9-5 ZSL_test.py └── tf2x.jpg /README.md: -------------------------------------------------------------------------------- 1 | # TensorFlow2x_Engineering_Implementation 2 | 3 | 一书配套代码 4 | 5 | 代码对应的配套资源可以在www.aianaconda.com网站上找到。 6 | 7 | 有问题可以去bbs.aianaconda.com上提问 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /code/代码2-1 用静态图训练一个具有保存检查点功能的回归模型.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | #使用静态图训练一个具有检查点的回归模型 10 | 11 | import tensorflow as tf 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | print(tf.__version__) 15 | tf.compat.v1.disable_v2_behavior() 16 | #(1)生成模拟数据 17 | train_X = np.linspace(-1, 1, 100) 18 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 19 | #图形显示 20 | plt.plot(train_X, train_Y, 'ro', label='Original data') 21 | plt.legend() 22 | plt.show() 23 | 24 | #tf.reset_default_graph() 25 | 26 | #(2)建立网络模型 27 | 28 | # 创建模型 29 | # 占位符 30 | X = tf.compat.v1.placeholder("float") 31 | Y = tf.compat.v1.placeholder("float") 32 | # 模型参数 33 | W = tf.Variable(tf.compat.v1.random_normal([1]), name="weight") 34 | b = tf.Variable(tf.zeros([1]), name="bias") 35 | # 前向结构 36 | z = tf.multiply(X, W)+ b 37 | global_step = tf.Variable(0, name='global_step', trainable=False) 38 | #反向优化 39 | cost =tf.reduce_mean( tf.square(Y - z)) 40 | learning_rate = 0.01 41 | optimizer = tf.compat.v1.train.GradientDescentOptimizer(learning_rate).minimize(cost,global_step) #梯度下降 42 | 43 | # 初始化所有变量 44 | init = tf.compat.v1.global_variables_initializer() 45 | # 定义学习参数 46 | training_epochs = 20 47 | display_step = 2 48 | 49 | savedir = "log/" 50 | saver = tf.compat.v1.train.Saver(tf.compat.v1.global_variables(), max_to_keep=1)#生成saver。 max_to_keep=1,表明最多只保存一个检查点文件 51 | 52 | #定义生成loss可视化的函数 53 | plotdata = { "batchsize":[], "loss":[] } 54 | def moving_average(a, w=10): 55 | if len(a) < w: 56 | return a[:] 57 | return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)] 58 | 59 | #(3)建立session进行训练 60 | with tf.compat.v1.Session() as sess: 61 | sess.run(init) 62 | kpt = tf.train.latest_checkpoint(savedir) 63 | if kpt!=None: 64 | saver.restore(sess, kpt) 65 | 66 | # 向模型输入数据 67 | while global_step.eval()/len(train_X) < training_epochs: 68 | step = int( global_step.eval()/len(train_X) ) 69 | for (x, y) in zip(train_X, train_Y): 70 | sess.run(optimizer, feed_dict={X: x, Y: y}) 71 | 72 | #显示训练中的详细信息 73 | if step % display_step == 0: 74 | loss = sess.run(cost, feed_dict={X: train_X, Y:train_Y}) 75 | print ("Epoch:", step+1, "cost=", loss,"W=", sess.run(W), "b=", sess.run(b)) 76 | if not (loss == "NA" ): 77 | plotdata["batchsize"].append(global_step.eval()) 78 | plotdata["loss"].append(loss) 79 | saver.save(sess, savedir+"linermodel.cpkt", global_step) 80 | 81 | print (" Finished!") 82 | saver.save(sess, savedir+"linermodel.cpkt", global_step) 83 | 84 | print ("cost=", sess.run(cost, feed_dict={X: train_X, Y: train_Y}), "W=", sess.run(W), "b=", sess.run(b)) 85 | 86 | #显示模型 87 | plt.plot(train_X, train_Y, 'ro', label='Original data') 88 | plt.plot(train_X, sess.run(W) * train_X + sess.run(b), label='Fitted line') 89 | plt.legend() 90 | plt.show() 91 | 92 | plotdata["avgloss"] = moving_average(plotdata["loss"]) 93 | plt.figure(1) 94 | plt.subplot(211) 95 | plt.plot(plotdata["batchsize"], plotdata["avgloss"], 'b--') 96 | plt.xlabel('Minibatch number') 97 | plt.ylabel('Loss') 98 | plt.title('Minibatch run vs. Training loss') 99 | 100 | plt.show() 101 | -------------------------------------------------------------------------------- /code/代码2-2 用动态图训练一个具有保存检查点功能的回归模型.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | #使用动态图训练一个具有检查点的回归模型 10 | 11 | import tensorflow as tf 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | 15 | print("TensorFlow 版本: {}".format(tf.version.VERSION))#TF2.1 16 | print("Eager execution: {}".format(tf.executing_eagerly())) 17 | 18 | #(1)生成模拟数据 19 | train_X = np.linspace(-1, 1, 100) 20 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 21 | #图形显示 22 | plt.plot(train_X, train_Y, 'ro', label='Original data') 23 | plt.legend() 24 | plt.show() 25 | 26 | # 定义学习参数 27 | W = tf.Variable(tf.random.normal([1]),dtype=tf.float32, name="weight") 28 | b = tf.Variable(tf.zeros([1]),dtype=tf.float32, name="bias") 29 | 30 | global_step = tf.compat.v1.train.get_or_create_global_step() 31 | 32 | def getcost(x,y):#定义函数,计算loss值 33 | # 前向结构 34 | z = tf.cast(tf.multiply(np.asarray(x,dtype = np.float32), W)+ b,dtype = tf.float32) 35 | cost =tf.reduce_mean( tf.square(y - z))#loss值 36 | return cost 37 | 38 | learning_rate = 0.01 39 | # 随机梯度下降法作为优化器 40 | optimizer = tf.compat.v1.train.GradientDescentOptimizer(learning_rate=learning_rate) 41 | 42 | #定义saver,演示两种方法处理检查点文件 43 | savedir = "logeager/" 44 | #savedirx = "logeagerx/" 45 | 46 | saver = tf.compat.v1.train.Saver([W,b], max_to_keep=1)#生成saver。 max_to_keep=1,表明最多只保存一个检查点文件 47 | #saverx = tfe.Saver([W,b])#生成saver。 max_to_keep=1,表明最多只保存一个检查点文件 48 | 49 | 50 | kpt = tf.train.latest_checkpoint(savedir)#找到检查点文件 51 | #kptx = tf.train.latest_checkpoint(savedirx)#找到检查点文件 52 | if kpt!=None: 53 | saver.restore(None, kpt) #两种加载方式都可以 54 | #saverx.restore(kptx) 55 | 56 | training_epochs = 10 #迭代训练次数 57 | display_step = 2 58 | 59 | plotdata = { "batchsize":[], "loss":[] }#收集训练参数 60 | 61 | while global_step/len(train_X) < training_epochs: #迭代训练模型 62 | step = int( global_step/len(train_X) ) 63 | with tf.GradientTape() as tape: 64 | cost_=getcost(train_X,train_Y) 65 | gradients=tape.gradient(target=cost_,sources=[W,b]) #计算梯度 66 | optimizer.apply_gradients(zip(gradients,[W,b]),global_step) 67 | 68 | 69 | #显示训练中的详细信息 70 | if step % display_step == 0: 71 | cost = cost_.numpy() 72 | print ("Epoch:", step+1, "cost=", cost,"W=", W.numpy(), "b=", b.numpy()) 73 | if not (cost == "NA" ): 74 | plotdata["batchsize"].append(global_step.numpy()) 75 | plotdata["loss"].append(cost) 76 | saver.save(None, savedir+"linermodel.cpkt", global_step) 77 | #saverx.save(savedirx+"linermodel.cpkt", global_step) 78 | 79 | 80 | print (" Finished!") 81 | saver.save(None, savedir+"linermodel.cpkt", global_step) 82 | #saverx.save(savedirx+"linermodel.cpkt", global_step) 83 | print ("cost=", getcost(train_X,train_Y).numpy() , "W=", W.numpy(), "b=", b.numpy()) 84 | 85 | #显示模型 86 | plt.plot(train_X, train_Y, 'ro', label='Original data') 87 | plt.plot(train_X, W * train_X + b, label='Fitted line') 88 | plt.legend() 89 | plt.show() 90 | 91 | def moving_average(a, w=10):#定义生成loss可视化的函数 92 | if len(a) < w: 93 | return a[:] 94 | return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)] 95 | 96 | plotdata["avgloss"] = moving_average(plotdata["loss"]) 97 | plt.figure(1) 98 | plt.subplot(211) 99 | plt.plot(plotdata["batchsize"], plotdata["avgloss"], 'b--') 100 | plt.xlabel('Minibatch number') 101 | plt.ylabel('Loss') 102 | plt.title('Minibatch run vs. Training loss') 103 | plt.show() 104 | -------------------------------------------------------------------------------- /code/代码3-1 从动态图种获取变量.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | import numpy as np 11 | #import tensorflow.contrib.eager as tfe 12 | 13 | 14 | 15 | #tf.compat.v1.enable_eager_execution() 16 | print("TensorFlow 版本: {}".format(tf.version.VERSION)) 17 | print("Eager execution: {}".format(tf.executing_eagerly())) 18 | 19 | #生成模拟数据 20 | train_X = np.linspace(-1, 1, 100) 21 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 22 | 23 | from tensorflow.python.ops import variable_scope 24 | #建立数据集 25 | dataset = tf.data.Dataset.from_tensor_slices( (np.reshape(train_X,[-1,1]),np.reshape(train_X,[-1,1])) ) 26 | dataset = dataset.repeat().batch(1) 27 | global_step = tf.compat.v1.train.get_or_create_global_step() 28 | container = variable_scope.EagerVariableStore()#container进行了改变 29 | learning_rate = 0.01 30 | # 随机梯度下降法作为优化器 31 | optimizer = tf.compat.v1.train.GradientDescentOptimizer(learning_rate=learning_rate) 32 | 33 | def getcost(x,y):#定义函数,计算loss值 34 | # 前向结构 35 | with container.as_default():#将动态图使用的层包装起来。可以得到变量 36 | 37 | # z = tf.contrib.slim.fully_connected(x, 1,reuse=tf.AUTO_REUSE) 38 | z = tf.compat.v1.layers.dense(x,1, name="l1") 39 | cost =tf.reduce_mean( input_tensor=tf.square(y - z))#loss值 40 | return cost 41 | 42 | def grad( inputs, targets): 43 | with tf.GradientTape() as tape: 44 | loss_value = getcost(inputs, targets) 45 | return tape.gradient(loss_value,container.trainable_variables()) 46 | 47 | training_epochs = 20 #迭代训练次数 48 | display_step = 2 49 | 50 | #迭代训练模型 51 | for step,value in enumerate(dataset) : 52 | grads = grad( value[0], value[1]) 53 | optimizer.apply_gradients(zip(grads, container.trainable_variables()), global_step=global_step) 54 | if step>=training_epochs: 55 | break 56 | 57 | #显示训练中的详细信息 58 | if step % display_step == 0: 59 | cost = getcost (value[0], value[1]) 60 | print ("Epoch:", step+1, "cost=", cost.numpy()) 61 | 62 | print (" Finished!") 63 | print ("cost=", cost.numpy() ) 64 | for i in container.trainable_variables(): 65 | print(i.name,i.numpy()) 66 | 67 | 68 | -------------------------------------------------------------------------------- /code/代码3-10 用估算器框架进行分布式训练worker.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | TF_CONFIG='''{ 10 | "cluster": { 11 | "chief": ["127.0.0.1:2221"], 12 | "worker": ["127.0.0.1:2222"], 13 | "ps": ["127.0.0.1:2223"] 14 | }, 15 | "task": {"type": "worker", "index": 0} 16 | }''' 17 | 18 | import os 19 | 20 | os.environ['TF_CONFIG']=TF_CONFIG 21 | print(os.environ.get('TF_CONFIG')) 22 | 23 | 24 | import tensorflow as tf 25 | import numpy as np 26 | tf.compat.v1.disable_v2_behavior() 27 | #在内存中生成模拟数据 28 | def GenerateData(datasize = 100 ): 29 | train_X = np.linspace(-1, 1, datasize) #train_X为-1到1之间连续的100个浮点数 30 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 31 | return train_X, train_Y #以生成器的方式返回 32 | 33 | train_data = GenerateData() 34 | test_data = GenerateData(20) 35 | batch_size=10 36 | 37 | def train_input_fn(train_data, batch_size): #定义训练数据集输入函数 38 | #构造数据集的组成:一个特征输入,一个标签输入 39 | dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 40 | dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 41 | return dataset #返回数据集 42 | 43 | def eval_input_fn(data,labels, batch_size): #定义测试或应用模型时,数据集的输入函数 44 | #batch不允许为空 45 | assert batch_size is not None, "batch_size must not be None" 46 | 47 | if labels is None: #如果评估,则没有标签 48 | inputs = data 49 | else: 50 | inputs = (data,labels) 51 | #构造数据集 52 | dataset = tf.data.Dataset.from_tensor_slices(inputs) 53 | 54 | dataset = dataset.batch(batch_size) #按批次划分 55 | return dataset #返回数据集 56 | 57 | def my_model(features, labels, mode, params):#自定义模型函数:参数是固定的。一个特征,一个标签 58 | #定义网络结构 59 | W = tf.Variable(tf.random.normal([1]), name="weight") 60 | b = tf.Variable(tf.zeros([1]), name="bias") 61 | # 前向结构 62 | predictions = tf.multiply(tf.cast(features,dtype = tf.float32), W)+ b 63 | 64 | if mode == tf.estimator.ModeKeys.PREDICT: #预测处理 65 | return tf.estimator.EstimatorSpec(mode, predictions=predictions) 66 | 67 | #定义损失函数 68 | loss = tf.compat.v1.losses.mean_squared_error(labels=labels, predictions=predictions) 69 | 70 | meanloss = tf.compat.v1.metrics.mean(loss)#添加评估输出项 71 | metrics = {'meanloss':meanloss} 72 | 73 | if mode == tf.estimator.ModeKeys.EVAL: #测试处理 74 | return tf.estimator.EstimatorSpec( mode, loss=loss, eval_metric_ops=metrics) 75 | #return tf.estimator.EstimatorSpec( mode, loss=loss) 76 | 77 | #训练处理. 78 | assert mode == tf.estimator.ModeKeys.TRAIN 79 | optimizer = tf.compat.v1.train.AdagradOptimizer(learning_rate=params['learning_rate']) 80 | train_op = optimizer.minimize(loss, global_step=tf.compat.v1.train.get_global_step()) 81 | return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op) 82 | 83 | 84 | tf.compat.v1.reset_default_graph() #清空图 85 | tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.INFO) #能够控制输出信息 , 86 | gpu_options = tf.compat.v1.GPUOptions(per_process_gpu_memory_fraction=0.333) #构建gpu_options,防止显存占满 87 | session_config=tf.compat.v1.ConfigProto(gpu_options=gpu_options) 88 | #构建估算器 89 | estimator = tf.estimator.Estimator( model_fn=my_model,model_dir='myestimatormode',params={'learning_rate': 0.1}, 90 | config=tf.estimator.RunConfig(session_config=session_config) ) 91 | 92 | 93 | train_spec = tf.estimator.TrainSpec(input_fn=lambda: train_input_fn(train_data, batch_size), max_steps=6000) 94 | eval_spec = tf.estimator.EvalSpec(input_fn=lambda: eval_input_fn(test_data,None, batch_size)) 95 | 96 | tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec) 97 | 98 | 99 | 100 | 101 | ##偏函数方式 102 | #from functools import partial 103 | #estimator.train(input_fn=partial(train_input_fn, train_data=train_data, batch_size=batch_size),steps=2) 104 | # 105 | ##装饰器方式 106 | #def checkParams(fn): #定义通用参数装饰器函数 107 | # def wrapper(): #使用字典和元组的解包参数来作形参 108 | # return fn(train_data=train_data, batch_size=batch_size) #如满足条件,则将参数透传给原函数,并返回 109 | # return wrapper 110 | # 111 | #@checkParams 112 | #def train_input_fn2(train_data, batch_size): #定义训练数据集输入函数 113 | # #构造数据集的组成:一个特征输入,一个标签输入 114 | # dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 115 | # dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 116 | # return dataset #返回数据集 117 | #estimator.train(input_fn=train_input_fn2, steps=2) 118 | # 119 | #tf.logging.info("训练完成.")#输出训练完成 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /code/代码3-11 keras回归模型.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import numpy as np # 引入基础模块 10 | import random 11 | from tensorflow.keras.layers import Dense, Input 12 | from tensorflow.keras.models import Model 13 | 14 | # 生成训练数据 y=2x+随机数 15 | x_train = np.linspace(0, 10, 100) # 100个数 16 | y_train_random = -1 + 2 * np.random.random(100) # -1到1之间的随机数 17 | y_train = 2 * x_train + y_train_random # y=2*x +随机数 18 | print("x_train \n", x_train) 19 | print("y_train \n", y_train) 20 | 21 | # 生成测试数据 22 | x_test = np.linspace(0, 10, 100) # 100个数 23 | y_test_random = -1 + 2 * np.random.random(100) # -1到1之间的随机数 24 | y_test = 2 * x_test + y_test_random # y=2*x +随机数 25 | print("x_test \n", x_test) 26 | print("y_test \n", y_test) 27 | 28 | # 预测数据 29 | x_predict = random.sample(range(0, 10), 10) # 10个数 30 | 31 | # 定义网络层,一个输入层,三个全连接层 32 | inputs = Input(shape=(1,)) # 定义输入张量 33 | x = Dense(64, activation='relu')(inputs) # 第一个全连接层 34 | x = Dense(64, activation='relu')(x) # 第二个全连接层 35 | predictions = Dense(1)(x) # 第三个全连接层, 36 | 37 | # 编译模型,指定训练的参数 38 | model = Model(inputs=inputs, outputs=predictions) 39 | model.compile(optimizer='rmsprop', # 定义优化器 40 | loss='mse', # 损失函数是均方差 41 | metrics=['mae']) # 定义度量,绝对误差均值 42 | 43 | # 训练模型,指定训练超参数 44 | history = model.fit(x_train, 45 | y_train, 46 | epochs=100, # 100个epochs 47 | batch_size=16) # 训练的每批数据量 48 | 49 | # 测试模型 50 | score = model.evaluate(x_test, 51 | y_test, 52 | batch_size=16) # 测试的每批数据量 53 | # 打印误差值和评估标准值 54 | print("score \n", score) 55 | 56 | # 模型预测 57 | y_predict = model.predict(x_predict) 58 | print("x_predict \n", x_predict) 59 | print("y_predict \n", y_predict) 60 | -------------------------------------------------------------------------------- /code/代码3-12 keras回归模型2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf # 引入基础模块 10 | import tensorflow.keras 11 | import numpy as np 12 | from tensorflow.keras.layers import Dense, Input, Layer 13 | from tensorflow.keras.models import Model 14 | import random 15 | 16 | class MyLayer(Layer): 17 | # 自定义一个类,继承自Layer 18 | def __init__(self, output_dim, **kwargs): 19 | self.output_dim = output_dim 20 | super(MyLayer, self).__init__(**kwargs) 21 | 22 | # 定义build方法用来创建权重 23 | def build(self, input_shape): 24 | shape = tf.TensorShape((input_shape[1], self.output_dim)) 25 | # 定义可训练变量 26 | self.weight = self.add_weight(name='weight', 27 | shape=shape, 28 | initializer='uniform', 29 | trainable=True) 30 | super(MyLayer, self).build(input_shape) 31 | 32 | # 实现父类的call方法,实现层功能逻辑 33 | def call(self, inputs): 34 | return tf.matmul(inputs, self.weight) 35 | 36 | # 如果层更改了输入张量的形状,需要定义形状变化的逻辑 37 | def compute_output_shape(self, input_shape): 38 | shape = tf.TensorShape(input_shape).as_list() 39 | shape[-1] = self.output_dim 40 | return tf.TensorShape(shape) 41 | 42 | def get_config(self): 43 | base_config = super(MyLayer, self).get_config() 44 | base_config['output_dim'] = self.output_dim 45 | return base_config 46 | 47 | @classmethod 48 | def from_config(cls, config): 49 | return cls(**config) 50 | 51 | # 单元测试程序 52 | if __name__ == '__main__': 53 | # 生成训练数据 y=2x 54 | x_train = np.linspace(0, 10, 100) # 100个数 55 | y_train_random = -1 + 2 * np.random.random(100) # -1到1之间的随机数 56 | y_train = 2 * x_train + y_train_random # y=2*x + 随机数 57 | print("x_train \n", x_train) 58 | print("y_train \n", y_train) 59 | 60 | # 生成测试数据 61 | x_test = np.linspace(0, 10, 100) # 100个数 62 | y_test_random = -1 + 2 * np.random.random(100) 63 | y_test = 2 * x_test + y_test_random # y=2*x + 随机数 64 | print("x_test \n", x_test) 65 | print("y_test \n", y_test) 66 | 67 | # 预测数据 68 | x_predict = random.sample(range(0, 10), 10) # 10个数 69 | 70 | # 定义网络层,一个输入层,三个全连接层 71 | inputs = Input(shape=(1,)) # 定义输入张量 72 | x = Dense(64, activation='relu')(inputs) # 第1个全连接层 73 | x = MyLayer(64)(x) # 第2个全连接层,是自定义的层 74 | predictions = Dense(1)(x) # 第3个全连接层 75 | 76 | # 编译模型,指定训练的参数 77 | model = Model(inputs=inputs, outputs=predictions) 78 | model.compile(optimizer='rmsprop', # 定义优化器 79 | loss='mse', # 定义损失函数,绝对误差均值 80 | metrics=['mae']) # 定义度量 81 | 82 | # 训练模型,指定训练超参数 83 | history = model.fit(x_train, 84 | y_train, 85 | epochs=100, # 50个epochs 86 | batch_size=16) # 训练的每批数据量 87 | 88 | # 测试模型 89 | score = model.evaluate(x_test, 90 | y_test, 91 | batch_size=16) # 测试的每批数据量 92 | # 打印误差值和评估标准值 93 | print("score \n", score) 94 | 95 | # 模型预测 96 | y_predict = model.predict(x_predict) 97 | print("x_predict \n", x_predict) 98 | print("y_predict \n", y_predict) 99 | -------------------------------------------------------------------------------- /code/代码3-2 在静态图中使用动态图.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | #使用动态图训练一个具有检查点的回归模型 10 | 11 | import tensorflow as tf 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | tf.compat.v1.disable_v2_behavior() 15 | 16 | #(1)生成模拟数据 17 | train_X = np.linspace(-1, 1, 100) 18 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 19 | #图形显示 20 | plt.plot(train_X, train_Y, 'ro', label='Original data') 21 | plt.legend() 22 | plt.show() 23 | 24 | tf.compat.v1.reset_default_graph() 25 | 26 | def my_py_func(X, W,b): 27 | z = tf.multiply(X, W)+ b 28 | print(z) 29 | return z 30 | 31 | 32 | #(2)建立网络模型 33 | 34 | # 创建模型 35 | # 占位符 36 | X = tf.compat.v1.placeholder("float") 37 | Y = tf.compat.v1.placeholder("float") 38 | # 模型参数 39 | W = tf.Variable(tf.random.normal([1]), name="weight") 40 | b = tf.Variable(tf.zeros([1]), name="bias") 41 | # 前向结构 42 | #z = tf.multiply(X, W)+ b 43 | 44 | 45 | z = tf.py_function(my_py_func, [X, W,b], tf.float32) 46 | global_step = tf.Variable(0, name='global_step', trainable=False) 47 | #反向优化 48 | cost =tf.reduce_mean( input_tensor=tf.square(Y - z)) 49 | learning_rate = 0.01 50 | optimizer = tf.compat.v1.train.GradientDescentOptimizer(learning_rate).minimize(cost,global_step) #梯度下降 51 | 52 | # 定义学习参数 53 | training_epochs = 34 54 | display_step = 2 55 | 56 | savedir = "log/" 57 | saver = tf.compat.v1.train.Saver(tf.compat.v1.global_variables(), max_to_keep=1)#生成saver。 max_to_keep=1,表明最多只保存一个检查点文件 58 | 59 | #定义生成loss可视化的函数 60 | plotdata = { "batchsize":[], "loss":[] } 61 | def moving_average(a, w=10): 62 | if len(a) < w: 63 | return a[:] 64 | return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)] 65 | 66 | #(3)建立session进行训练 67 | with tf.compat.v1.Session() as sess: 68 | sess.run(tf.compat.v1.global_variables_initializer()) 69 | kpt = tf.train.latest_checkpoint(savedir) 70 | if kpt!=None: 71 | saver.restore(sess, kpt) 72 | 73 | # 向模型输入数据 74 | while global_step.eval()/len(train_X) < training_epochs: 75 | step = int( global_step.eval()/len(train_X) ) 76 | for (x, y) in zip(train_X, train_Y): 77 | sess.run(optimizer, feed_dict={X: x, Y: y}) 78 | 79 | #显示训练中的详细信息 80 | if step % display_step == 0: 81 | loss = sess.run(cost, feed_dict={X: train_X, Y:train_Y}) 82 | print ("Epoch:", step+1, "cost=", loss,"W=", sess.run(W), "b=", sess.run(b)) 83 | if not (loss == "NA" ): 84 | plotdata["batchsize"].append(global_step.eval()) 85 | plotdata["loss"].append(loss) 86 | saver.save(sess, savedir+"linermodel.cpkt", global_step) 87 | 88 | print (" Finished!") 89 | saver.save(sess, savedir+"linermodel.cpkt", global_step) 90 | 91 | print ("cost=", sess.run(cost, feed_dict={X: train_X, Y: train_Y}), "W=", sess.run(W), "b=", sess.run(b)) 92 | 93 | #显示模型 94 | 95 | plt.plot(train_X, train_Y, 'ro', label='Original data') 96 | v = sess.run(z, feed_dict={X: train_X}) 97 | plt.plot(train_X, v, label='Fitted line') 98 | plt.legend() 99 | plt.show() 100 | 101 | plotdata["avgloss"] = moving_average(plotdata["loss"]) 102 | plt.figure(1) 103 | plt.subplot(211) 104 | plt.plot(plotdata["batchsize"], plotdata["avgloss"], 'b--') 105 | plt.xlabel('Minibatch number') 106 | plt.ylabel('Loss') 107 | plt.title('Minibatch run vs. Training loss') 108 | 109 | plt.show() 110 | -------------------------------------------------------------------------------- /code/代码3-3 用估算器框架训练一个回归模型.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | import numpy as np 11 | tf.compat.v1.disable_v2_behavior() 12 | #在内存中生成模拟数据 13 | def GenerateData(datasize = 100 ): 14 | train_X = np.linspace(-1, 1, datasize) #train_X为-1到1之间连续的100个浮点数 15 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 16 | return train_X, train_Y #以生成器的方式返回 17 | 18 | train_data = GenerateData() 19 | test_data = GenerateData(20) 20 | batch_size=10 21 | 22 | def train_input_fn(train_data, batch_size): #定义训练数据集输入函数 23 | #构造数据集的组成:一个特征输入,一个标签输入 24 | dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 25 | dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 26 | return dataset #返回数据集 27 | 28 | def eval_input_fn(data,labels, batch_size): #定义测试或应用模型时,数据集的输入函数 29 | #batch不允许为空 30 | assert batch_size is not None, "batch_size must not be None" 31 | 32 | if labels is None: #如果评估,则没有标签 33 | inputs = data 34 | else: 35 | inputs = (data,labels) 36 | #构造数据集 37 | dataset = tf.data.Dataset.from_tensor_slices(inputs) 38 | 39 | dataset = dataset.batch(batch_size) #按批次划分 40 | return dataset #返回数据集 41 | 42 | def my_model(features, labels, mode, params):#自定义模型函数:参数是固定的。一个特征,一个标签 43 | #定义网络结构 44 | W = tf.Variable(tf.random.normal([1]), name="weight") 45 | b = tf.Variable(tf.zeros([1]), name="bias") 46 | # 前向结构 47 | predictions = tf.multiply(tf.cast(features,dtype = tf.float32), W)+ b 48 | 49 | if mode == tf.estimator.ModeKeys.PREDICT: #预测处理 50 | return tf.estimator.EstimatorSpec(mode, predictions=predictions) 51 | 52 | #定义损失函数 53 | loss = tf.compat.v1.losses.mean_squared_error(labels=labels, predictions=predictions) 54 | 55 | meanloss = tf.compat.v1.metrics.mean(loss)#添加评估输出项 56 | metrics = {'meanloss':meanloss} 57 | 58 | if mode == tf.estimator.ModeKeys.EVAL: #测试处理 59 | return tf.estimator.EstimatorSpec( mode, loss=loss, eval_metric_ops=metrics) 60 | #return tf.estimator.EstimatorSpec( mode, loss=loss) 61 | 62 | #训练处理. 63 | assert mode == tf.estimator.ModeKeys.TRAIN 64 | optimizer = tf.compat.v1.train.AdagradOptimizer(learning_rate=params['learning_rate']) 65 | train_op = optimizer.minimize(loss, global_step=tf.compat.v1.train.get_global_step()) 66 | return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op) 67 | 68 | 69 | tf.compat.v1.reset_default_graph() #清空图 70 | tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.INFO) #能够控制输出信息 , 71 | gpu_options = tf.compat.v1.GPUOptions(per_process_gpu_memory_fraction=0.8) #构建gpu_options,防止显存占满 72 | session_config=tf.compat.v1.ConfigProto(gpu_options=gpu_options) 73 | #构建估算器 74 | estimator = tf.estimator.Estimator( model_fn=my_model,model_dir='./myestimatormode',params={'learning_rate': 0.1}, 75 | config=tf.estimator.RunConfig(session_config=session_config) ) 76 | #匿名输入方式 77 | estimator.train(lambda: train_input_fn(train_data, batch_size),steps=200) 78 | tf.compat.v1.logging.info("训练完成.")#输出训练完成 79 | ##偏函数方式 80 | #from functools import partial 81 | #estimator.train(input_fn=partial(train_input_fn, train_data=train_data, batch_size=batch_size),steps=2) 82 | # 83 | ##装饰器方式 84 | #def checkParams(fn): #定义通用参数装饰器函数 85 | # def wrapper(): #使用字典和元组的解包参数来作形参 86 | # return fn(train_data=train_data, batch_size=batch_size) #如满足条件,则将参数透传给原函数,并返回 87 | # return wrapper 88 | # 89 | #@checkParams 90 | #def train_input_fn2(train_data, batch_size): #定义训练数据集输入函数 91 | # #构造数据集的组成:一个特征输入,一个标签输入 92 | # dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 93 | # dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 94 | # return dataset #返回数据集 95 | #estimator.train(input_fn=train_input_fn2, steps=2) 96 | # 97 | #tf.logging.info("训练完成.")#输出训练完成 98 | 99 | 100 | 101 | 102 | #热启动 103 | warm_start_from = tf.estimator.WarmStartSettings( 104 | ckpt_to_initialize_from='./myestimatormode', 105 | ) 106 | #重新定义带有热启动的估算器 107 | estimator2 = tf.estimator.Estimator( model_fn=my_model,model_dir='./myestimatormode3',warm_start_from=warm_start_from,params={'learning_rate': 0.1}, 108 | config=tf.estimator.RunConfig(session_config=session_config) ) 109 | estimator2.train(lambda: train_input_fn(train_data, batch_size),steps=200) 110 | 111 | test_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn(test_data[0],test_data[1],batch_size=1,shuffle=False) 112 | train_metrics = estimator.evaluate(input_fn=test_input_fn) 113 | #train_metrics = estimator2.evaluate(input_fn=lambda: eval_input_fn(train_data[0],train_data[1],batch_size)) 114 | # 115 | print("train_metrics",train_metrics) 116 | # 117 | predictions = estimator.predict(input_fn=lambda: eval_input_fn(test_data[0],None,batch_size)) 118 | print("predictions",list(predictions)) 119 | 120 | new_samples = np.array( [6.4, 3.2, 4.5, 1.5], dtype=np.float32) #定义输入 121 | predict_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( new_samples,num_epochs=1, batch_size=1,shuffle=False) 122 | predictions = list(estimator.predict(input_fn=predict_input_fn)) 123 | print( "输入, 结果: {} {}\n".format(new_samples,predictions)) 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /code/代码3-4 为估算器添加钩子.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | import numpy as np 11 | 12 | #在内存中生成模拟数据 13 | def GenerateData(datasize = 100 ): 14 | train_X = np.linspace(-1, 1, datasize) #train_X为-1到1之间连续的100个浮点数 15 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 16 | return train_X, train_Y #以生成器的方式返回 17 | 18 | train_data = GenerateData() 19 | test_data = GenerateData(20) 20 | batch_size=10 21 | 22 | def train_input_fn(train_data, batch_size): #定义训练数据集输入函数 23 | #构造数据集的组成:一个特征输入,一个标签输入 24 | dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 25 | dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 26 | return dataset #返回数据集 27 | 28 | def eval_input_fn(data,labels, batch_size): #定义测试或应用模型时,数据集的输入函数 29 | #batch不允许为空 30 | assert batch_size is not None, "batch_size must not be None" 31 | 32 | if labels is None: #如果评估,则没有标签 33 | inputs = data 34 | else: 35 | inputs = (data,labels) 36 | #构造数据集 37 | dataset = tf.data.Dataset.from_tensor_slices(inputs) 38 | 39 | dataset = dataset.batch(batch_size) #按批次划分 40 | return dataset #返回数据集 41 | 42 | def my_model(features, labels, mode, params):#自定义模型函数:参数是固定的。一个特征,一个标签 43 | #print(features.name,labels.name) 44 | #print(features.get_shape(),features.graph,labels.graph) 45 | #定义网络结构 46 | W = tf.Variable(tf.random.normal([1]), name="weight") 47 | b = tf.Variable(tf.zeros([1]), name="bias") 48 | # 前向结构 49 | predictions = tf.multiply(tf.cast(features,dtype = tf.float32), W)+ b 50 | 51 | if mode == tf.estimator.ModeKeys.PREDICT: #预测处理 52 | return tf.estimator.EstimatorSpec(mode, predictions=predictions) 53 | 54 | #定义损失函数 55 | loss = tf.compat.v1.losses.mean_squared_error(labels=labels, predictions=predictions) 56 | lossout = tf.identity(loss, name="loss") 57 | meanloss = tf.compat.v1.metrics.mean(loss)#添加评估输出项 58 | metrics = {'meanloss':meanloss} 59 | 60 | if mode == tf.estimator.ModeKeys.EVAL: #测试处理 61 | return tf.estimator.EstimatorSpec( mode, loss=loss, eval_metric_ops=metrics) 62 | #return tf.estimator.EstimatorSpec( mode, loss=loss) 63 | 64 | #训练处理. 65 | assert mode == tf.estimator.ModeKeys.TRAIN 66 | optimizer = tf.compat.v1.train.AdagradOptimizer(learning_rate=params['learning_rate']) 67 | train_op = optimizer.minimize(loss, global_step=tf.compat.v1.train.get_global_step()) 68 | return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op) 69 | 70 | 71 | tf.compat.v1.reset_default_graph() #清空图 72 | 73 | 74 | 75 | tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.INFO) #能够控制输出信息 , 76 | gpu_options = tf.compat.v1.GPUOptions(per_process_gpu_memory_fraction=0.333) #构建gpu_options,防止显存占满 77 | session_config=tf.compat.v1.ConfigProto(gpu_options=gpu_options) 78 | #构建估算器 79 | estimator = tf.estimator.Estimator( model_fn=my_model,model_dir='./estimator_hook',params={'learning_rate': 0.1}, 80 | config=tf.estimator.RunConfig(session_config=session_config) ) 81 | 82 | tensors_to_log = {"钩子函数输出": "loss"} 83 | logging_hook = tf.estimator.LoggingTensorHook( tensors=tensors_to_log, every_n_iter=1) 84 | 85 | estimator.train(lambda: train_input_fn(train_data, batch_size),steps=200,hooks=[logging_hook]) 86 | tf.compat.v1.logging.info("训练完成.")#输出训练完成 87 | -------------------------------------------------------------------------------- /code/代码3-5 自定义hook.py.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | import numpy as np 11 | 12 | #测试自定义hook 13 | x = tf.compat.v1.placeholder(shape=(10, 2), dtype=tf.float32) 14 | w = tf.Variable(initial_value=[[10.], [10.]]) 15 | w0 = [[1], [1.]] 16 | y = tf.matmul(x, w0) 17 | loss = tf.reduce_mean(input_tensor=(tf.matmul(x, w) - y) ** 2) 18 | optimizer = tf.compat.v1.train.AdamOptimizer(0.001).minimize(loss) 19 | 20 | class _Hook(tf.estimator.SessionRunHook): 21 | def __init__(self, loss): 22 | self.loss = loss 23 | 24 | def begin(self): 25 | pass 26 | 27 | def before_run(self, run_context): 28 | return tf.estimator.SessionRunArgs(self.loss) 29 | 30 | def after_run(self, run_context, run_values): 31 | loss_value = run_values.results 32 | print("loss value:", loss_value) 33 | 34 | sess = tf.compat.v1.train.MonitoredSession(hooks=[_Hook(loss)]) 35 | for _ in range(10): 36 | x_ = np.random.random((10, 2)) 37 | sess.run(optimizer, {x: x_}) 38 | 39 | 40 | tf.compat.v1.reset_default_graph() 41 | #测试FeedFnHook 42 | x2 = tf.compat.v1.placeholder(dtype=tf.float32) 43 | y = x2 + 1 44 | hook = tf.estimator.FeedFnHook(feed_fn=lambda: {x2: 1.0}) 45 | sess = tf.compat.v1.train.MonitoredSession(hooks=[hook]) 46 | print(sess.run(y)) 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /code/代码3-6 将估算器模型转为静态图模型.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | import numpy as np 11 | import matplotlib.pyplot as plt 12 | tf.compat.v1.disable_v2_behavior() 13 | #在内存中生成模拟数据 14 | def GenerateData(datasize = 100 ): 15 | train_X = np.linspace(-1, 1, datasize) #train_X为-1到1之间连续的100个浮点数 16 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 17 | return train_X, train_Y #以生成器的方式返回 18 | 19 | train_data = GenerateData() 20 | 21 | batch_size=10 22 | 23 | def train_input_fn(train_data, batch_size): #定义训练数据集输入函数 24 | #构造数据集的组成:一个特征输入,一个标签输入 25 | dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 26 | dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 27 | return dataset #返回数据集 28 | 29 | 30 | 31 | #定义生成loss可视化的函数 32 | plotdata = { "batchsize":[], "loss":[] } 33 | def moving_average(a, w=10): 34 | if len(a) < w: 35 | return a[:] 36 | return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)] 37 | 38 | tf.compat.v1.reset_default_graph() 39 | 40 | 41 | features = tf.compat.v1.placeholder("float",[None])#重新定义占位符 42 | labels = tf.compat.v1.placeholder("float",[None]) 43 | 44 | #其他网络结构不变 45 | W = tf.Variable(tf.random.normal([1]), name="weight") 46 | b = tf.Variable(tf.zeros([1]), name="bias") 47 | predictions = tf.multiply(tf.cast(features,dtype = tf.float32), W)+ b# 前向结构 48 | loss = tf.compat.v1.losses.mean_squared_error(labels=labels, predictions=predictions)#定义损失函数 49 | 50 | global_step = tf.compat.v1.train.get_or_create_global_step()#重新定义global_step 51 | 52 | optimizer = tf.compat.v1.train.AdagradOptimizer(learning_rate=0.1) 53 | train_op = optimizer.minimize(loss, global_step=global_step) 54 | 55 | saver = tf.compat.v1.train.Saver(tf.compat.v1.global_variables(), max_to_keep=1)#重新定义saver 56 | 57 | # 定义学习参数 58 | training_epochs = 500 #设置迭代次数为500 59 | display_step = 2 60 | 61 | dataset = train_input_fn(train_data, batch_size) #重复使用输入函数train_input_fn 62 | one_element = tf.compat.v1.data.make_one_shot_iterator(dataset).get_next() #获得输入数据源张量 63 | 64 | with tf.compat.v1.Session() as sess: 65 | 66 | #恢复估算器检查点文件 67 | savedir = "myestimatormode/" 68 | kpt = tf.train.latest_checkpoint(savedir) #找到检查点文件 69 | print("kpt:",kpt) 70 | saver.restore(sess, kpt) #恢复检查点数据 71 | 72 | # 向模型输入数据 73 | while global_step.eval() < training_epochs: 74 | step = global_step.eval() 75 | x,y =sess.run(one_element) 76 | 77 | sess.run(train_op, feed_dict={features: x, labels: y}) 78 | 79 | #显示训练中的详细信息 80 | if step % display_step == 0: 81 | vloss = sess.run(loss, feed_dict={features: x, labels: y}) 82 | print ("Epoch:", step+1, "cost=", vloss) 83 | if not (vloss == "NA" ): 84 | plotdata["batchsize"].append(global_step.eval()) 85 | plotdata["loss"].append(vloss) 86 | saver.save(sess, savedir+"linermodel.cpkt", global_step) 87 | 88 | print (" Finished!") 89 | saver.save(sess, savedir+"linermodel.cpkt", global_step) 90 | 91 | print ("cost=", sess.run(loss, feed_dict={features: x, labels: y})) 92 | 93 | 94 | 95 | plotdata["avgloss"] = moving_average(plotdata["loss"]) 96 | plt.figure(1) 97 | plt.subplot(211) 98 | plt.plot(plotdata["batchsize"], plotdata["avgloss"], 'b--') 99 | plt.xlabel('Minibatch number') 100 | plt.ylabel('Loss') 101 | plt.title('Minibatch run vs. Training loss') 102 | 103 | plt.show() 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /code/代码3-7 用估算器框架进行分布式训练.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | import numpy as np 11 | tf.compat.v1.disable_v2_behavior() 12 | #在内存中生成模拟数据 13 | def GenerateData(datasize = 100 ): 14 | train_X = np.linspace(-1, 1, datasize) #train_X为-1到1之间连续的100个浮点数 15 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 16 | return train_X, train_Y #以生成器的方式返回 17 | 18 | train_data = GenerateData() 19 | test_data = GenerateData(20) 20 | batch_size=10 21 | 22 | def train_input_fn(train_data, batch_size): #定义训练数据集输入函数 23 | #构造数据集的组成:一个特征输入,一个标签输入 24 | dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 25 | dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 26 | return dataset #返回数据集 27 | 28 | def eval_input_fn(data,labels, batch_size): #定义测试或应用模型时,数据集的输入函数 29 | #batch不允许为空 30 | assert batch_size is not None, "batch_size must not be None" 31 | 32 | if labels is None: #如果评估,则没有标签 33 | inputs = data 34 | else: 35 | inputs = (data,labels) 36 | #构造数据集 37 | dataset = tf.data.Dataset.from_tensor_slices(inputs) 38 | 39 | dataset = dataset.batch(batch_size) #按批次划分 40 | return dataset #返回数据集 41 | 42 | def my_model(features, labels, mode, params):#自定义模型函数:参数是固定的。一个特征,一个标签 43 | #定义网络结构 44 | W = tf.Variable(tf.random.normal([1]), name="weight") 45 | b = tf.Variable(tf.zeros([1]), name="bias") 46 | # 前向结构 47 | predictions = tf.multiply(tf.cast(features,dtype = tf.float32), W)+ b 48 | 49 | if mode == tf.estimator.ModeKeys.PREDICT: #预测处理 50 | return tf.estimator.EstimatorSpec(mode, predictions=predictions) 51 | 52 | #定义损失函数 53 | loss = tf.compat.v1.losses.mean_squared_error(labels=labels, predictions=predictions) 54 | 55 | meanloss = tf.compat.v1.metrics.mean(loss)#添加评估输出项 56 | metrics = {'meanloss':meanloss} 57 | 58 | if mode == tf.estimator.ModeKeys.EVAL: #测试处理 59 | return tf.estimator.EstimatorSpec( mode, loss=loss, eval_metric_ops=metrics) 60 | #return tf.estimator.EstimatorSpec( mode, loss=loss) 61 | 62 | #训练处理. 63 | assert mode == tf.estimator.ModeKeys.TRAIN 64 | optimizer = tf.compat.v1.train.AdagradOptimizer(learning_rate=params['learning_rate']) 65 | train_op = optimizer.minimize(loss, global_step=tf.compat.v1.train.get_global_step()) 66 | return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op) 67 | 68 | 69 | tf.compat.v1.reset_default_graph() #清空图 70 | tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.INFO) #能够控制输出信息 , 71 | gpu_options = tf.compat.v1.GPUOptions(per_process_gpu_memory_fraction=0.333) #构建gpu_options,防止显存占满 72 | session_config=tf.compat.v1.ConfigProto(gpu_options=gpu_options) 73 | #构建估算器 74 | estimator = tf.estimator.Estimator( model_fn=my_model,model_dir='myestimatormode',params={'learning_rate': 0.1}, 75 | config=tf.estimator.RunConfig(session_config=session_config) ) 76 | 77 | 78 | train_spec = tf.estimator.TrainSpec(input_fn=lambda: train_input_fn(train_data, batch_size), max_steps=1000) 79 | eval_spec = tf.estimator.EvalSpec(input_fn=lambda: eval_input_fn(test_data,None, batch_size)) 80 | 81 | tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec) 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /code/代码3-8 用估算器框架分布式训练ps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com (有问必答) 7 | """ 8 | 9 | TF_CONFIG='''{ 10 | "cluster": { 11 | "chief": ["127.0.0.1:2221"], 12 | "worker": ["127.0.0.1:2222"], 13 | "ps": ["127.0.0.1:2223"] 14 | }, 15 | "task": {"type": "ps", "index": 0} 16 | }''' 17 | 18 | import os 19 | os.environ['TF_CONFIG']=TF_CONFIG 20 | print(os.environ.get('TF_CONFIG')) 21 | 22 | 23 | 24 | import tensorflow as tf 25 | import numpy as np 26 | tf.compat.v1.disable_v2_behavior() 27 | #在内存中生成模拟数据 28 | def GenerateData(datasize = 100 ): 29 | train_X = np.linspace(-1, 1, datasize) #train_X为-1到1之间连续的100个浮点数 30 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 31 | return train_X, train_Y #以生成器的方式返回 32 | 33 | train_data = GenerateData() 34 | test_data = GenerateData(20) 35 | batch_size=10 36 | 37 | def train_input_fn(train_data, batch_size): #定义训练数据集输入函数 38 | #构造数据集的组成:一个特征输入,一个标签输入 39 | dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 40 | dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 41 | return dataset #返回数据集 42 | 43 | def eval_input_fn(data,labels, batch_size): #定义测试或应用模型时,数据集的输入函数 44 | #batch不允许为空 45 | assert batch_size is not None, "batch_size must not be None" 46 | 47 | if labels is None: #如果评估,则没有标签 48 | inputs = data 49 | else: 50 | inputs = (data,labels) 51 | #构造数据集 52 | dataset = tf.data.Dataset.from_tensor_slices(inputs) 53 | 54 | dataset = dataset.batch(batch_size) #按批次划分 55 | return dataset #返回数据集 56 | 57 | def my_model(features, labels, mode, params):#自定义模型函数:参数是固定的。一个特征,一个标签 58 | #定义网络结构 59 | W = tf.Variable(tf.random.normal([1]), name="weight") 60 | b = tf.Variable(tf.zeros([1]), name="bias") 61 | # 前向结构 62 | predictions = tf.multiply(tf.cast(features,dtype = tf.float32), W)+ b 63 | 64 | if mode == tf.estimator.ModeKeys.PREDICT: #预测处理 65 | return tf.estimator.EstimatorSpec(mode, predictions=predictions) 66 | 67 | #定义损失函数 68 | loss = tf.compat.v1.losses.mean_squared_error(labels=labels, predictions=predictions) 69 | 70 | meanloss = tf.compat.v1.metrics.mean(loss)#添加评估输出项 71 | metrics = {'meanloss':meanloss} 72 | 73 | if mode == tf.estimator.ModeKeys.EVAL: #测试处理 74 | return tf.estimator.EstimatorSpec( mode, loss=loss, eval_metric_ops=metrics) 75 | #return tf.estimator.EstimatorSpec( mode, loss=loss) 76 | 77 | #训练处理. 78 | assert mode == tf.estimator.ModeKeys.TRAIN 79 | optimizer = tf.compat.v1.train.AdagradOptimizer(learning_rate=params['learning_rate']) 80 | train_op = optimizer.minimize(loss, global_step=tf.compat.v1.train.get_global_step()) 81 | return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op) 82 | 83 | 84 | tf.compat.v1.reset_default_graph() #清空图 85 | tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.INFO) #能够控制输出信息 , 86 | gpu_options = tf.compat.v1.GPUOptions(per_process_gpu_memory_fraction=0.333) #构建gpu_options,防止显存占满 87 | session_config=tf.compat.v1.ConfigProto(gpu_options=gpu_options) 88 | #构建估算器 89 | estimator = tf.estimator.Estimator( model_fn=my_model,model_dir='myestimatormode',params={'learning_rate': 0.1}, 90 | config=tf.estimator.RunConfig(session_config=session_config) ) 91 | 92 | 93 | train_spec = tf.estimator.TrainSpec(input_fn=lambda: train_input_fn(train_data, batch_size), max_steps=6000) 94 | eval_spec = tf.estimator.EvalSpec(input_fn=lambda: eval_input_fn(test_data,None, batch_size)) 95 | 96 | tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec) 97 | 98 | 99 | 100 | 101 | ##偏函数方式 102 | #from functools import partial 103 | #estimator.train(input_fn=partial(train_input_fn, train_data=train_data, batch_size=batch_size),steps=2) 104 | # 105 | ##装饰器方式 106 | #def checkParams(fn): #定义通用参数装饰器函数 107 | # def wrapper(): #使用字典和元组的解包参数来作形参 108 | # return fn(train_data=train_data, batch_size=batch_size) #如满足条件,则将参数透传给原函数,并返回 109 | # return wrapper 110 | # 111 | #@checkParams 112 | #def train_input_fn2(train_data, batch_size): #定义训练数据集输入函数 113 | # #构造数据集的组成:一个特征输入,一个标签输入 114 | # dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 115 | # dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 116 | # return dataset #返回数据集 117 | #estimator.train(input_fn=train_input_fn2, steps=2) 118 | # 119 | #tf.logging.info("训练完成.")#输出训练完成 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /code/代码3-9 用估算器框架进行分布式训练chief.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | TF_CONFIG='''{ 10 | "cluster": { 11 | "chief": ["127.0.0.1:2221"], 12 | "worker": ["127.0.0.1:2222"], 13 | "ps": ["127.0.0.1:2223"] 14 | }, 15 | "task": {"type": "chief", "index": 0} 16 | }''' 17 | 18 | import os 19 | os.environ['TF_CONFIG']=TF_CONFIG 20 | print(os.environ.get('TF_CONFIG')) 21 | 22 | 23 | import tensorflow as tf 24 | import numpy as np 25 | tf.compat.v1.disable_v2_behavior() 26 | #在内存中生成模拟数据 27 | def GenerateData(datasize = 100 ): 28 | train_X = np.linspace(-1, 1, datasize) #train_X为-1到1之间连续的100个浮点数 29 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 30 | return train_X, train_Y #以生成器的方式返回 31 | 32 | train_data = GenerateData() 33 | test_data = GenerateData(20) 34 | batch_size=10 35 | 36 | def train_input_fn(train_data, batch_size): #定义训练数据集输入函数 37 | #构造数据集的组成:一个特征输入,一个标签输入 38 | dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 39 | dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 40 | return dataset #返回数据集 41 | 42 | def eval_input_fn(data,labels, batch_size): #定义测试或应用模型时,数据集的输入函数 43 | #batch不允许为空 44 | assert batch_size is not None, "batch_size must not be None" 45 | 46 | if labels is None: #如果评估,则没有标签 47 | inputs = data 48 | else: 49 | inputs = (data,labels) 50 | #构造数据集 51 | dataset = tf.data.Dataset.from_tensor_slices(inputs) 52 | 53 | dataset = dataset.batch(batch_size) #按批次划分 54 | return dataset #返回数据集 55 | 56 | def my_model(features, labels, mode, params):#自定义模型函数:参数是固定的。一个特征,一个标签 57 | #定义网络结构 58 | W = tf.Variable(tf.random.normal([1]), name="weight") 59 | b = tf.Variable(tf.zeros([1]), name="bias") 60 | # 前向结构 61 | predictions = tf.multiply(tf.cast(features,dtype = tf.float32), W)+ b 62 | 63 | if mode == tf.estimator.ModeKeys.PREDICT: #预测处理 64 | return tf.estimator.EstimatorSpec(mode, predictions=predictions) 65 | 66 | #定义损失函数 67 | loss = tf.compat.v1.losses.mean_squared_error(labels=labels, predictions=predictions) 68 | 69 | meanloss = tf.compat.v1.metrics.mean(loss)#添加评估输出项 70 | metrics = {'meanloss':meanloss} 71 | 72 | if mode == tf.estimator.ModeKeys.EVAL: #测试处理 73 | return tf.estimator.EstimatorSpec( mode, loss=loss, eval_metric_ops=metrics) 74 | #return tf.estimator.EstimatorSpec( mode, loss=loss) 75 | 76 | #训练处理. 77 | assert mode == tf.estimator.ModeKeys.TRAIN 78 | optimizer = tf.compat.v1.train.AdagradOptimizer(learning_rate=params['learning_rate']) 79 | train_op = optimizer.minimize(loss, global_step=tf.compat.v1.train.get_global_step()) 80 | return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op) 81 | 82 | 83 | tf.compat.v1.reset_default_graph() #清空图 84 | tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.INFO) #能够控制输出信息 , 85 | gpu_options = tf.compat.v1.GPUOptions(per_process_gpu_memory_fraction=0.333) #构建gpu_options,防止显存占满 86 | session_config=tf.compat.v1.ConfigProto(gpu_options=gpu_options) 87 | #构建估算器 88 | estimator = tf.estimator.Estimator( model_fn=my_model,model_dir='myestimatormode',params={'learning_rate': 0.1}, 89 | config=tf.estimator.RunConfig(session_config=session_config) ) 90 | 91 | 92 | train_spec = tf.estimator.TrainSpec(input_fn=lambda: train_input_fn(train_data, batch_size), max_steps=6000) 93 | eval_spec = tf.estimator.EvalSpec(input_fn=lambda: eval_input_fn(test_data,None, batch_size)) 94 | 95 | tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec) 96 | 97 | 98 | 99 | 100 | ##偏函数方式 101 | #from functools import partial 102 | #estimator.train(input_fn=partial(train_input_fn, train_data=train_data, batch_size=batch_size),steps=2) 103 | # 104 | ##装饰器方式 105 | #def checkParams(fn): #定义通用参数装饰器函数 106 | # def wrapper(): #使用字典和元组的解包参数来作形参 107 | # return fn(train_data=train_data, batch_size=batch_size) #如满足条件,则将参数透传给原函数,并返回 108 | # return wrapper 109 | # 110 | #@checkParams 111 | #def train_input_fn2(train_data, batch_size): #定义训练数据集输入函数 112 | # #构造数据集的组成:一个特征输入,一个标签输入 113 | # dataset = tf.data.Dataset.from_tensor_slices( ( train_data[0],train_data[1]) ) 114 | # dataset = dataset.shuffle(1000).repeat().batch(batch_size) #将数据集乱序、重复、批次划分. 115 | # return dataset #返回数据集 116 | #estimator.train(input_fn=train_input_fn2, steps=2) 117 | # 118 | #tf.logging.info("训练完成.")#输出训练完成 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /code/代码4-1 将模拟数据制作成内存对象数据集.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import tensorflow as tf 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | 12 | tf.compat.v1.disable_v2_behavior() 13 | 14 | def GenerateData(batchsize=100): 15 | train_x=np.linspace(-1,1,batchsize) 16 | train_y=2*train_x+np.random.randn(*train_x.shape)*0.3 17 | yield train_x,train_y 18 | 19 | 20 | Xinput=tf.compat.v1.placeholder("float",(None)) 21 | Yinput=tf.compat.v1.placeholder("float",(None)) 22 | 23 | training_epochs=20 24 | with tf.compat.v1.Session() as sess: 25 | for epoch in range(training_epochs): 26 | for x,y in GenerateData(): 27 | xv,yv=sess.run([Xinput,Yinput],feed_dict={Xinput:x,Yinput:y}) 28 | 29 | print(epoch,"|x.shape:",np.shape(xv),"|x[:3]:",xv[:3]) 30 | print(epoch,"|y.shape:",np.shape(yv),"|y[:3]:",yv[:3]) 31 | 32 | train_data=list(GenerateData())[0] 33 | plt.plot(train_data[0],train_data[1],'ro',label='Original data') 34 | plt.legend() 35 | plt.show() -------------------------------------------------------------------------------- /code/代码4-11 将图片文件制作成Dataset数据集TFa.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author: 代码医生工作室 3 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 4 | @来源: 配套代码 5 | @配套代码技术支持:bbs.aianaconda.com 6 | """ 7 | import os 8 | import tensorflow as tf 9 | import tensorflow_addons as tfa 10 | tf.compat.v1.disable_v2_behavior() 11 | from sklearn.utils import shuffle 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | 15 | def load_sample(sample_dir,shuffleflag = True): 16 | '''递归读取文件。只支持一级。返回文件名、数值标签、数值对应的标签名''' 17 | print ('loading sample dataset..') 18 | lfilenames = [] 19 | labelsnames = [] 20 | for (dirpath, dirnames, filenames) in os.walk(sample_dir):#递归遍历文件夹 21 | for filename in filenames: #遍历所有文件名 22 | #print(dirnames) 23 | filename_path = os.sep.join([dirpath, filename]) 24 | lfilenames.append(filename_path) #添加文件名 25 | labelsnames.append( dirpath.split('\\')[-1] )#添加文件名对应的标签 26 | 27 | lab= list(sorted(set(labelsnames))) #生成标签名称列表 28 | labdict=dict( zip( lab ,list(range(len(lab))) )) #生成字典 29 | 30 | labels = [labdict[i] for i in labelsnames] 31 | if shuffleflag == True: 32 | return shuffle(np.asarray( lfilenames),np.asarray( labels)),np.asarray(lab) 33 | else: 34 | return (np.asarray( lfilenames),np.asarray( labels)),np.asarray(lab) 35 | 36 | 37 | 38 | directory='man_woman\\' #定义样本路径 39 | (filenames,labels),_ =load_sample(directory,shuffleflag=False) #载入文件名称与标签 40 | 41 | 42 | def _distorted_image(image,size,ch=1,shuffleflag = False,cropflag = False, 43 | brightnessflag=False,contrastflag=False): #定义函数,实现变化图片 44 | distorted_image =tf.image.random_flip_left_right(image) 45 | 46 | if cropflag == True: #随机裁剪 47 | s = tf.random.uniform((1,2),int(size[0]*0.8),size[0],tf.int32) 48 | distorted_image = tf.image.random_crop(distorted_image, [s[0][0],s[0][0],ch]) 49 | 50 | distorted_image = tf.image.random_flip_up_down(distorted_image)#上下随机翻转 51 | if brightnessflag == True:#随机变化亮度 52 | distorted_image = tf.image.random_brightness(distorted_image,max_delta=10) 53 | if contrastflag == True: #随机变化对比度 54 | distorted_image = tf.image.random_contrast(distorted_image,lower=0.2, upper=1.8) 55 | if shuffleflag==True: 56 | distorted_image = tf.random.shuffle(distorted_image)#沿着第0维乱序 57 | return distorted_image 58 | 59 | 60 | def _norm_image(image,size,ch=1,flattenflag = False): #定义函数,实现归一化,并且拍平 61 | image_decoded = image/255.0 62 | if flattenflag==True: 63 | image_decoded = tf.reshape(image_decoded, [size[0]*size[1]*ch]) 64 | return image_decoded 65 | 66 | 67 | def _random_rotated30(image, label): #定义函数实现图片随机旋转操作 68 | def _rotatedwrap(): 69 | 70 | image_rotated = tfa.image.rotate(image,np.deg2rad(30)) #调用第三方函数 71 | return tf.cast(image_rotated,tf.float32) 72 | 73 | a = tf.random.uniform([1],0,2,tf.int32)#实现随机功能 74 | image_decoded = tf.cond(pred=tf.math.equal(tf.constant(0),a[0]),true_fn=lambda: image, false_fn=_rotatedwrap) 75 | 76 | return image_decoded, label 77 | 78 | def dataset(directory,size,batchsize,random_rotated=False):#定义函数,创建数据集 79 | """ parse dataset.""" 80 | (filenames,labels),_ =load_sample(directory,shuffleflag=False) #载入文件名称与标签 81 | def _parseone(filename, label): #解析一个图片文件 82 | """ Reading and handle image""" 83 | image_string = tf.io.read_file(filename) #读取整个文件 84 | image_decoded = tf.image.decode_image(image_string) 85 | image_decoded.set_shape([None, None, None]) # 必须有这句,不然下面会转化失败 86 | image_decoded = _distorted_image(image_decoded,size)#对图片做扭曲变化 87 | image_decoded = tf.image.resize(image_decoded, size) #变化尺寸 88 | image_decoded = _norm_image(image_decoded,size)#归一化 89 | image_decoded = tf.cast(image_decoded,dtype=tf.float32) 90 | label = tf.cast( tf.reshape(label, []) ,dtype=tf.int32 )#将label 转为张量 91 | return image_decoded, label 92 | 93 | dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))#生成Dataset对象 94 | dataset = dataset.map(_parseone) #有图片内容的数据集 95 | 96 | if random_rotated == True: 97 | dataset = dataset.map(_random_rotated30) 98 | 99 | dataset = dataset.batch(batchsize) #批次划分数据集 100 | 101 | return dataset 102 | 103 | 104 | 105 | 106 | #如果显示有错,可以尝试使用np.reshape(thisimg, (size[0],size[1],3))或 107 | #np.asarray(thisimg[0], dtype='uint8')改变类型与形状 108 | def showresult(subplot,title,thisimg): #显示单个图片 109 | p =plt.subplot(subplot) 110 | p.axis('off') 111 | p.imshow(thisimg) 112 | p.set_title(title) 113 | 114 | def showimg(index,label,img,ntop): #显示 115 | plt.figure(figsize=(20,10)) #定义显示图片的宽、高 116 | plt.axis('off') 117 | ntop = min(ntop,9) 118 | print(index) 119 | for i in range (ntop): 120 | showresult(100+10*ntop+1+i,label[i],img[i]) 121 | plt.show() 122 | 123 | def getone(dataset): 124 | iterator = tf.compat.v1.data.make_one_shot_iterator(dataset) #生成一个迭代器 125 | one_element = iterator.get_next() #从iterator里取出一个元素 126 | return one_element 127 | 128 | sample_dir=r"man_woman" 129 | size = [96,96] 130 | batchsize = 10 131 | tdataset = dataset(sample_dir,size,batchsize) 132 | tdataset2 = dataset(sample_dir,size,batchsize,True) 133 | 134 | print(tf.compat.v1.data.get_output_types(tdataset)) 135 | print(tf.compat.v1.data.get_output_shapes(tdataset)) 136 | 137 | 138 | one_element1 = getone(tdataset) #从tdataset里取出一个元素 139 | one_element2 = getone(tdataset2) #从tdataset2里取出一个元素 140 | 141 | 142 | 143 | with tf.compat.v1.Session() as sess: # 建立会话(session) 144 | sess.run(tf.compat.v1.global_variables_initializer()) #初始化 145 | 146 | try: 147 | for step in np.arange(1): 148 | value = sess.run(one_element1) 149 | value2 = sess.run(one_element2) 150 | 151 | showimg(step,value[1],np.asarray( value[0]*255,np.uint8),10) #显示图片 152 | showimg(step,value2[1],np.asarray( value2[0]*255,np.uint8),10) #显示图片 153 | 154 | 155 | except tf.errors.OutOfRangeError: #捕获异常 156 | print("Done!!!") 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /code/代码4-12 在动态图里读取Dataset数据集.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import os 10 | import tensorflow as tf 11 | 12 | from sklearn.utils import shuffle 13 | import numpy as np 14 | import matplotlib.pyplot as plt 15 | 16 | print("TensorFlow 版本: {}".format(tf.__version__)) 17 | print("Eager execution: {}".format(tf.executing_eagerly())) 18 | 19 | 20 | 21 | 22 | def load_sample(sample_dir,shuffleflag = True): 23 | '''递归读取文件。只支持一级。返回文件名、数值标签、数值对应的标签名''' 24 | print ('loading sample dataset..') 25 | lfilenames = [] 26 | labelsnames = [] 27 | for (dirpath, dirnames, filenames) in os.walk(sample_dir):#递归遍历文件夹 28 | for filename in filenames: #遍历所有文件名 29 | #print(dirnames) 30 | filename_path = os.sep.join([dirpath, filename]) 31 | lfilenames.append(filename_path) #添加文件名 32 | labelsnames.append( dirpath.split('\\')[-1] )#添加文件名对应的标签 33 | 34 | lab= list(sorted(set(labelsnames))) #生成标签名称列表 35 | labdict=dict( zip( lab ,list(range(len(lab))) )) #生成字典 36 | 37 | labels = [labdict[i] for i in labelsnames] 38 | if shuffleflag == True: 39 | return shuffle(np.asarray( lfilenames),np.asarray( labels)),np.asarray(lab) 40 | else: 41 | return (np.asarray( lfilenames),np.asarray( labels)),np.asarray(lab) 42 | 43 | 44 | 45 | directory='man_woman\\' #定义样本路径 46 | (filenames,labels),_ =load_sample(directory,shuffleflag=False) #载入文件名称与标签 47 | 48 | 49 | def _distorted_image(image,size,ch=1,shuffleflag = False,cropflag = False, 50 | brightnessflag=False,contrastflag=False): #定义函数,实现变化图片 51 | distorted_image =tf.image.random_flip_left_right(image) 52 | 53 | if cropflag == True: #随机裁剪 54 | s = tf.random.uniform((1,2),int(size[0]*0.8),size[0],tf.int32) 55 | distorted_image = tf.image.random_crop(distorted_image, [s[0][0],s[0][0],ch]) 56 | 57 | distorted_image = tf.image.random_flip_up_down(distorted_image)#上下随机翻转 58 | if brightnessflag == True:#随机变化亮度 59 | distorted_image = tf.image.random_brightness(distorted_image,max_delta=10) 60 | if contrastflag == True: #随机变化对比度 61 | distorted_image = tf.image.random_contrast(distorted_image,lower=0.2, upper=1.8) 62 | if shuffleflag==True: 63 | distorted_image = tf.random.shuffle(distorted_image)#沿着第0维乱序 64 | return distorted_image 65 | 66 | 67 | def _norm_image(image,size,ch=1,flattenflag = False): #定义函数,实现归一化,并且拍平 68 | image_decoded = image/255.0 69 | if flattenflag==True: 70 | image_decoded = tf.reshape(image_decoded, [size[0]*size[1]*ch]) 71 | return image_decoded 72 | 73 | from skimage import transform 74 | def _random_rotated30(image, label): #定义函数实现图片随机旋转操作 75 | 76 | def _rotated(image): #封装好的skimage模块,来进行图片旋转30度 77 | shift_y, shift_x = np.array(image.shape[:2],np.float32) / 2. 78 | tf_rotate = transform.SimilarityTransform(rotation=np.deg2rad(30)) 79 | tf_shift = transform.SimilarityTransform(translation=[-shift_x, -shift_y]) 80 | tf_shift_inv = transform.SimilarityTransform(translation=[shift_x, shift_y]) 81 | image_rotated = transform.warp(image, (tf_shift + (tf_rotate + tf_shift_inv)).inverse) 82 | return image_rotated 83 | 84 | def _rotatedwrap(): 85 | image_rotated = tf.py_function( _rotated,[image],[tf.float64]) #调用第三方函数 86 | return tf.cast(image_rotated,tf.float32)[0] 87 | 88 | a = tf.random.uniform([1],0,2,tf.int32)#实现随机功能 89 | image_decoded = tf.cond(pred=tf.equal(tf.constant(0),a[0]),true_fn=lambda: image,false_fn=_rotatedwrap) 90 | 91 | return image_decoded, label 92 | 93 | 94 | 95 | def dataset(directory,size,batchsize,random_rotated=False):#定义函数,创建数据集 96 | """ parse dataset.""" 97 | (filenames,labels),_ =load_sample(directory,shuffleflag=False) #载入文件名称与标签 98 | def _parseone(filename, label): #解析一个图片文件 99 | """ Reading and handle image""" 100 | image_string = tf.io.read_file(filename) #读取整个文件 101 | image_decoded = tf.image.decode_image(image_string) 102 | image_decoded.set_shape([None, None, None]) # 必须有这句,不然下面会转化失败 103 | image_decoded = _distorted_image(image_decoded,size)#对图片做扭曲变化 104 | image_decoded = tf.image.resize(image_decoded, size) #变化尺寸 105 | image_decoded = _norm_image(image_decoded,size)#归一化 106 | image_decoded = tf.cast(image_decoded,dtype=tf.float32) 107 | label = tf.cast( tf.reshape(label, []) ,dtype=tf.int32 )#将label 转为张量 108 | return image_decoded, label 109 | 110 | dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))#生成Dataset对象 111 | dataset = dataset.map(_parseone) #有图片内容的数据集 112 | 113 | if random_rotated == True: 114 | dataset = dataset.map(_random_rotated30) 115 | 116 | dataset = dataset.batch(batchsize) #批次划分数据集 117 | 118 | return dataset 119 | 120 | 121 | 122 | 123 | #如果显示有错,可以尝试使用np.reshape(thisimg, (size[0],size[1],3))或 124 | #np.asarray(thisimg[0], dtype='uint8')改变类型与形状 125 | def showresult(subplot,title,thisimg): #显示单个图片 126 | p =plt.subplot(subplot) 127 | p.axis('off') 128 | p.imshow(thisimg) 129 | p.set_title(title) 130 | 131 | def showimg(index,label,img,ntop): #显示 132 | plt.figure(figsize=(20,10)) #定义显示图片的宽、高 133 | plt.axis('off') 134 | ntop = min(ntop,9) 135 | print(index) 136 | for i in range (ntop): 137 | showresult(100+10*ntop+1+i,label[i],img[i]) 138 | plt.show() 139 | 140 | def getone(dataset): 141 | iterator = tf.compat.v1.data.make_one_shot_iterator(dataset) #生成一个迭代器 142 | one_element = iterator.get_next() #从iterator里取出一个元素 143 | return one_element 144 | 145 | sample_dir=r"man_woman" 146 | size = [96,96] 147 | batchsize = 10 148 | tdataset = dataset(sample_dir,size,batchsize) 149 | tdataset2 = dataset(sample_dir,size,batchsize,True) 150 | #print(tdataset.output_types) #打印数据集的输出信息 151 | #print(tdataset.output_shapes) 152 | 153 | for step,value in enumerate(tdataset): 154 | showimg(step, value[1].numpy(),np.asarray( value[0]*255,np.uint8),10) #显示图片 155 | 156 | 157 | -------------------------------------------------------------------------------- /code/代码4-13 在不同场景中使用数据集.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | 11 | 12 | tf.compat.v1.disable_v2_behavior() 13 | 14 | dataset1 = tf.data.Dataset.from_tensor_slices( [1,2,3,4,5] ) #定义训练数据集 15 | 16 | #创建迭代器 17 | iterator1 = tf.compat.v1.data.Iterator.from_structure(tf.compat.v1.data.get_output_types(dataset1),tf.compat.v1.data.get_output_shapes(dataset1)) 18 | 19 | one_element1 = iterator1.get_next() 20 | 21 | with tf.compat.v1.Session() as sess2: 22 | sess2.run( iterator1.make_initializer(dataset1) )#初始化迭代器 23 | for ii in range(2): #数据集迭代两次 24 | while True: #通过for循环打印所有的数据 25 | try: 26 | print(sess2.run(one_element1)) #调用sess.run读出Tensor值 27 | except tf.errors.OutOfRangeError: 28 | print("遍历结束") 29 | sess2.run( iterator1.make_initializer(dataset1) )# 从头再来一遍 30 | break 31 | 32 | 33 | print(sess2.run(one_element1,{one_element1:356})) #往数据集中注入数据 34 | 35 | 36 | dataset1 = tf.data.Dataset.from_tensor_slices( [1,2,3,4,5] ) #定义训练数据集 37 | iterator = tf.compat.v1.data.make_one_shot_iterator(dataset1) #生成一个迭代器 38 | 39 | dataset_test = tf.data.Dataset.from_tensor_slices( [10,20,30,40,50] )#定义测试数据集 40 | iterator_test = tf.compat.v1.data.make_one_shot_iterator(dataset1) #生成一个迭代器 41 | #适用于测试与训练场景下的数据集方式 42 | with tf.compat.v1.Session() as sess: 43 | iterator_handle = sess.run(iterator.string_handle()) 44 | iterator_handle_test = sess.run(iterator_test.string_handle()) 45 | 46 | handle = tf.compat.v1.placeholder(tf.string, shape=[]) 47 | iterator3 = tf.compat.v1.data.Iterator.from_string_handle(handle, iterator.output_types) 48 | 49 | one_element3 = iterator3.get_next() 50 | print(sess.run(one_element3,{handle: iterator_handle})) 51 | print(sess.run(one_element3,{handle: iterator_handle_test})) 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /code/代码4-2 带迭代的模拟数据集.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import tensorflow as tf 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | from sklearn.utils import shuffle 12 | tf.compat.v1.disable_v2_behavior() 13 | 14 | def GenerateData(training_epochs,batchsize=100): 15 | for i in range(training_epochs): 16 | train_X=np.linspace(-1,1,batchsize) 17 | train_Y=2*train_X+np.random.randn(*train_X.shape)*0.3 18 | yield shuffle(train_X,train_Y),i 19 | 20 | Xinput=tf.compat.v1.placeholder("float",(None)) 21 | Yinput=tf.compat.v1.placeholder("float",(None)) 22 | 23 | training_epochs=20 24 | with tf.compat.v1.Session() as sess: 25 | for (x,y),ii in GenerateData(training_epochs): 26 | xv,yv=sess.run([Xinput,Yinput],feed_dict={Xinput:x,Yinput:y}) 27 | 28 | print(ii,"|x.shape:",np.shape(xv),"|x[:3]:",xv[:3]) 29 | print(ii,"|y.shape:",np.shape(yv),"|y[:3]:",yv[:3]) 30 | 31 | train_data=list(GenerateData(1))[0] 32 | plt.plot(train_data[0][0],train_data[0][1],'ro',label='Original data') 33 | plt.legend() 34 | plt.show() -------------------------------------------------------------------------------- /code/代码4-3 将图片制作成内存对象数据集.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aianaconda/TensorFlow2x_Engineering_Implementation/6ac6cbf96465e37039286cdf8c0f23b8e53b64e2/code/代码4-3 将图片制作成内存对象数据集.py -------------------------------------------------------------------------------- /code/代码4-4 将Excel文件制作成内存对象数据集.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | 10 | import tensorflow as tf 11 | tf.compat.v1.disable_v2_behavior() 12 | def read_data(file_queue): #csv文件处理函数 13 | reader = tf.compat.v1.TextLineReader(skip_header_lines=1) #tf.TextLineReader 可以每次读取一行 14 | key, value = reader.read(file_queue) 15 | 16 | defaults = [[0], [0.], [0.], [0.], [0.], [0]] #为每个字段设置初始值 17 | cvscolumn = tf.io.decode_csv(records=value, record_defaults=defaults) #tf.decode_csv对每一行进行解析 18 | 19 | featurecolumn = [i for i in cvscolumn[1:-1]] #分离出列中的样本数据列 20 | labelcolumn = cvscolumn[-1] #分离出列中的标签数据列 21 | 22 | return tf.stack(featurecolumn), labelcolumn #返回结果 23 | 24 | def create_pipeline(filename, batch_size, num_epochs=None): #创建队列数据集函数 25 | #创建一个输入队列 26 | file_queue = tf.compat.v1.train.string_input_producer([filename], num_epochs=num_epochs) 27 | 28 | feature, label = read_data(file_queue) #载入数据和标签 29 | 30 | min_after_dequeue = 1000 #设置队列中的最少数据条数(取完数据后,保证还是有1000条) 31 | capacity = min_after_dequeue + batch_size #队列的长度 32 | 33 | feature_batch, label_batch = tf.compat.v1.train.shuffle_batch( #生成乱序的批次数据 34 | [feature, label], batch_size=batch_size, capacity=capacity, 35 | min_after_dequeue=min_after_dequeue 36 | ) 37 | 38 | return feature_batch, label_batch #返回指定批次数据 39 | 40 | #读取训练集 41 | x_train_batch, y_train_batch = create_pipeline('iris_training.csv', 32, num_epochs=100) 42 | #读取测试集 43 | x_test, y_test = create_pipeline('iris_test.csv', 32) 44 | 45 | with tf.compat.v1.Session() as sess: 46 | 47 | init_op = tf.compat.v1.global_variables_initializer() #初始化 48 | local_init_op = tf.compat.v1.local_variables_initializer() #初始化本地变量,没有回报错 49 | sess.run(init_op) 50 | sess.run(local_init_op) 51 | 52 | coord = tf.train.Coordinator() #创建协调器 53 | threads = tf.compat.v1.train.start_queue_runners(coord=coord) #开启线程列队 54 | 55 | try: 56 | while True: 57 | if coord.should_stop(): 58 | break 59 | example, label = sess.run([x_train_batch, y_train_batch]) #注入训练数据 60 | print ("训练数据:",example) #打印数据 61 | print ("训练标签:",label) #打印标签 62 | except tf.errors.OutOfRangeError: #定义取完数据的异常处理 63 | print ('Done reading') 64 | example, label = sess.run([x_test, y_test]) #注入测试数据 65 | print ("测试数据:",example) #打印数据 66 | print ("测试标签:",label) #打印标签 67 | except KeyboardInterrupt: #定义按ctrl+c键时,对应的异常处理 68 | print("程序终止...") 69 | finally: 70 | coord.request_stop() 71 | 72 | coord.join(threads) 73 | sess.close() -------------------------------------------------------------------------------- /code/代码4-5 将图片文件制作成TFRecord数据集.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aianaconda/TensorFlow2x_Engineering_Implementation/6ac6cbf96465e37039286cdf8c0f23b8e53b64e2/code/代码4-5 将图片文件制作成TFRecord数据集.py -------------------------------------------------------------------------------- /code/代码4-6 interleave例子.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | 10 | 11 | import tensorflow as tf 12 | tf.compat.v1.disable_v2_behavior() 13 | Dataset =tf.data.Dataset 14 | 15 | def parse_fn(x): 16 | print(x) 17 | return x 18 | 19 | dataset = (Dataset.list_files('testset\*.txt', shuffle=False) 20 | .interleave(lambda x: 21 | tf.data.TextLineDataset(x).map(parse_fn, num_parallel_calls=1), 22 | cycle_length=2, block_length=2)) 23 | 24 | 25 | 26 | 27 | def getone(dataset): 28 | iterator = tf.compat.v1.data.make_one_shot_iterator(dataset) #生成一个迭代器 29 | one_element = iterator.get_next() #从iterator里取出一个元素 30 | return one_element 31 | 32 | one_element1 = getone(dataset) #从dataset里取出一个元素 33 | 34 | 35 | def showone(one_element,datasetname): 36 | print('{0:-^50}'.format(datasetname)) 37 | for ii in range(20): 38 | datav = sess.run(one_element)#通过静态图注入的方式,传入数据 39 | print(datav) 40 | 41 | 42 | 43 | with tf.compat.v1.Session() as sess: # 建立会话(session) 44 | showone(one_element1,"dataset1") 45 | -------------------------------------------------------------------------------- /code/代码4-7 Dataset对象的操作方法.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aianaconda/TensorFlow2x_Engineering_Implementation/6ac6cbf96465e37039286cdf8c0f23b8e53b64e2/code/代码4-7 Dataset对象的操作方法.py -------------------------------------------------------------------------------- /code/代码4-8 将内存数据转成DataSet数据集.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | 10 | import tensorflow as tf 11 | import numpy as np 12 | tf.compat.v1.disable_v2_behavior() 13 | #在内存中生成模拟数据 14 | def GenerateData(datasize = 100 ): 15 | train_X = np.linspace(-1, 1, datasize) #train_X为-1到1之间连续的100个浮点数 16 | train_Y = 2 * train_X + np.random.randn(*train_X.shape) * 0.3 # y=2x,但是加入了噪声 17 | return train_X, train_Y #以生成器的方式返回 18 | 19 | 20 | train_data = GenerateData() 21 | 22 | #将内存数据转化成数据集 23 | dataset = tf.data.Dataset.from_tensor_slices( train_data ) #元祖 24 | dataset2 = tf.data.Dataset.from_tensor_slices( { #字典 25 | "x":train_data[0], 26 | "y":train_data[1] 27 | } ) # 28 | 29 | batchsize = 10 #定义批次样本个数 30 | dataset3 = dataset.repeat().batch(batchsize) #批次划分数据集 31 | 32 | dataset4 = dataset2.map(lambda data: (data['x'],tf.cast(data['y'],tf.int32)) )#自定义处理数据集元素 33 | dataset5 = dataset.shuffle(100)#乱序数据集 34 | 35 | def getone(dataset): 36 | iterator = tf.compat.v1.data.make_one_shot_iterator(dataset) #生成一个迭代器 37 | one_element = iterator.get_next() #从iterator里取出一个元素 38 | return one_element 39 | 40 | one_element1 = getone(dataset) #从dataset里取出一个元素 41 | one_element2 = getone(dataset2) #从dataset2里取出一个元素 42 | one_element3 = getone(dataset3) #从dataset3里取出一个批次的元素 43 | one_element4 = getone(dataset4) #从dataset4里取出一个批次的元素 44 | one_element5 = getone(dataset5) #从dataset5里取出一个批次的元素 45 | 46 | 47 | def showone(one_element,datasetname): 48 | print('{0:-^50}'.format(datasetname)) 49 | for ii in range(5): 50 | datav = sess.run(one_element)#通过静态图注入的方式,传入数据 51 | print(datasetname,"-",ii,"| x,y:",datav) 52 | 53 | def showbatch(onebatch_element,datasetname): 54 | print('{0:-^50}'.format(datasetname)) 55 | for ii in range(5): 56 | datav = sess.run(onebatch_element)#通过静态图注入的方式,传入数据 57 | print(datasetname,"-",ii,"| x.shape:",np.shape(datav[0]),"| x[:3]:",datav[0][:3]) 58 | print(datasetname,"-",ii,"| y.shape:",np.shape(datav[1]),"| y[:3]:",datav[1][:3]) 59 | 60 | with tf.compat.v1.Session() as sess: # 建立会话(session) 61 | showone(one_element1,"dataset1") 62 | showone(one_element2,"dataset2") 63 | showbatch(one_element3,"dataset3") 64 | showone(one_element4,"dataset4") 65 | showone(one_element5,"dataset5") 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /code/代码4-9 from_tensor_slices的注意事项.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | 11 | 12 | tf.compat.v1.disable_v2_behavior() 13 | dataset1 = tf.data.Dataset.from_tensor_slices( [1,2,3,4,5] ) 14 | #dataset1 = tf.data.Dataset.from_tensor_slices( (1,2,3,4,5) ) 15 | #dataset1 = tf.data.Dataset.from_tensor_slices( ([1],[2],[3],[4],[5]) ) 16 | 17 | def getone(dataset): 18 | iterator = tf.compat.v1.data.make_one_shot_iterator(dataset) #生成一个迭代器 19 | one_element = iterator.get_next() #从iterator里取出一个元素 20 | return one_element 21 | 22 | one_element1 = getone(dataset1) 23 | 24 | with tf.compat.v1.Session() as sess: # 建立会话(session) 25 | for i in range(5): #通过for循环打印所有的数据 26 | print(sess.run(one_element1)) #调用sess.run读出Tensor值 27 | 28 | 29 | 30 | 31 | dataset1 = tf.data.Dataset.from_tensor_slices( ([1],[2],[3],[4],[5]) ) 32 | one_element1 = getone(dataset1) 33 | with tf.compat.v1.Session() as sess: # 建立会话(session) 34 | print(sess.run(one_element1)) #调用sess.run读出Tensor值 -------------------------------------------------------------------------------- /code/代码5-1 用feature_column模块处理连续值特征列.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | tf.compat.v1.disable_v2_behavior() 11 | #演示只有一个连续值特征列的操作 12 | def test_one_column(): 13 | price = tf.feature_column.numeric_column('price') #定义一个特征列 14 | 15 | features = {'price': [[1.], [5.]]} #将样本数据定义为字典的类型 16 | net = tf.compat.v1.feature_column.input_layer(features, [price]) #将数据集与特征列一起输入,到input_layer生成张量 17 | 18 | with tf.compat.v1.Session() as sess: #通过建立会话将其输出 19 | tt = sess.run(net) 20 | print( tt) 21 | 22 | test_one_column() 23 | 24 | #演示带占位符的特征列操作 25 | def test_placeholder_column(): 26 | price = tf.feature_column.numeric_column('price') #定义一个特征列 27 | 28 | features = {'price':tf.compat.v1.placeholder(dtype=tf.float64)} #生成一个value为占位符的字典 29 | net = tf.compat.v1.feature_column.input_layer(features, [price]) #将数据集与特征列一起输入,到input_layer生成张量 30 | 31 | with tf.compat.v1.Session() as sess: #通过建立会话将其输出 32 | tt = sess.run(net, feed_dict={ 33 | features['price']: [[1.], [5.]] 34 | }) 35 | print( tt) 36 | 37 | test_placeholder_column() 38 | 39 | 40 | 41 | 42 | 43 | import numpy as np 44 | print(np.shape([[[1., 2.]], [[5., 6.]]])) 45 | print(np.shape([[3., 4.], [7., 8.]])) 46 | print(np.shape([[3., 4.]])) 47 | def test_reshaping(): 48 | tf.compat.v1.reset_default_graph() 49 | price = tf.feature_column.numeric_column('price', shape=[1, 2])#定义一个特征列,并指定形状 50 | features = {'price': [[[1., 2.]], [[5., 6.]]]} #传入一个3维的数组 51 | features1 = {'price': [[3., 4.], [7., 8.]]} #传入一个2维的数组 52 | 53 | 54 | net = tf.compat.v1.feature_column.input_layer(features, price) #生成特征列张量 55 | net1 = tf.compat.v1.feature_column.input_layer(features1, price) #生成特征列张量 56 | with tf.compat.v1.Session() as sess: #通过建立会话将其输出 57 | print(net.eval()) 58 | print(net1.eval()) 59 | 60 | test_reshaping() 61 | 62 | def test_column_order(): 63 | tf.compat.v1.reset_default_graph() 64 | price_a = tf.feature_column.numeric_column('price_a') #定义了3个特征列 65 | price_b = tf.feature_column.numeric_column('price_b') 66 | price_c = tf.feature_column.numeric_column('price_c') 67 | 68 | features = { #创建字典传入数据 69 | 'price_a': [[1.]], 70 | 'price_c': [[4.]], 71 | 'price_b': [[3.]], 72 | } 73 | 74 | #生成输入层 75 | net = tf.compat.v1.feature_column.input_layer(features, [price_c, price_a, price_b]) 76 | 77 | with tf.compat.v1.Session() as sess: #通过建立会话将其输出 78 | print(net.eval()) 79 | 80 | test_column_order() 81 | 82 | -------------------------------------------------------------------------------- /code/代码5-11 data_loader.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @author: 代码医生工作室 3 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 4 | @来源: 配套代码 5 | @配套代码技术支持:bbs.aianaconda.com 6 | ''' 7 | import numpy as np 8 | import os 9 | 10 | 11 | def load_data(args): 12 | n_user, n_item, train_data, eval_data, test_data = load_rating(args) 13 | n_entity, n_relation, kg = load_kg(args) 14 | print('data loaded.') 15 | 16 | return n_user, n_item, n_entity, n_relation, train_data, eval_data, test_data, kg 17 | 18 | 19 | def load_rating(args): 20 | print('reading rating file ...') 21 | 22 | # reading rating file 23 | rating_file = 'data/' + args.dataset + '/ratings_final' 24 | rating_np = np.loadtxt(rating_file + '.txt', dtype=np.int32) 25 | 26 | n_user = len(set(rating_np[:, 0]))#出现过的用户个数 27 | n_item = len(set(rating_np[:, 1]))#出现过的电影个数 28 | train_data, eval_data, test_data = dataset_split(rating_np) 29 | 30 | return n_user, n_item, train_data, eval_data, test_data 31 | 32 | 33 | def dataset_split(rating_np): 34 | print('splitting dataset ...') 35 | 36 | # train:eval:test = 6:2:2 37 | eval_ratio = 0.2 38 | test_ratio = 0.2 39 | n_ratings = rating_np.shape[0] 40 | 41 | eval_indices = np.random.choice(list(range(n_ratings)), size=int(n_ratings * eval_ratio), replace=False) 42 | left = set(range(n_ratings)) - set(eval_indices) 43 | test_indices = np.random.choice(list(left), size=int(n_ratings * test_ratio), replace=False) 44 | train_indices = list(left - set(test_indices)) 45 | 46 | train_data = rating_np[train_indices] 47 | eval_data = rating_np[eval_indices] 48 | test_data = rating_np[test_indices] 49 | 50 | return train_data, eval_data, test_data 51 | 52 | 53 | def load_kg(args): 54 | print('reading KG file ...') 55 | 56 | # reading kg file 57 | kg_file = 'data/' + args.dataset + '/kg_final' 58 | kg = np.loadtxt(kg_file + '.txt', dtype=np.int32) 59 | 60 | 61 | n_entity = len(set(kg[:, 0]) | set(kg[:, 2]))#两端的实体个数 62 | n_relation = len(set(kg[:, 1])) #关系个数 63 | 64 | return n_entity, n_relation, kg 65 | -------------------------------------------------------------------------------- /code/代码5-2 将连续值特征列转化成离散值特征列.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import tensorflow as tf 9 | tf.compat.v1.disable_v2_behavior() 10 | def test_numeric_cols_to_bucketized(): 11 | price = tf.feature_column.numeric_column('price')#定义连续数值的特征列 12 | 13 | #将连续数值转成离散值的特征列,离散值共分为3段:小于3、在3与5之间、大于5 14 | price_bucketized = tf.feature_column.bucketized_column( price, boundaries=[3.,5.]) 15 | 16 | features = { #传定义字典 17 | 'price': [[2.], [6.]], 18 | } 19 | 20 | net = tf.compat.v1.feature_column.input_layer(features,[ price,price_bucketized]) #生成输入层张量 21 | with tf.compat.v1.Session() as sess: 22 | sess.run(tf.compat.v1.global_variables_initializer()) 23 | print(net.eval()) 24 | 25 | test_numeric_cols_to_bucketized() 26 | 27 | def test_numeric_cols_to_identity(): 28 | tf.compat.v1.reset_default_graph() 29 | price = tf.feature_column.numeric_column('price')#定义连续数值的特征列 30 | 31 | categorical_column = tf.feature_column.categorical_column_with_identity('price', 6) 32 | print(type(categorical_column)) 33 | one_hot_style = tf.feature_column.indicator_column(categorical_column) 34 | features = { #传定义字典 35 | 'price': [[2], [4]], 36 | } 37 | 38 | net = tf.compat.v1.feature_column.input_layer(features,[ price,one_hot_style]) #生成输入层张量 39 | with tf.compat.v1.Session() as sess: 40 | sess.run(tf.compat.v1.global_variables_initializer()) 41 | print(net.eval()) 42 | 43 | test_numeric_cols_to_identity() -------------------------------------------------------------------------------- /code/代码5-3 将离散文本特征列转化为one-hot编码与词向量.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import tensorflow as tf 9 | from tensorflow.python.feature_column.feature_column import _LazyBuilder 10 | tf.compat.v1.disable_v2_behavior()#加不加这句都可以 11 | #将离散文本按照指定范围散列 12 | def test_categorical_cols_to_hash_bucket(): 13 | tf.compat.v1.reset_default_graph() 14 | some_sparse_column = tf.feature_column.categorical_column_with_hash_bucket( 15 | 'sparse_feature', hash_bucket_size=5)#稀疏矩阵,单独放进去会出错 16 | 17 | builder = _LazyBuilder({ 18 | 'sparse_feature': [['a'], ['x']], 19 | }) 20 | id_weight_pair = some_sparse_column._get_sparse_tensors(builder) # 21 | 22 | with tf.compat.v1.Session() as sess: 23 | 24 | id_tensor_eval = id_weight_pair.id_tensor.eval() 25 | print("稀疏矩阵:\n",id_tensor_eval) 26 | 27 | dense_decoded = tf.sparse.to_dense( id_tensor_eval, default_value=-1).eval(session=sess) 28 | print("稠密矩阵:\n",dense_decoded) 29 | 30 | test_categorical_cols_to_hash_bucket() 31 | 32 | 33 | from tensorflow.python.ops import lookup_ops 34 | #将离散文本按照指定词表与指定范围,混合散列 35 | def test_with_1d_sparse_tensor(): 36 | tf.compat.v1.reset_default_graph() 37 | #混合散列 38 | body_style = tf.feature_column.categorical_column_with_vocabulary_list( 39 | 'name', vocabulary_list=['anna', 'gary', 'bob'],num_oov_buckets=2) #稀疏矩阵 40 | 41 | #稠密矩阵 42 | builder = _LazyBuilder({ 43 | 'name': ['anna', 'gary','alsa'], 44 | }) 45 | 46 | #稀疏矩阵 47 | builder2 = _LazyBuilder({ 48 | 'name': tf.SparseTensor( 49 | indices=((0,), (1,), (2,)), 50 | values=('anna', 'gary', 'alsa'), 51 | dense_shape=(3,)), 52 | }) 53 | 54 | id_weight_pair = body_style._get_sparse_tensors(builder) # 55 | id_weight_pair2 = body_style._get_sparse_tensors(builder2) # 56 | 57 | 58 | with tf.compat.v1.Session() as sess: 59 | sess.run(lookup_ops.tables_initializer()) 60 | 61 | id_tensor_eval = id_weight_pair.id_tensor.eval() 62 | print("稀疏矩阵:\n",id_tensor_eval) 63 | id_tensor_eval2 = id_weight_pair2.id_tensor.eval() 64 | print("稀疏矩阵2:\n",id_tensor_eval2) 65 | 66 | dense_decoded = tf.sparse.to_dense( id_tensor_eval, default_value=-1).eval(session=sess) 67 | print("稠密矩阵:\n",dense_decoded) 68 | 69 | test_with_1d_sparse_tensor() 70 | 71 | 72 | #将离散文本转为onehot特征列 73 | def test_categorical_cols_to_onehot(): 74 | tf.compat.v1.reset_default_graph() 75 | some_sparse_column = tf.feature_column.categorical_column_with_hash_bucket( 76 | 'sparse_feature', hash_bucket_size=5) #定义散列特征列 77 | 78 | #转换成one-hot特征列 79 | one_hot_style = tf.feature_column.indicator_column(some_sparse_column) 80 | 81 | 82 | features = { 83 | 'sparse_feature': [['a'], ['x']], 84 | } 85 | 86 | net = tf.compat.v1.feature_column.input_layer(features, one_hot_style) #生成输入层张量 87 | with tf.compat.v1.Session() as sess: #通过会话输出数据 88 | print(net.eval()) 89 | 90 | test_categorical_cols_to_onehot() 91 | 92 | 93 | 94 | 95 | 96 | #将离散文本转为onehot词嵌入特征列 97 | def test_categorical_cols_to_embedding(): 98 | tf.compat.v1.reset_default_graph() 99 | some_sparse_column = tf.feature_column.categorical_column_with_hash_bucket( 100 | 'sparse_feature', hash_bucket_size=5)#稀疏矩阵,单独放进去会出错 101 | 102 | embedding_col = tf.feature_column.embedding_column( some_sparse_column, dimension=3) 103 | 104 | features = { 105 | 'sparse_feature': [['a'], ['x']], 106 | } 107 | 108 | #生成输入层张量 109 | cols_to_vars = {} 110 | net = tf.compat.v1.feature_column.input_layer(features, embedding_col,cols_to_vars) 111 | 112 | with tf.compat.v1.Session() as sess: #通过会话输出数据 113 | sess.run(tf.compat.v1.global_variables_initializer()) 114 | print(net.eval()) 115 | 116 | test_categorical_cols_to_embedding() 117 | 118 | #input_layer中的顺序 119 | def test_order(): 120 | tf.compat.v1.reset_default_graph() 121 | numeric_col = tf.feature_column.numeric_column('numeric_col') 122 | some_sparse_column = tf.feature_column.categorical_column_with_hash_bucket( 123 | 'asparse_feature', hash_bucket_size=5)#稀疏矩阵,单独放进去会出错 124 | 125 | embedding_col = tf.feature_column.embedding_column( some_sparse_column, dimension=3) 126 | #转换成one-hot特征列 127 | one_hot_col = tf.feature_column.indicator_column(some_sparse_column) 128 | print(one_hot_col.name) 129 | print(embedding_col.name) 130 | print(numeric_col.name) 131 | 132 | features = { 133 | 'numeric_col': [[3], [6]], 134 | 'asparse_feature': [['a'], ['x']], 135 | } 136 | 137 | #生成输入层张量 138 | cols_to_vars = {} 139 | net = tf.compat.v1.feature_column.input_layer(features, [numeric_col,one_hot_col,embedding_col],cols_to_vars) 140 | 141 | with tf.compat.v1.Session() as sess: #通过会话输出数据 142 | sess.run(tf.compat.v1.global_variables_initializer()) 143 | print(net.eval()) 144 | 145 | test_order() 146 | -------------------------------------------------------------------------------- /code/代码5-4 根据特征列生成交叉列.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | from tensorflow.python.feature_column.feature_column import _LazyBuilder 11 | tf.compat.v1.disable_v2_behavior() 12 | def test_crossed(): 13 | 14 | a = tf.feature_column.numeric_column('a', dtype=tf.int32, shape=(2,)) 15 | b = tf.feature_column.bucketized_column(a, boundaries=(0, 1)) #离散值转化 16 | crossed = tf.feature_column.crossed_column([b, 'c'], hash_bucket_size=5)#生成交叉列 17 | 18 | builder = _LazyBuilder({ #生成模拟输入的数据 19 | 'a': 20 | tf.constant(((-1.,-1.5), (.5, 1.))), 21 | 'c': 22 | tf.SparseTensor( 23 | indices=((0, 0), (1, 0), (1, 1)), 24 | values=['cA', 'cB', 'cC'], 25 | dense_shape=(2, 2)), 26 | }) 27 | id_weight_pair = crossed._get_sparse_tensors(builder)#生成输入层张量 28 | with tf.compat.v1.Session() as sess2: #建立会话session,取值 29 | id_tensor_eval = id_weight_pair.id_tensor.eval() 30 | print(id_tensor_eval) #输出稀疏矩阵 31 | 32 | dense_decoded = tf.sparse.to_dense( id_tensor_eval, default_value=-1).eval(session=sess2) 33 | print(dense_decoded) #输出稠密矩阵 34 | 35 | test_crossed() 36 | 37 | -------------------------------------------------------------------------------- /code/代码5-5 序列特征工程.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | tf.compat.v1.disable_v2_behavior() 11 | tf.compat.v1.reset_default_graph() 12 | 13 | vocabulary_size = 3 #假如有3个词,向量为0,1,2 14 | 15 | sparse_input_a = tf.SparseTensor( #定义一个稀疏矩阵, 值为: 16 | indices=((0, 0), (1, 0), (1, 1)), # [2] 只有一个序列 17 | values=(2, 0, 1), # [0, 1] 有连个序列 18 | dense_shape=(2, 2)) 19 | 20 | sparse_input_b = tf.SparseTensor( #定义一个稀疏矩阵, 值为: 21 | indices=((0, 0), (1, 0), (1, 1)), # [1] 22 | values=(1, 2, 0), # [2, 0] 23 | dense_shape=(2, 2)) 24 | 25 | embedding_dimension_a = 2 26 | embedding_values_a = ( #为稀疏矩阵的三个值(0,1,2)匹配词嵌入初始值 27 | (1., 2.), # id 0 28 | (3., 4.), # id 1 29 | (5., 6.) # id 2 30 | ) 31 | embedding_dimension_b = 3 32 | embedding_values_b = ( #为稀疏矩阵的三个值(0,1,2)匹配词嵌入初始值 33 | (11., 12., 13.), # id 0 34 | (14., 15., 16.), # id 1 35 | (17., 18., 19.) # id 2 36 | ) 37 | 38 | def _get_initializer(embedding_dimension, embedding_values): #自定义初始化词嵌入 39 | def _initializer(shape, dtype, partition_info): 40 | return embedding_values 41 | return _initializer 42 | 43 | 44 | 45 | categorical_column_a = tf.feature_column.sequence_categorical_column_with_identity( #带序列的离散列 46 | key='a', num_buckets=vocabulary_size) 47 | embedding_column_a = tf.feature_column.embedding_column( #将离散列转为词向量 48 | categorical_column_a, dimension=embedding_dimension_a, 49 | initializer=_get_initializer(embedding_dimension_a, embedding_values_a)) 50 | 51 | 52 | categorical_column_b = tf.feature_column.sequence_categorical_column_with_identity( 53 | key='b', num_buckets=vocabulary_size) 54 | embedding_column_b = tf.feature_column.embedding_column( 55 | categorical_column_b, dimension=embedding_dimension_b, 56 | initializer=_get_initializer(embedding_dimension_b, embedding_values_b)) 57 | 58 | 59 | 60 | shared_embedding_columns = tf.feature_column.shared_embeddings( #共享列 61 | [categorical_column_b, categorical_column_a], 62 | dimension=embedding_dimension_a, 63 | initializer=_get_initializer(embedding_dimension_a, embedding_values_a)) 64 | 65 | features={ #将a,b合起来 66 | 'a': sparse_input_a, 67 | 'b': sparse_input_b, 68 | } 69 | 70 | sequence_feature_layer = tf.keras.experimental.SequenceFeatures(feature_columns=[embedding_column_b, embedding_column_a])#定义序列输入层 71 | input_layer, sequence_length = sequence_feature_layer(features) 72 | 73 | sequence_feature_layer2=tf.keras.experimental.SequenceFeatures(feature_columns=shared_embedding_columns) 74 | input_layer2, sequence_length2 = sequence_feature_layer2(features) #定义序列输入层 75 | 76 | global_vars = tf.compat.v1.get_collection(tf.compat.v1.GraphKeys.GLOBAL_VARIABLES)#返回图中的张量(2个嵌入词权重) 77 | print([v.name for v in global_vars]) 78 | 79 | with tf.compat.v1.train.MonitoredSession() as sess: 80 | print(global_vars[0].eval(session=sess))#输出词向量的初始值 81 | print(global_vars[1].eval(session=sess)) 82 | print(global_vars[2].eval(session=sess)) 83 | print(sequence_length.eval(session=sess)) 84 | print(input_layer.eval(session=sess)) #输出序列输入层的内容 85 | print(sequence_length2.eval(session=sess)) 86 | print(input_layer2.eval(session=sess)) #输出序列输入层的内容 87 | 88 | 89 | -------------------------------------------------------------------------------- /code/代码5-8 preprocess.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author: 代码医生工作室 3 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 4 | @来源: 配套代码 5 | @配套代码技术支持:bbs.aianaconda.com 6 | """ 7 | import argparse 8 | import numpy as np 9 | 10 | RATING_FILE_NAME = dict({'movie': 'ratings.dat', 11 | 'book': 'BX-Book-Ratings.csv', 12 | 'music': 'user_artists.dat', 13 | 'news': 'ratings.txt'}) 14 | SEP = dict({'movie': '::', 'book': ';', 'music': '\t', 'news': '\t'}) 15 | THRESHOLD = dict({'movie': 4, 'book': 0, 'music': 0, 'news': 0}) 16 | 17 | 18 | def read_item_index_to_entity_id_file(): 19 | file = 'data/' + DATASET + '/item_index2entity_id.txt'#具体的业务条目(item) 索引(entity id) 20 | print('reading item index to entity id file: ' + file + ' ...') 21 | i = 0 22 | for line in open(file, encoding='utf-8').readlines(): 23 | item_index = line.strip().split('\t')[0] 24 | satori_id = line.strip().split('\t')[1] 25 | item_index_old2new[item_index] = i#item与行的对应关系(重新编号) 26 | entity_id2index[satori_id] = i #entity id与行的对应关系(重新编号) 27 | i += 1 28 | 29 | #生成ratings_final.txt 用户 电影 喜欢/不关注(1/0)作为标签 30 | def convert_rating(): 31 | file = 'data/' + DATASET + '/' + RATING_FILE_NAME[DATASET] 32 | 33 | print('reading rating file ...') 34 | item_set = set(item_index_old2new.values()) 35 | user_pos_ratings = dict() 36 | user_neg_ratings = dict() 37 | 38 | for line in open(file, encoding='utf-8').readlines()[1:]: 39 | array = line.strip().split(SEP[DATASET]) #userID movieID weight 40 | 41 | # remove prefix and suffix quotation marks for BX dataset 42 | if DATASET == 'book': 43 | array = list(map(lambda x: x[1:-1], array)) 44 | 45 | item_index_old = array[1] 46 | if item_index_old not in item_index_old2new: # the item is not in the final item set 47 | continue 48 | item_index = item_index_old2new[item_index_old] 49 | 50 | user_index_old = int(array[0]) 51 | 52 | rating = float(array[2]) 53 | if rating >= THRESHOLD[DATASET]:#用来区分正向,负向 54 | if user_index_old not in user_pos_ratings: 55 | user_pos_ratings[user_index_old] = set() 56 | user_pos_ratings[user_index_old].add(item_index) 57 | else: 58 | if user_index_old not in user_neg_ratings: 59 | user_neg_ratings[user_index_old] = set() 60 | user_neg_ratings[user_index_old].add(item_index) 61 | 62 | print('converting rating file ...') 63 | writer = open('data/' + DATASET + '/ratings_final.txt', 'w', encoding='utf-8') 64 | user_cnt = 0 65 | user_index_old2new = dict() 66 | for user_index_old, pos_item_set in user_pos_ratings.items(): 67 | if user_index_old not in user_index_old2new: 68 | user_index_old2new[user_index_old] = user_cnt 69 | user_cnt += 1 70 | user_index = user_index_old2new[user_index_old] 71 | 72 | for item in pos_item_set: 73 | writer.write('%d\t%d\t1\n' % (user_index, item)) 74 | unwatched_set = item_set - pos_item_set 75 | if user_index_old in user_neg_ratings: 76 | unwatched_set -= user_neg_ratings[user_index_old] 77 | for item in np.random.choice(list(unwatched_set), size=len(pos_item_set), replace=False): 78 | writer.write('%d\t%d\t0\n' % (user_index, item)) 79 | writer.close() 80 | print('number of users: %d' % user_cnt) 81 | print('number of items: %d' % len(item_set)) 82 | 83 | 84 | def convert_kg(): 85 | print('converting kg.txt file ...') 86 | entity_cnt = len(entity_id2index) 87 | relation_cnt = 0 88 | 89 | writer = open('data/' + DATASET + '/kg_final.txt', 'w', encoding='utf-8') 90 | file = open('data/' + DATASET + '/kg.txt', encoding='utf-8') 91 | 92 | for line in file: 93 | array = line.strip().split('\t') 94 | head_old = array[0] 95 | relation_old = array[1] 96 | tail_old = array[2] 97 | 98 | if head_old not in entity_id2index: 99 | continue 100 | head = entity_id2index[head_old] 101 | 102 | if tail_old not in entity_id2index: 103 | entity_id2index[tail_old] = entity_cnt 104 | entity_cnt += 1 105 | tail = entity_id2index[tail_old] 106 | 107 | if relation_old not in relation_id2index: 108 | relation_id2index[relation_old] = relation_cnt 109 | relation_cnt += 1 110 | relation = relation_id2index[relation_old] 111 | 112 | writer.write('%d\t%d\t%d\n' % (head, relation, tail)) 113 | 114 | writer.close() 115 | print('number of entities (containing items): %d' % entity_cnt) 116 | print('number of relations: %d' % relation_cnt) 117 | 118 | 119 | if __name__ == '__main__': 120 | np.random.seed(555) 121 | 122 | parser = argparse.ArgumentParser() 123 | parser.add_argument('-d', type=str, default='movie', help='which dataset to preprocess') 124 | args = parser.parse_args() 125 | DATASET = args.d 126 | 127 | entity_id2index = dict() 128 | relation_id2index = dict() 129 | item_index_old2new = dict() 130 | 131 | read_item_index_to_entity_id_file() 132 | convert_rating() 133 | convert_kg() 134 | 135 | print('done') 136 | -------------------------------------------------------------------------------- /code/代码6-1 NLP文本预处理.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | 10 | import tensorflow as tf 11 | from preprocessing import text 12 | print('import succeed') 13 | 14 | 15 | positive_data_file ="./data/rt-polaritydata/rt-polarity.pos" 16 | negative_data_file = "./data/rt-polaritydata/rt-polarity.neg" 17 | 18 | def mydataset(positive_data_file,negative_data_file): #定义函数创建数据集 19 | filelist = [positive_data_file,negative_data_file] 20 | 21 | def gline(filelist): #定义生成器函数,返回每一行的数据 22 | for file in filelist: 23 | with open(file, "r",encoding='utf-8') as f: 24 | for line in f: 25 | yield line 26 | 27 | x_text = gline(filelist) 28 | lenlist = [len(x.split(" ")) for x in x_text] 29 | max_document_length = max(lenlist) 30 | vocab_processor = text.VocabularyProcessor(max_document_length,5) 31 | 32 | x_text = gline(filelist) 33 | vocab_processor.fit(x_text) 34 | a=list (vocab_processor.reverse( [list(range(0,len(vocab_processor.vocabulary_)))] )) 35 | print("字典:",a) 36 | 37 | def gen(): #循环生成器(不然一次生成器结束就会没有了) 38 | while True: 39 | x_text2 = gline(filelist) 40 | for i ,x in enumerate(vocab_processor.transform(x_text2)): 41 | if i < int(len(lenlist)/2): 42 | onehot = [1,0] 43 | else: 44 | onehot = [0,1] 45 | yield (x,onehot) 46 | 47 | data = tf.data.Dataset.from_generator( gen,(tf.int64,tf.int64) ) 48 | data = data.shuffle(len(lenlist)) 49 | data = data.batch(256) 50 | data = data.prefetch(1) 51 | return data,vocab_processor,max_document_length #返回数据集、字典、最大长度 52 | 53 | if __name__ == '__main__': #单元测试代码 54 | data,_,_ =mydataset(positive_data_file,negative_data_file) 55 | iterator = tf.compat.v1.data.make_initializable_iterator(data) 56 | next_element = iterator.get_next() 57 | 58 | with tf.compat.v1.Session() as sess2: 59 | sess2.run(iterator.initializer) 60 | for i in range(80): 61 | print("batched data 1:",i)#, 62 | sess2.run(next_element) 63 | -------------------------------------------------------------------------------- /code/代码6-2 TextCNN模型.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author: 代码医生工作室 3 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 4 | @来源: 配套代码 5 | @配套代码技术支持:bbs.aianaconda.com 6 | """ 7 | import tensorflow as tf 8 | import numpy as np 9 | from tensorflow.keras import layers 10 | tf.compat.v1.disable_v2_behavior() 11 | class TextCNN(object): 12 | """ 13 | TextCNN文本分类器. 14 | """ 15 | def __init__( 16 | self, sequence_length, num_classes, vocab_size, 17 | embedding_size, filter_sizes, num_filters, l2_reg_lambda=0.0): 18 | 19 | #定义占位符 20 | self.input_x = tf.compat.v1.placeholder(tf.int32, [None, sequence_length], name="input_x") 21 | self.input_y = tf.compat.v1.placeholder(tf.float32, [None, num_classes], name="input_y") 22 | self.dropout_keep_prob = tf.compat.v1.placeholder(tf.float32, name="dropout_keep_prob") 23 | 24 | #词嵌入层 25 | embed_initer = tf.keras.initializers.RandomUniform(minval=-1, maxval=1) 26 | 27 | embed = layers.Embedding(vocab_size, embedding_size, 28 | embeddings_initializer=embed_initer, 29 | input_length=sequence_length, 30 | name='Embedding')(self.input_x) 31 | 32 | embed = layers.Reshape((sequence_length, embedding_size, 1), name='add_channel')(embed) 33 | 34 | #定义多通道卷积 与最大池化网络 35 | pool_outputs = [] 36 | 37 | for i, filter_size in enumerate(filter_sizes): 38 | filter_shape = (filter_size, embedding_size) 39 | 40 | conv = layers.Conv2D(num_filters, filter_shape, strides=(1, 1), padding='valid', 41 | #activation='relu', 42 | activation=tf.nn.leaky_relu, 43 | kernel_initializer='glorot_normal', 44 | bias_initializer=tf.keras.initializers.constant(0.1), 45 | name='convolution_{:d}'.format(filter_size))(embed) 46 | 47 | max_pool_shape = (sequence_length - filter_size + 1, 1) 48 | pool = layers.MaxPool2D(pool_size=max_pool_shape, 49 | strides=(1, 1), padding='valid', 50 | #data_format='channels_last', 51 | name='max_pooling_{:d}'.format(filter_size))(conv) 52 | 53 | pool_outputs.append(pool) 54 | 55 | #展开特征,并添加dropout 56 | pool_outputs = layers.concatenate(pool_outputs, axis=-1, name='concatenate') 57 | pool_outputs = layers.Flatten(data_format='channels_last', name='flatten')(pool_outputs) 58 | pool_outputs = layers.Dropout(self.dropout_keep_prob, name='dropout')(pool_outputs) 59 | 60 | 61 | #计算L2_loss 62 | l2_loss = tf.constant(0.0) 63 | 64 | outputs = layers.Dense(num_classes, activation=None, 65 | kernel_initializer='glorot_normal', 66 | bias_initializer=tf.keras.initializers.constant(0.1), 67 | kernel_regularizer=tf.keras.regularizers.l2(l2_reg_lambda), 68 | bias_regularizer=tf.keras.regularizers.l2(l2_reg_lambda), 69 | name='dense')(pool_outputs) 70 | 71 | for tf_var in tf.compat.v1.trainable_variables(): 72 | if ("dense" in tf_var.name ): 73 | l2_loss += tf.reduce_mean(input_tensor=tf.nn.l2_loss(tf_var)) 74 | print("tf_var",tf_var) 75 | 76 | self.predictions = tf.argmax(input=outputs, axis=1, name="predictions") 77 | 78 | # 计算交叉熵 79 | with tf.compat.v1.name_scope("loss"): 80 | losses = tf.nn.softmax_cross_entropy_with_logits(logits=outputs, labels=self.input_y) 81 | self.loss = tf.reduce_mean(input_tensor=losses) + l2_reg_lambda * l2_loss 82 | 83 | #计算准确率 84 | with tf.compat.v1.name_scope("accuracy"): 85 | correct_predictions = tf.equal(self.predictions, tf.argmax(input=self.input_y, axis=1)) 86 | self.accuracy = tf.reduce_mean(input_tensor=tf.cast(correct_predictions, "float"), name="accuracy") 87 | 88 | def build_mode(self):#定义函数构建模型 89 | self.global_step = tf.Variable(0, name="global_step", trainable=False) 90 | optimizer = tf.compat.v1.train.AdamOptimizer(1e-3) 91 | grads_and_vars = optimizer.compute_gradients(self.loss) 92 | self.train_op = optimizer.apply_gradients(grads_and_vars, global_step=self.global_step) 93 | 94 | #生成摘要 95 | grad_summaries = [] 96 | for g, v in grads_and_vars: 97 | if g is not None: 98 | grad_hist_summary = tf.compat.v1.summary.histogram("{}/grad/hist".format(v.name), g) 99 | sparsity_summary = tf.compat.v1.summary.scalar("{}/grad/sparsity".format(v.name), tf.nn.zero_fraction(g)) 100 | grad_summaries.append(grad_hist_summary) 101 | grad_summaries.append(sparsity_summary) 102 | grad_summaries_merged = tf.compat.v1.summary.merge(grad_summaries) 103 | #生成损失及准确率的摘要 104 | loss_summary = tf.compat.v1.summary.scalar("loss", self.loss) 105 | acc_summary = tf.compat.v1.summary.scalar("accuracy", self.accuracy) 106 | 107 | #合并摘要 108 | self.train_summary_op = tf.compat.v1.summary.merge([loss_summary, acc_summary, grad_summaries_merged]) 109 | 110 | -------------------------------------------------------------------------------- /code/代码6-2 用keras注意力机制模型分析评论者的情绪.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | 10 | import tensorflow as tf 11 | import numpy as np 12 | tf.compat.v1.disable_v2_behavior() 13 | attention_keras = __import__("代码6-3 keras注意力机制模型") 14 | 15 | #定义参数 16 | num_words = 20000 17 | maxlen = 80 18 | batch_size = 32 19 | 20 | #加载数据 21 | print('Loading data...') 22 | (x_train, y_train), (x_test, y_test) = tf.keras.datasets.imdb.load_data(path='./imdb.npz',num_words=num_words) 23 | print(len(x_train), 'train sequences') 24 | print(len(x_test), 'test sequences') 25 | print(x_train[0]) 26 | print(y_train[:10]) 27 | 28 | word_index = tf.keras.datasets.imdb.get_word_index('./imdb_word_index.json')# 单词--下标 对应字典 29 | reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])# 下标-单词对应字典 30 | 31 | decoded_newswire = ' '.join([reverse_word_index.get(i - 3, '?') for i in x_train[0]]) 32 | print(decoded_newswire) 33 | 34 | 35 | 36 | #数据对齐 37 | x_train = tf.keras.preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen) 38 | x_test = tf.keras.preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen) 39 | print('Pad sequences x_train shape:', x_train.shape) 40 | 41 | #定义输入节点 42 | S_inputs = tf.keras.layers.Input(shape=(None,), dtype='int32') 43 | 44 | #生成词向量 45 | embeddings = tf.keras.layers.Embedding(num_words, 128)(S_inputs) 46 | embeddings = attention_keras.Position_Embedding()(embeddings) #默认使用同等维度的位置向量 47 | #(None,None,128) 48 | 49 | 50 | 51 | #使用内部注意力模型处理 52 | O_seq = attention_keras.Attention(8,16)([embeddings,embeddings,embeddings]) 53 | print("O_seq",O_seq) 54 | #将结果进行全局池化 55 | O_seq = tf.keras.layers.GlobalAveragePooling1D()(O_seq) 56 | #添加dropout 57 | #O_seq = tf.keras.layers.Dropout(0.5)(O_seq) 58 | O_seq =attention_keras.TargetedDropout(drop_rate=0.5, target_rate=0.5)(O_seq) 59 | #输出最终节点 60 | outputs = tf.keras.layers.Dense(1, activation='sigmoid')(O_seq) 61 | print(outputs) 62 | #将网络结构组合到一起 63 | model = tf.keras.models.Model(inputs=S_inputs, outputs=outputs) 64 | 65 | #添加反向传播节点 66 | model.compile(loss='binary_crossentropy',optimizer='adam', metrics=['accuracy']) 67 | 68 | #开始训练 69 | print('Train...') 70 | model.fit(x_train, y_train, batch_size=batch_size,epochs=5, validation_data=(x_test, y_test)) -------------------------------------------------------------------------------- /code/代码6-3 用TextCNN模型进行文本分类.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import tensorflow as tf 9 | import os 10 | import time 11 | import datetime 12 | tf.compat.v1.disable_v2_behavior() 13 | predata = __import__("代码6-1 NLP文本预处理") 14 | mydataset = predata.mydataset 15 | text_cnn = __import__("代码6-2 TextCNN模型") 16 | TextCNN = text_cnn.TextCNN 17 | 18 | def train(): 19 | #指定样本文件 20 | positive_data_file ="./data/rt-polaritydata/rt-polarity.pos" 21 | negative_data_file = "./data/rt-polaritydata/rt-polarity.neg" 22 | #设置训练参数 23 | num_steps = 2000 #定义训练次数 24 | display_every=20 #定义训练中的显示间隔 25 | checkpoint_every=100 #定义训练中保存模型的间隔 26 | SaveFileName= "text_cnn_model" #定义保存模型文件夹名称 27 | #设置模型参数 28 | num_classes =2 #设置模型分类 29 | dropout_keep_prob =0.8 #定义dropout系数 30 | l2_reg_lambda=0.1 #定义正则化系数 31 | filter_sizes = "3,4,5" #定义多通道卷积核 32 | num_filters =64 #定义每通道的输出个数 33 | 34 | tf.compat.v1.reset_default_graph()#清空图 35 | 36 | #预处理生成字典及数据集 37 | data,vocab_processor,max_document_length =mydataset(positive_data_file,negative_data_file) 38 | iterator = tf.compat.v1.data.make_one_shot_iterator(data) 39 | next_element = iterator.get_next() 40 | 41 | #定义TextCnn网络 42 | cnn = TextCNN( 43 | sequence_length=max_document_length, 44 | num_classes=num_classes, 45 | vocab_size=len(vocab_processor.vocabulary_), 46 | embedding_size=128, 47 | filter_sizes=list(map(int, filter_sizes.split(","))), 48 | num_filters=num_filters, 49 | l2_reg_lambda=l2_reg_lambda) 50 | #构建网络 51 | cnn.build_mode() 52 | 53 | #打开session,准备训练 54 | session_conf = tf.compat.v1.ConfigProto(allow_soft_placement=True,log_device_placement=False) 55 | with tf.compat.v1.Session(config=session_conf) as sess: 56 | sess.run(tf.compat.v1.global_variables_initializer()) 57 | 58 | 59 | #准备输出模型路径 60 | timestamp = str(int(time.time())) 61 | out_dir = os.path.abspath(os.path.join(os.path.curdir, SaveFileName, timestamp)) 62 | print("Writing to {}\n".format(out_dir)) 63 | 64 | #准备输出摘要路径 65 | train_summary_dir = os.path.join(out_dir, "summaries", "train") 66 | train_summary_writer = tf.compat.v1.summary.FileWriter(train_summary_dir, sess.graph) 67 | 68 | 69 | #准备检查点名称 70 | checkpoint_dir = os.path.abspath(os.path.join(out_dir, "checkpoints")) 71 | checkpoint_prefix = os.path.join(checkpoint_dir, "model") 72 | if not os.path.exists(checkpoint_dir): 73 | os.makedirs(checkpoint_dir) 74 | #定义保存检查点的saver 75 | saver = tf.compat.v1.train.Saver(tf.compat.v1.global_variables(), max_to_keep=1) 76 | 77 | #保存字典 78 | vocab_processor.save(os.path.join(out_dir, "vocab")) 79 | 80 | def train_step(x_batch, y_batch):#训练步骤 81 | feed_dict = { 82 | cnn.input_x: x_batch, 83 | cnn.input_y: y_batch, 84 | cnn.dropout_keep_prob: dropout_keep_prob 85 | } 86 | _, step, summaries, loss, accuracy = sess.run( 87 | [cnn.train_op, cnn.global_step, cnn.train_summary_op, cnn.loss, cnn.accuracy], 88 | feed_dict) 89 | time_str = datetime.datetime.now().isoformat() 90 | train_summary_writer.add_summary(summaries, step) 91 | return (time_str, step, loss, accuracy) 92 | 93 | i = 0 94 | while tf.compat.v1.train.global_step(sess, cnn.global_step) < num_steps: 95 | x_batch, y_batch = sess.run(next_element) 96 | i = i+1 97 | time_str, step, loss, accuracy =train_step(x_batch, y_batch) 98 | 99 | current_step = tf.compat.v1.train.global_step(sess, cnn.global_step) 100 | if current_step % display_every == 0: 101 | print("{}: step {}, loss {:g}, acc {:g}".format(time_str, step, loss, accuracy)) 102 | 103 | if current_step % checkpoint_every == 0: 104 | path = saver.save(sess, checkpoint_prefix, global_step=current_step) 105 | print("Saved model checkpoint to {}\n".format(path)) 106 | 107 | def main(argv=None): 108 | train()#启动训练 109 | 110 | if __name__ == '__main__': 111 | tf.compat.v1.app.run() -------------------------------------------------------------------------------- /code/代码6-5 pipline方式运行Transformers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | #代码6-5 pipline方式运行Transformers 10 | 11 | 12 | 13 | 14 | ################分类############################## 15 | 16 | from transformers import * 17 | nlp_sentence_classif= pipeline("sentiment-analysis") #自动加载模型 18 | print(nlp_sentence_classif ("I like this book!")) #调用模型进行处理 19 | 20 | ################抽取特征############################## 21 | import numpy as np 22 | nlp_features = pipeline('feature-extraction') 23 | output = nlp_features( 24 | 'Code Doctor Studio is a Chinese company based in BeiJing.') 25 | print(np.array(output).shape) #输出特征形状 26 | 27 | ################完型填空############################## 28 | nlp_fill = pipeline("fill-mask") 29 | print(nlp_fill.tokenizer.mask_token) #输出遮蔽字符:'[MASK]' 30 | #调用模型进行处理 31 | print(nlp_fill(f"Li Jinhong wrote many {nlp_fill.tokenizer.mask_token} about artificial intelligence technology and helped many people.")) 32 | 33 | 34 | ################阅读理解############################## 35 | nlp_qa = pipeline("question-answering") #实例化模型 36 | print( #输出模型处理结果 37 | nlp_qa(context='Code Doctor Studio is a Chinese company based in BeiJing.', 38 | question='Where is Code Doctor Studio?') ) 39 | 40 | 41 | ################摘要生成############################## 42 | TEXT_TO_SUMMARIZE = ''' 43 | In this notebook we will be using the transformer model, first introduced in this paper. Specifically, we will be using the BERT (Bidirectional Encoder Representations from Transformers) model from this paper. 44 | Transformer models are considerably larger than anything else covered in these tutorials. As such we are going to use the transformers library to get pre-trained transformers and use them as our embedding layers. We will freeze (not train) the transformer and only train the remainder of the model which learns from the representations produced by the transformer. In this case we will be using a multi-layer bi-directional GRU, however any model can learn from these representations. 45 | ''' 46 | summarizer = pipeline("summarization", model="t5-small", tokenizer="t5-small", 47 | framework="tf") 48 | print(summarizer(TEXT_TO_SUMMARIZE,min_length=5, max_length=150)) 49 | 50 | 51 | 52 | 53 | ################实体词############################## 54 | nlp_token_class = pipeline("ner") 55 | print(nlp_token_class( 56 | 'Code Doctor Studio is a Chinese company based in BeiJing.')) 57 | 58 | 59 | from transformers import ALL_PRETRAINED_MODEL_ARCHIVE_MAP 60 | print(ALL_PRETRAINED_MODEL_ARCHIVE_MAP) 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /code/代码6-6 用BERT模型实现完型填空.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | 10 | 11 | 12 | import tensorflow as tf 13 | from transformers import * 14 | 15 | #加载预训练模型 tokenizer (vocabulary) 16 | tokenizer = BertTokenizer.from_pretrained('bert-base-cased') 17 | 18 | 19 | 20 | 21 | 22 | 23 | #输入文本 24 | text = "[CLS] Who is Li Jinhong ? [SEP] Li Jinhong is a programmer [SEP]" 25 | tokenized_text = tokenizer.tokenize(text) 26 | print(tokenized_text) 27 | 28 | masked_index = 15 #掩码一个标记,用' BertForMaskedLM '预测回来 29 | tokenized_text[masked_index] = '[MASK]' 30 | print(tokenized_text) 31 | 32 | # 将标记转换为词汇表索引 33 | indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text) 34 | # 将输入转换为张量 35 | tokens_tensor = tf.constant([indexed_tokens]) 36 | 37 | 38 | # 加载预训练模型 (weights) 39 | model = TFAutoModelWithLMHead.from_pretrained('bert-base-uncased') 40 | 41 | 42 | segments_ids = [0, 0, 0, 0, 0, 0, 0, 0,0,0, 1, 1, 1, 1, 1, 1, 1,1,1] 43 | segments_tensors = tf.constant([segments_ids]) 44 | 45 | 46 | # 预测所有的tokens 47 | # output = model(tokens_tensor) 48 | outputs = model(tokens_tensor, token_type_ids=segments_tensors) 49 | 50 | predictions = outputs[0] #[1, 19, 30522] 51 | 52 | predicted_index = tf.argmax(predictions[0, masked_index]) 53 | predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0] #转成单词 54 | print('Predicted token is:',predicted_token) 55 | 56 | 57 | -------------------------------------------------------------------------------- /code/代码6-7 用GPT2模型生成句子.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | 10 | import tensorflow as tf 11 | from transformers import * 12 | 13 | # 加载预训练模型(权重) 14 | tokenizer = GPT2Tokenizer.from_pretrained('gpt2') 15 | 16 | 17 | #编码输入 18 | indexed_tokens = tokenizer.encode("Who is Li Jinhong ? Li Jinhong is a") 19 | 20 | print( tokenizer.decode(indexed_tokens)) 21 | 22 | tokens_tensor = tf.constant([indexed_tokens])#转换为张量 23 | 24 | # 加载预训练模型(权重) 25 | model = GPT2LMHeadModel.from_pretrained('gpt2') 26 | 27 | 28 | 29 | 30 | 31 | # 预测所有标记 32 | 33 | outputs = model(tokens_tensor) 34 | predictions = outputs[0]#(1, 13, 50257) 35 | 36 | # 得到预测的下一词 37 | predicted_index = tf.argmax(predictions[0, -1, :]) 38 | predicted_text = tokenizer.decode(indexed_tokens + [predicted_index]) 39 | print(predicted_text) 40 | 41 | 42 | #生成一段完整的话 43 | stopids = tokenizer.convert_tokens_to_ids(["."])[0] 44 | past = None 45 | for i in range(100): 46 | 47 | output, past = model(tokens_tensor, past=past) 48 | token = tf.argmax(output[..., -1, :],axis= -1) 49 | 50 | indexed_tokens += token.numpy().tolist() 51 | 52 | if stopids== token.numpy()[0]: 53 | break 54 | tokens_tensor = token[None,:] #增加一个维度 55 | 56 | sequence = tokenizer.decode(indexed_tokens) 57 | 58 | print(sequence) 59 | 60 | 61 | -------------------------------------------------------------------------------- /code/代码6-8 迁移训练BERT模型对中文分类.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import tensorflow as tf 10 | from transformers import * 11 | import os 12 | 13 | 14 | data_dir='./THUCNews/data' #定义数据集根目录 15 | #获取分类信息 16 | class_list = [x.strip() for x in open( 17 | os.path.join(data_dir, "class.txt")).readlines()] 18 | 19 | tokenizer = BertTokenizer.from_pretrained(r'./bert-base-chinese/bert-base-chinese-vocab.txt') 20 | #定义指定分类的配置文件 21 | config = AutoConfig.from_pretrained( 22 | r'./bert-base-chinese/bert-base-chinese-config.json',num_labels=len(class_list)) 23 | #初始化模型,单独指定config,在config中指定分类个数 24 | model = TFAutoModelForSequenceClassification.from_pretrained( 25 | r'./bert-base-chinese/bert-base-chinese-tf_model.h5', 26 | config=config) 27 | 28 | 29 | def read_file(path): #读取数据集文件内容 30 | with open(path, 'r', encoding="UTF-8") as file: 31 | docus = file.readlines() 32 | newDocus = [] 33 | labs = [] 34 | for data in docus: 35 | content, label = data.split('\t') 36 | label = int(label) 37 | newDocus.append(content) 38 | labs.append(label) 39 | 40 | ids = tokenizer.batch_encode_plus( newDocus, 41 | #!!!!!模型的配置文件中就是512,当有超过这个长度的会报错 42 | max_length=model.config.max_position_embeddings, 43 | pad_to_max_length=True)#,return_tensors='tf')#没有return_tensors会返回list!!!! 44 | 45 | return (ids["input_ids"],ids["attention_mask"],labs) 46 | 47 | #获得训练集和测试集 48 | trainContent = read_file(os.path.join(data_dir, "train.txt")) 49 | testContent = read_file(os.path.join(data_dir, "test.txt")) 50 | 51 | 52 | def getdataset(features): #定义函数,封装数据集 53 | 54 | def gen(): #定义生成器 55 | for ex in zip(features[0],features[1],features[2]): 56 | yield ( 57 | { 58 | "input_ids": ex[0], 59 | "attention_mask": ex[1], 60 | }, 61 | ex[2], 62 | ) 63 | 64 | return tf.data.Dataset.from_generator( #返回数据集 65 | gen, 66 | ({"input_ids": tf.int32, "attention_mask": tf.int32}, tf.int64), 67 | ( 68 | { 69 | "input_ids": tf.TensorShape([None]), 70 | "attention_mask": tf.TensorShape([None]), 71 | }, 72 | tf.TensorShape([]), 73 | ), 74 | ) 75 | 76 | #制作数据集 77 | valid_dataset = getdataset(testContent) 78 | train_dataset = getdataset(trainContent) 79 | #设置批次 80 | train_dataset = train_dataset.shuffle(100).batch(8).repeat(2) 81 | valid_dataset = valid_dataset.batch(16) 82 | 83 | #定义优化器 84 | optimizer = tf.keras.optimizers.Adam(learning_rate=3e-5, epsilon=1e-08, clipnorm=1.0) 85 | loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) 86 | metric = tf.keras.metrics.SparseCategoricalAccuracy('accuracy') 87 | model.compile(optimizer=optimizer, loss=loss, metrics=[metric]) 88 | 89 | #训练模型 90 | history = model.fit(train_dataset, epochs=2, steps_per_epoch=115, 91 | validation_data=valid_dataset, validation_steps=7) 92 | 93 | #保存模型 94 | savedir = r'./myfinetun-bert_chinese/' 95 | os.makedirs(savedir, exist_ok=True) 96 | model.save_pretrained(savedir) 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /code/代码7-1 用AI模型识别图像.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import numpy as np 10 | from tensorflow.keras.applications.resnet50 import ResNet50 11 | from tensorflow.keras.preprocessing import image 12 | from tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictions 13 | 14 | 15 | model = ResNet50(weights='resnet50_weights_tf_dim_ordering_tf_kernels.h5') 16 | 17 | 18 | img_path = 'book2.png' 19 | img = image.load_img(img_path, target_size=(224, 224)) 20 | x = image.img_to_array(img) 21 | x = np.expand_dims(x, axis=0) 22 | x = preprocess_input(x) 23 | 24 | preds = model.predict(x) 25 | 26 | 27 | predtop3 = decode_predictions(preds, top=3)[0] 28 | print('Predicted:', predtop3) 29 | 30 | -------------------------------------------------------------------------------- /code/代码7-10 weights.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import numpy as np 9 | import struct 10 | 11 | class WeightReader: 12 | def __init__(self, weight_file): 13 | with open(weight_file, 'rb') as w_f: 14 | major, = struct.unpack('i', w_f.read(4)) 15 | minor, = struct.unpack('i', w_f.read(4)) 16 | _, = struct.unpack('i', w_f.read(4)) 17 | 18 | if (major*10 + minor) >= 2 and major < 1000 and minor < 1000: 19 | w_f.read(8) 20 | else: 21 | w_f.read(4) 22 | binary = w_f.read() 23 | 24 | self.offset = 0 25 | self.all_weights = np.frombuffer(binary, dtype='float32') 26 | 27 | def load_weights(self, model, skip_detect_layer=False): 28 | 29 | # 81 93 105 30 | for i in range(model.num_layers): 31 | if skip_detect_layer and i in [81, 93, 105]: 32 | skip_size = self._skip(i) 33 | self._read_bytes(skip_size) 34 | continue 35 | 36 | suffixes = ["beta", "gamma", "moving_mean", "moving_variance", "bias"] 37 | for suffix in suffixes: 38 | variables = model.get_variables(layer_idx=i, suffix=suffix) 39 | if variables: 40 | self._load_1d_var(variables[0]) 41 | 42 | variables = model.get_variables(layer_idx=i, suffix="kernel") 43 | if variables: 44 | self._load_4d_var(variables[0]) 45 | 46 | print(self.offset) # 62001757 47 | 48 | def _skip(self, i): 49 | if i == 81: 50 | skip_size = 255 + 1024*255 51 | elif i == 93: 52 | skip_size = 255 + 512*255 53 | elif i == 105: 54 | skip_size = 255 + 256*255 55 | else: 56 | skip_size = 0 57 | return skip_size 58 | 59 | def _read_bytes(self, size): 60 | self.offset = self.offset + size 61 | return self.all_weights[self.offset-size:self.offset] 62 | 63 | def _load_1d_var(self, variable): 64 | size = np.prod(variable.shape) 65 | value = self._read_bytes(size) # bias 66 | variable.assign(value) 67 | 68 | def _load_4d_var(self, variable): 69 | size = np.prod(variable.shape) 70 | value = self._read_bytes(size) # scale 71 | value = value.reshape(list(reversed(variable.shape))) 72 | value = value.transpose([2,3,1,0]) 73 | variable.assign(value) 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /code/代码7-11 yololoss.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import tensorflow as tf 9 | 10 | def _create_mesh_xy(batch_size, grid_h, grid_w, n_box):#生成带序号的网格 11 | mesh_x = tf.cast(tf.reshape(tf.tile(tf.range(grid_w), [grid_h]), (1, grid_h, grid_w, 1, 1)),tf.float32) 12 | mesh_y = tf.transpose(a=mesh_x, perm=(0,2,1,3,4)) 13 | mesh_xy = tf.tile(tf.concat([mesh_x,mesh_y],-1), [batch_size, 1, 1, n_box, 1]) 14 | return mesh_xy 15 | 16 | def adjust_pred_tensor(y_pred):#将网格信息融入坐标,置信度做sigmoid。并重新组合 17 | grid_offset = _create_mesh_xy(*y_pred.shape[:4]) 18 | pred_xy = grid_offset + tf.sigmoid(y_pred[..., :2]) #计算该尺度矩阵上的坐标sigma(t_xy) + c_xy 19 | pred_wh = y_pred[..., 2:4] #取出预测物体的尺寸t_wh 20 | pred_conf = tf.sigmoid(y_pred[..., 4]) #对分类概率(置信度)做sigmoid转化 21 | pred_classes = y_pred[..., 5:] #取出分类结果 22 | #重新组合 23 | preds = tf.concat([pred_xy, pred_wh, tf.expand_dims(pred_conf, axis=-1), pred_classes], axis=-1) 24 | return preds 25 | 26 | #生成一个矩阵。每个格子里放有3个候选框 27 | def _create_mesh_anchor(anchors, batch_size, grid_h, grid_w, n_box): 28 | mesh_anchor = tf.tile(anchors, [batch_size*grid_h*grid_w]) 29 | mesh_anchor = tf.reshape(mesh_anchor, [batch_size, grid_h, grid_w, n_box, 2])#每个候选框有2个值 30 | mesh_anchor = tf.cast(mesh_anchor, tf.float32) 31 | return mesh_anchor 32 | 33 | def conf_delta_tensor(y_true, y_pred, anchors, ignore_thresh): 34 | 35 | pred_box_xy, pred_box_wh, pred_box_conf = y_pred[..., :2], y_pred[..., 2:4], y_pred[..., 4] 36 | #带有候选框的格子矩阵 37 | anchor_grid = _create_mesh_anchor(anchors, *y_pred.shape[:4])#y_pred.shape为(2,13,13,3,15) 38 | true_wh = y_true[:,:,:,:,2:4] 39 | true_wh = anchor_grid * tf.exp(true_wh) 40 | true_wh = true_wh * tf.expand_dims(y_true[:,:,:,:,4], 4)#还原真实尺寸,高和宽 41 | anchors_ = tf.constant(anchors, dtype='float', shape=[1,1,1,y_pred.shape[3],2])#y_pred.shape[3]为候选框个数 42 | true_xy = y_true[..., 0:2]#获取中心点 43 | true_wh_half = true_wh / 2. 44 | true_mins = true_xy - true_wh_half#计算起始坐标 45 | true_maxes = true_xy + true_wh_half#计算尾部坐标 46 | 47 | pred_xy = pred_box_xy 48 | pred_wh = tf.exp(pred_box_wh) * anchors_ 49 | 50 | pred_wh_half = pred_wh / 2. 51 | pred_mins = pred_xy - pred_wh_half#计算起始坐标 52 | pred_maxes = pred_xy + pred_wh_half#计算尾部坐标 53 | 54 | intersect_mins = tf.maximum(pred_mins, true_mins) 55 | intersect_maxes = tf.minimum(pred_maxes, true_maxes) 56 | 57 | #计算重叠面积 58 | intersect_wh = tf.maximum(intersect_maxes - intersect_mins, 0.) 59 | intersect_areas = intersect_wh[..., 0] * intersect_wh[..., 1] 60 | 61 | true_areas = true_wh[..., 0] * true_wh[..., 1] 62 | pred_areas = pred_wh[..., 0] * pred_wh[..., 1] 63 | #计算不重叠面积 64 | union_areas = pred_areas + true_areas - intersect_areas 65 | best_ious = tf.truediv(intersect_areas, union_areas)#计算iou 66 | #ios小于阈值将作为负向的loss 67 | conf_delta = pred_box_conf * tf.cast(best_ious < ignore_thresh,tf.float32) 68 | return conf_delta 69 | 70 | def wh_scale_tensor(true_box_wh, anchors, image_size): 71 | image_size_ = tf.reshape(tf.cast(image_size, tf.float32), [1,1,1,1,2]) 72 | anchors_ = tf.constant(anchors, dtype='float', shape=[1,1,1,3,2]) 73 | 74 | #计算高和宽的缩放范围 75 | wh_scale = tf.exp(true_box_wh) * anchors_ / image_size_ 76 | #物体尺寸占整个图片的面积比 77 | wh_scale = tf.expand_dims(2 - wh_scale[..., 0] * wh_scale[..., 1], axis=4) 78 | return wh_scale 79 | 80 | #位置loss为box之差乘缩放比,所得的结果,再进行平方求和 81 | def loss_coord_tensor(object_mask, pred_box, true_box, wh_scale, xywh_scale): 82 | xy_delta = object_mask * (pred_box-true_box) * wh_scale * xywh_scale 83 | loss_xy = tf.reduce_sum(input_tensor=tf.square(xy_delta), axis=list(range(1,5)))#按照1,2,3,4(xyhw)规约求和 84 | return loss_xy 85 | 86 | def loss_conf_tensor(object_mask, pred_box_conf, true_box_conf, obj_scale, noobj_scale, conf_delta): 87 | object_mask_ = tf.squeeze(object_mask, axis=-1) 88 | conf_delta = object_mask_ * (pred_box_conf-true_box_conf) * obj_scale + (1-object_mask_) * conf_delta * noobj_scale 89 | loss_conf = tf.reduce_sum(input_tensor=tf.square(conf_delta), axis=list(range(1,4)))#按照1,2,3(候选框)归约求和,0为批次 90 | return loss_conf 91 | 92 | 93 | def loss_class_tensor(object_mask, pred_box_class, true_box_class, class_scale): 94 | true_box_class_ = tf.cast(true_box_class, tf.int64) 95 | class_delta = object_mask * \ 96 | tf.expand_dims(tf.nn.softmax_cross_entropy_with_logits(labels=true_box_class_, logits=pred_box_class), 4) * \ 97 | class_scale 98 | 99 | loss_class = tf.reduce_sum(input_tensor=class_delta, axis=list(range(1,5))) 100 | return loss_class 101 | 102 | ignore_thresh=0.5 103 | grid_scale=1 104 | obj_scale=5 105 | noobj_scale=1 106 | xywh_scale=1 107 | class_scale=1 108 | def lossCalculator(y_true, y_pred, anchors,image_size): #image_size【h,w】 109 | y_pred = tf.reshape(y_pred, y_true.shape) #(2, 13, 13, 3, 15) 110 | 111 | object_mask = tf.expand_dims(y_true[..., 4], 4)#(2, 13, 13, 3, 1) 112 | preds = adjust_pred_tensor(y_pred)#将box与置信度数值变化后重新组合 113 | 114 | conf_delta = conf_delta_tensor(y_true, preds, anchors, ignore_thresh) 115 | wh_scale = wh_scale_tensor(y_true[..., 2:4], anchors, image_size) 116 | 117 | loss_box = loss_coord_tensor(object_mask, preds[..., :4], y_true[..., :4], wh_scale, xywh_scale) 118 | loss_conf = loss_conf_tensor(object_mask, preds[..., 4], y_true[..., 4], obj_scale, noobj_scale, conf_delta) 119 | loss_class = loss_class_tensor(object_mask, preds[..., 5:], y_true[..., 5:], class_scale) 120 | loss = loss_box + loss_conf + loss_class 121 | return loss*grid_scale 122 | 123 | def loss_fn(list_y_trues, list_y_preds,anchors,image_size): 124 | inputanchors = [anchors[12:],anchors[6:12],anchors[:6]] 125 | losses = [lossCalculator(list_y_trues[i], list_y_preds[i], inputanchors[i],image_size) for i in range(len(list_y_trues)) ] 126 | return tf.math.sqrt(tf.math.reduce_sum(input_tensor=losses)) #将三个矩阵的loss相加再开平方 127 | 128 | 129 | -------------------------------------------------------------------------------- /code/代码7-12 mainyolo.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | import os 10 | import tensorflow as tf 11 | import glob 12 | from tqdm import tqdm 13 | import cv2 14 | import matplotlib.pyplot as plt 15 | 16 | generator = __import__("代码7-5 generator") 17 | BatchGenerator = generator.BatchGenerator 18 | box = __import__("代码7-6 box") 19 | draw_boxes = box.draw_boxes 20 | yolov3 = __import__("代码7-9 yolov3") 21 | Yolonet = yolov3.Yolonet 22 | yololoss = __import__("代码7-11 yololoss") 23 | loss_fn = yololoss.loss_fn 24 | 25 | 26 | PROJECT_ROOT = os.path.dirname(__file__)#获取当前目录 27 | print('PROJECT_ROOT',PROJECT_ROOT) 28 | 29 | #定义coco锚点候选框 30 | COCO_ANCHORS = [10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326] 31 | #定义预训练模型路径 32 | YOLOV3_WEIGHTS = os.path.join(PROJECT_ROOT, "yolov3.weights") 33 | #定义分类 34 | LABELS = ['0',"1", "2", "3",'4','5','6','7','8', "9"] 35 | 36 | #定义样本路径 37 | ann_dir = os.path.join(PROJECT_ROOT, "data", "ann", "*.xml") 38 | img_dir = os.path.join(PROJECT_ROOT, "data", "img") 39 | 40 | train_ann_fnames = glob.glob(ann_dir)#获取该路径下的xml文件 41 | 42 | imgsize =416 43 | batch_size =2 44 | #制作数据集 45 | generator = BatchGenerator(train_ann_fnames,img_dir, 46 | net_size=imgsize, 47 | anchors=COCO_ANCHORS, 48 | batch_size=2, 49 | labels=LABELS, 50 | jitter = False)#随机变化尺寸。数据增强 51 | 52 | #定义训练参数 53 | learning_rate = 1e-4 #定义学习率 54 | num_epoches =85 #定义迭代次数 55 | save_dir = "./model" #定义模型路径 56 | 57 | #循环整个数据集,进行loss值验证 58 | def _loop_validation(model, generator): 59 | n_steps = generator.steps_per_epoch 60 | loss_value = 0 61 | for _ in range(n_steps): #按批次循环获取数据,并计算loss 62 | xs, yolo_1, yolo_2, yolo_3 = generator.next_batch() 63 | xs=tf.convert_to_tensor(value=xs) 64 | yolo_1=tf.convert_to_tensor(value=yolo_1) 65 | yolo_2=tf.convert_to_tensor(value=yolo_2) 66 | yolo_3=tf.convert_to_tensor(value=yolo_3) 67 | ys = [yolo_1, yolo_2, yolo_3] 68 | ys_ = model(xs ) 69 | loss_value += loss_fn(ys, ys_,anchors=COCO_ANCHORS, 70 | image_size=[imgsize, imgsize] ) 71 | loss_value /= generator.steps_per_epoch 72 | return loss_value 73 | 74 | #循环整个数据集,进行模型训练 75 | 76 | def _loop_train(model,optimizer, generator,grad): 77 | # one epoch 78 | n_steps = generator.steps_per_epoch 79 | for _ in tqdm(range(n_steps)):#按批次循环获取数据,并计算训练 80 | xs, yolo_1, yolo_2, yolo_3 = generator.next_batch() 81 | xs=tf.convert_to_tensor(value=xs) 82 | yolo_1=tf.convert_to_tensor(value=yolo_1) 83 | yolo_2=tf.convert_to_tensor(value=yolo_2) 84 | yolo_3=tf.convert_to_tensor(value=yolo_3) 85 | ys = [yolo_1, yolo_2, yolo_3] 86 | optimizer.apply_gradients(zip(grad(yolo_v3,xs, ys),yolo_v3.variables)) 87 | 88 | if not os.path.exists(save_dir): 89 | os.makedirs(save_dir) 90 | save_fname = os.path.join(save_dir, "weights") 91 | 92 | yolo_v3 = Yolonet(n_classes=len(LABELS))#实例化yolo模型类对象 93 | yolo_v3.load_darknet_params(YOLOV3_WEIGHTS, skip_detect_layer=True)#加载预训练模型 94 | 95 | #定义优化器 96 | optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=learning_rate) 97 | 98 | #定义函数计算loss 99 | def _grad_fn(yolo_v3, images_tensor, list_y_trues): 100 | 101 | with tf.GradientTape() as tape: 102 | logits = yolo_v3(images_tensor) 103 | #tape.watch(yolo_v3.trainable_variables) 104 | loss = loss_fn(list_y_trues, logits,anchors=COCO_ANCHORS,image_size=[imgsize, imgsize]) 105 | #grad=tape.gradient(target=loss,sources=yolo_v3.trainable_variables) 106 | grad=tape.gradient(target=loss,sources=yolo_v3.variables) 107 | return grad 108 | 109 | grad=_grad_fn 110 | 111 | history = [] 112 | 113 | for i in range(num_epoches): 114 | _loop_train(yolo_v3,optimizer, generator,grad)#训练 115 | 116 | loss_value = _loop_validation(yolo_v3, generator)#验证 117 | print("{}-th loss = {}".format(i, loss_value)) 118 | 119 | #收集loss 120 | history.append(loss_value) 121 | if loss_value == min(history):#只有loss创新低时再保存模型 122 | print(" update weight {}".format(loss_value)) 123 | yolo_v3.save_weights("{}.h5".format(save_fname)) 124 | ################################################################ 125 | #使用模型 126 | 127 | IMAGE_FOLDER = os.path.join(PROJECT_ROOT, "data", "test","*.png") 128 | img_fnames = glob.glob(IMAGE_FOLDER) 129 | 130 | imgs = [] #存放图片 131 | for fname in img_fnames:#读取图片 132 | img = cv2.imread(fname) 133 | img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 134 | imgs.append(img) 135 | 136 | yolo_v3.load_weights(save_fname+".h5")#将训练好的模型载入 137 | import numpy as np 138 | for img in imgs: #依次传入模型 139 | boxes, labels, probs = yolo_v3.detect(img, COCO_ANCHORS,imgsize) 140 | print(boxes, labels, probs) 141 | image = draw_boxes(img, boxes, labels, probs, class_labels=LABELS, desired_size=400) 142 | image = np.asarray(image,dtype= np.uint8) 143 | plt.imshow(image) 144 | plt.show() 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /code/代码7-2 用EfficientNet模型识别图像.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import numpy as np 9 | from keras.preprocessing import image 10 | from keras.applications.imagenet_utils import decode_predictions,preprocess_input 11 | from keras_efficientnets import EfficientNetB0 12 | # from keras_efficientnets import EfficientNetB4 13 | 14 | 15 | #6.7.10节 动态图 16 | #tf.enable_eager_execution() #启动动态图 17 | #model = EfficientNetB4(weights='efficientnet-b4.h5') 18 | model = EfficientNetB0(weights='efficientnet-b0.h5') 19 | 20 | img_path = 'dog.jpg' 21 | img = image.load_img(img_path, target_size=(224, 224)) 22 | x = image.img_to_array(img) 23 | x = np.expand_dims(x, axis=0) 24 | x = preprocess_input(x) 25 | 26 | preds = model.predict(x) 27 | print('Predicted:', decode_predictions(preds, top=3)[0]) 28 | 29 | #6.7.10节 动态图 30 | #preds = model(x) 31 | #print('Predicted:', decode_predictions(preds.numpy(), top=3)[0]) -------------------------------------------------------------------------------- /code/代码7-5 generator.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import numpy as np 9 | from random import shuffle 10 | annotation = __import__("代码7-4 annotation") 11 | parse_annotation = annotation.parse_annotation 12 | ImgAugment= annotation.ImgAugment 13 | 14 | box = __import__("代码7-6 box") 15 | find_match_box = box.find_match_box 16 | 17 | DOWNSAMPLE_RATIO = 32 18 | 19 | class BatchGenerator(object): 20 | def __init__(self, ann_fnames, img_dir,labels, 21 | batch_size, anchors, net_size=416, 22 | jitter=True, shuffle=True): 23 | self.ann_fnames = ann_fnames 24 | self.img_dir = img_dir 25 | self.lable_names = labels 26 | self._net_size = net_size 27 | self.jitter = jitter 28 | self.anchors = create_anchor_boxes(anchors)#按照anchors的尺寸,生成坐标从00开始的框 29 | self.batch_size = batch_size 30 | self.shuffle = shuffle 31 | self.steps_per_epoch = int(len(ann_fnames) / batch_size) 32 | self._epoch = 0 33 | self._end_epoch = False 34 | self._index = 0 35 | 36 | def next_batch(self): 37 | xs,ys_1,ys_2,ys_3 = [],[],[],[] 38 | for _ in range(self.batch_size): 39 | x, y1, y2, y3 = self._get() 40 | xs.append(x) 41 | ys_1.append(y1) 42 | ys_2.append(y2) 43 | ys_3.append(y3) 44 | if self._end_epoch == True: 45 | if self.shuffle: 46 | shuffle(self.ann_fnames) 47 | self._end_epoch = False 48 | self._epoch += 1 49 | return np.array(xs).astype(np.float32), np.array(ys_1).astype(np.float32), np.array(ys_2).astype(np.float32), np.array(ys_3).astype(np.float32) 50 | 51 | def _get(self): 52 | net_size = self._net_size 53 | #解析标注文件 54 | fname, boxes, coded_labels = parse_annotation(self.ann_fnames[self._index], self.img_dir, self.lable_names) 55 | #读取图片,并按照设置修改图片尺寸 56 | img_augmenter = ImgAugment(net_size, net_size, self.jitter) 57 | img, boxes_ = img_augmenter.imread(fname, boxes) 58 | 59 | #生成3种尺度的格子 60 | list_ys = _create_empty_xy(net_size, len(self.lable_names)) 61 | for original_box, label in zip(boxes_, coded_labels): 62 | #在anchors中,找到与其面积区域最匹配的候选框max_anchor,对应的尺度索引,该尺度下的第几个锚点 63 | max_anchor, scale_index, box_index = _find_match_anchor(original_box, self.anchors) 64 | #计算在对应尺度上的中心点坐标和对应候选框的长宽缩放比例 65 | _coded_box = _encode_box(list_ys[scale_index], original_box, max_anchor, net_size, net_size) 66 | _assign_box(list_ys[scale_index], box_index, _coded_box, label) 67 | 68 | self._index += 1 69 | if self._index == len(self.ann_fnames): 70 | self._index = 0 71 | self._end_epoch = True 72 | 73 | return img/255., list_ys[2], list_ys[1], list_ys[0] 74 | 75 | #初始化标签 76 | def _create_empty_xy(net_size, n_classes, n_boxes=3): 77 | #获得最小矩阵格子 78 | base_grid_h, base_grid_w = net_size//DOWNSAMPLE_RATIO, net_size//DOWNSAMPLE_RATIO 79 | #初始化三种不同尺度的矩阵。用于存放标签 80 | ys_1 = np.zeros((1*base_grid_h, 1*base_grid_w, n_boxes, 4+1+n_classes)) 81 | ys_2 = np.zeros((2*base_grid_h, 2*base_grid_w, n_boxes, 4+1+n_classes)) 82 | ys_3 = np.zeros((4*base_grid_h, 4*base_grid_w, n_boxes, 4+1+n_classes)) 83 | list_ys = [ys_3, ys_2, ys_1] 84 | return list_ys 85 | 86 | def _encode_box(yolo, original_box, anchor_box, net_w, net_h): 87 | x1, y1, x2, y2 = original_box 88 | _, _, anchor_w, anchor_h = anchor_box 89 | #取出格子在高和宽方向上的个数 90 | grid_h, grid_w = yolo.shape[:2] 91 | 92 | #根据原始图片到当前矩阵的缩放比例,计算当前矩阵中,物体的中心点坐标 93 | center_x = .5*(x1 + x2) 94 | center_x = center_x / float(net_w) * grid_w 95 | center_y = .5*(y1 + y2) 96 | center_y = center_y / float(net_h) * grid_h 97 | 98 | #计算物体相对于候选框的尺寸缩放值 99 | w = np.log(max((x2 - x1), 1) / float(anchor_w)) # t_w 100 | h = np.log(max((y2 - y1), 1) / float(anchor_h)) # t_h 101 | box = [center_x, center_y, w, h]#将中心点和缩放值打包返回 102 | return box 103 | 104 | #找到与物体尺寸最接近的候选框 105 | def _find_match_anchor(box, anchor_boxes): 106 | x1, y1, x2, y2 = box 107 | shifted_box = np.array([0, 0, x2-x1, y2-y1]) 108 | max_index = find_match_box(shifted_box, anchor_boxes) 109 | max_anchor = anchor_boxes[max_index] 110 | scale_index = max_index // 3 111 | box_index = max_index%3 112 | return max_anchor, scale_index, box_index 113 | 114 | #将具体的值放到标签矩阵里。作为真正的标签 115 | def _assign_box(yolo, box_index, box, label): 116 | center_x, center_y, _, _ = box 117 | #向下取整,得到的就是格子的索引 118 | grid_x = int(np.floor(center_x)) 119 | grid_y = int(np.floor(center_y)) 120 | #填入所计算的数值,作为标签 121 | yolo[grid_y, grid_x, box_index] = 0. 122 | yolo[grid_y, grid_x, box_index, 0:4] = box 123 | yolo[grid_y, grid_x, box_index, 4 ] = 1. 124 | yolo[grid_y, grid_x, box_index, 5+label] = 1. 125 | 126 | def create_anchor_boxes(anchors):#将候选框变为box 127 | boxes = [] 128 | n_boxes = int(len(anchors)/2) 129 | for i in range(n_boxes): 130 | boxes.append(np.array([0, 0, anchors[2*i], anchors[2*i+1]])) 131 | return np.array(boxes) 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /code/代码7-9 yolov3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import tensorflow as tf 9 | import numpy as np 10 | import cv2 11 | box = __import__("代码7-6 box") 12 | boxes_to_array = box.boxes_to_array 13 | to_minmax = box.to_minmax 14 | BoundBox = box.BoundBox 15 | nms_boxes = box.nms_boxes 16 | correct_yolo_boxes = box.correct_yolo_boxes 17 | darknet53 = __import__("代码7-7 darknet53") 18 | Darknet53 = darknet53.Darknet53 19 | weights = __import__("代码7-9 yolov3") 20 | WeightReader = weights.WeightReader 21 | yolohead = __import__("代码7-8 yolohead") 22 | Headnet = yolohead.Headnet 23 | 24 | layers = tf.keras.layers 25 | 26 | # Yolo v3 27 | class Yolonet(tf.keras.Model): 28 | def __init__(self, n_classes=80): 29 | 30 | super(Yolonet, self).__init__(name='') 31 | 32 | self.body = Darknet53() 33 | self.head = Headnet(n_classes) 34 | 35 | self.num_layers = 110 36 | self._init_vars() 37 | 38 | def load_darknet_params(self, weights_file, skip_detect_layer=False): 39 | weight_reader = WeightReader(weights_file) 40 | weight_reader.load_weights(self, skip_detect_layer) 41 | 42 | def predict(self, input_array): 43 | f5, f4, f3 = self.call(tf.constant(input_array.astype(np.float32))) 44 | return f5.numpy(), f4.numpy(), f3.numpy() 45 | 46 | def call(self, input_tensor, training=False): 47 | s3, s4, s5 = self.body(input_tensor, training) 48 | f5, f4, f3 = self.head(s3, s4, s5, training) 49 | return f5, f4, f3 50 | 51 | def get_variables(self, layer_idx, suffix=None): 52 | if suffix: 53 | find_name = "layer_{}/{}".format(layer_idx, suffix) 54 | else: 55 | find_name = "layer_{}/".format(layer_idx) 56 | variables = [] 57 | for v in self.variables: 58 | if find_name in v.name: 59 | variables.append(v) 60 | return variables 61 | 62 | def _init_vars(self): 63 | sample = tf.constant(np.random.randn(1, 224, 224, 3).astype(np.float32)) 64 | self.call(sample, training=False) 65 | 66 | def detect(self, image, anchors, net_size=416): 67 | image_h, image_w, _ = image.shape 68 | new_image = preprocess_input(image, net_size) 69 | # 3. predict 70 | yolos = self.predict(new_image) 71 | boxes_ = postprocess_ouput(yolos, anchors, net_size, image_h, image_w) 72 | 73 | if len(boxes_) > 0: 74 | boxes, probs = boxes_to_array(boxes_) 75 | boxes = to_minmax(boxes) 76 | labels = np.array([b.get_label() for b in boxes_]) 77 | else: 78 | boxes, labels, probs = [], [], [] 79 | return boxes, labels, probs 80 | 81 | def postprocess_ouput(yolos, anchors, net_size, image_h, image_w, obj_thresh=0.5, nms_thresh=0.5): 82 | 83 | anchors = np.array(anchors).reshape(3, 6) 84 | boxes = [] 85 | 86 | for i in range(len(yolos)): 87 | boxes += decode_netout(yolos[i][0], anchors[3-(i+1)], obj_thresh, net_size) 88 | 89 | correct_yolo_boxes(boxes, image_h, image_w) 90 | 91 | nms_boxes(boxes, nms_thresh) 92 | return boxes 93 | 94 | 95 | def decode_netout(netout, anchors, obj_thresh, net_size, nb_box=3): 96 | 97 | n_rows, n_cols = netout.shape[:2] 98 | netout = netout.reshape((n_rows, n_cols, nb_box, -1)) 99 | 100 | boxes = [] 101 | for row in range(n_rows): 102 | for col in range(n_cols): 103 | for b in range(nb_box): 104 | 105 | x, y, w, h = _decode_coords(netout, row, col, b, anchors) 106 | objectness, classes = _activate_probs(netout[row, col, b, 4],#分值 107 | netout[row, col, b, 5:],#分类 108 | obj_thresh) 109 | 110 | #scale normalize 111 | x /= n_cols 112 | y /= n_rows 113 | w /= net_size 114 | h /= net_size 115 | 116 | if objectness > obj_thresh: 117 | box = BoundBox(x, y, w, h, objectness, classes) 118 | boxes.append(box) 119 | 120 | return boxes 121 | 122 | 123 | def _decode_coords(netout, row, col, b, anchors): 124 | x, y, w, h = netout[row, col, b, :4] #取出前4个坐标 125 | 126 | x = col + _sigmoid(x) 127 | y = row + _sigmoid(y) 128 | w = anchors[2 * b + 0] * np.exp(w) 129 | h = anchors[2 * b + 1] * np.exp(h) 130 | 131 | return x, y, w, h 132 | 133 | 134 | def _activate_probs(objectness, classes, obj_thresh=0.3): 135 | 136 | # 1. sigmoid activation 137 | objectness_prob = _sigmoid(objectness) 138 | classes_probs = _sigmoid(classes) 139 | # 2. conditional probability 140 | classes_conditional_probs = classes_probs * objectness_prob 141 | # 3. thresholding 142 | classes_conditional_probs *= objectness_prob > obj_thresh 143 | return objectness_prob, classes_conditional_probs 144 | 145 | 146 | def _sigmoid(x): 147 | return 1. / (1. + np.exp(-x)) 148 | 149 | def preprocess_input(image, net_size): 150 | 151 | # resize the image to the new size 152 | preprocess_img = cv2.resize(image/255., (net_size, net_size)) 153 | return np.expand_dims(preprocess_img, axis=0) 154 | 155 | -------------------------------------------------------------------------------- /code/代码8-1 用tf.keras实现变分自编码模型.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | from scipy.stats import norm 11 | 12 | from tensorflow.keras.layers import * 13 | from tensorflow.keras.models import * 14 | import tensorflow as tf 15 | import tensorflow.keras.backend as K 16 | from tensorflow.keras.datasets import mnist 17 | from tensorflow.keras.optimizers import Adam 18 | 19 | from tensorflow.keras import metrics 20 | # tf.compat.v1.disable_v2_behavior() 21 | 22 | batch_size = 100 23 | original_dim = 784 #28*28 24 | latent_dim = 2 25 | intermediate_dim = 256 26 | nb_epoch = 50 27 | 28 | 29 | class Encoder(tf.keras.Model): # 提取图片特征 30 | def __init__(self ,intermediate_dim,latent_dim, **kwargs): 31 | super(Encoder, self).__init__(**kwargs) 32 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 33 | self.z_mean = Dense(units=latent_dim) 34 | self.z_log_var = Dense(units=latent_dim) 35 | 36 | def call(self, x): 37 | activation = self.hidden_layer(x) 38 | z_mean = self.z_mean(activation) 39 | z_log_var= self.z_log_var(activation) 40 | return z_mean,z_log_var 41 | 42 | class Decoder(tf.keras.Model): # 提取图片特征 43 | def __init__(self ,intermediate_dim,original_dim,**kwargs): 44 | super(Decoder, self).__init__(**kwargs) 45 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 46 | self.output_layer = Dense(units=original_dim, activation='sigmoid') 47 | 48 | def call(self, z): 49 | activation = self.hidden_layer(z) 50 | output_layer = self.output_layer(activation) 51 | return output_layer 52 | 53 | 54 | def samplingfun(z_mean, z_log_var): 55 | epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., 56 | stddev=1.0) 57 | return z_mean + K.exp(z_log_var / 2) * epsilon 58 | 59 | def sampling(args): 60 | z_mean, z_log_var = args 61 | return samplingfun(z_mean, z_log_var) 62 | 63 | 64 | encoder = Encoder(intermediate_dim,latent_dim) 65 | decoder = Decoder(intermediate_dim,original_dim) 66 | 67 | inputs = Input(batch_shape=(batch_size, original_dim)) 68 | z_mean,z_log_var = encoder(inputs) 69 | 70 | # z= samplingfun(z_mean, z_log_var) #ok 71 | # z = Lambda(samplingfun, output_shape=(latent_dim,))(z_mean, z_log_var) #no 72 | z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var]) #ok 73 | y_pred = decoder(z) 74 | 75 | autoencoder = Model(inputs, y_pred, name='autoencoder') 76 | autoencoder.summary() 77 | 78 | 79 | def vae_loss(x, x_decoded_mean): 80 | #my tips:logloss 81 | xent_loss = original_dim * metrics.binary_crossentropy(x, x_decoded_mean) #ok 82 | 83 | kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1) 84 | 85 | return xent_loss + kl_loss 86 | 87 | autoencoder.compile(optimizer='rmsprop', loss=vae_loss) 88 | 89 | 90 | # train the VAE on MNIST digits 91 | # (x_train, y_train), (x_test, y_test) = mnist.load_data(path='mnist.pkl.gz') 92 | (x_train, y_train), (x_test, y_test) = mnist.load_data() 93 | 94 | 95 | x_train = x_train.astype('float32') / 255. 96 | x_test = x_test.astype('float32') / 255. 97 | x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:]))) 98 | x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:]))) 99 | 100 | 101 | 102 | autoencoder.fit(x_train, x_train, 103 | shuffle=True, 104 | epochs=5,#nb_epoch, 105 | verbose=2, 106 | batch_size=batch_size, 107 | validation_data=(x_test, x_test)) 108 | 109 | 110 | for i in autoencoder.layers: 111 | print(i) 112 | 113 | print(autoencoder.layers[1]) #Encoder 114 | print(autoencoder.layers[-1]) #Decoder 115 | 116 | # build a model to project inputs on the latent space 117 | modencoder = Model(inputs, z_mean) 118 | 119 | 120 | print(modencoder.layers[1]) #Encoder 121 | 122 | # display a 2D plot of the digit classes in the latent space 123 | x_test_encoded = modencoder.predict(x_test, batch_size=batch_size) 124 | plt.figure(figsize=(6, 6)) 125 | plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test) 126 | plt.colorbar() 127 | plt.show() 128 | 129 | -------------------------------------------------------------------------------- /code/代码8-11 AttGANmodels.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author: 代码医生工作室 3 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 4 | @来源: 配套代码 5 | @配套代码技术支持:bbs.aianaconda.com 6 | """ 7 | import tensorflow as tf 8 | import tensorflow.keras.layers as KL 9 | #import tensorflow.contrib.slim as slim 10 | 11 | MAX_DIM = 64 * 16 12 | def Genc(x, dim=64, n_layers=5, is_training=True): 13 | with tf.compat.v1.variable_scope('Genc', reuse=tf.compat.v1.AUTO_REUSE): 14 | z = x 15 | zs = [] 16 | for i in range(n_layers): 17 | d = min(dim * 2**i, MAX_DIM) 18 | z=KL.Conv2D(d,4,2,activation=tf.nn.leaky_relu)(z) 19 | #z = slim.conv2d(z,d,4,2,activation_fn=tf.nn.leaky_relu) 20 | #z = slim.batch_norm(z,scale=True,updates_collections=None, is_training=is_training) 21 | z = KL.BatchNormalization(trainable=is_training)(z) 22 | zs.append(z) 23 | return zs 24 | 25 | 26 | def Gdec(zs, _a, dim=64, n_layers=5, shortcut_layers=1, inject_layers=0, is_training=True): 27 | shortcut_layers = min(shortcut_layers, n_layers - 1) 28 | inject_layers = min(inject_layers, n_layers - 1) 29 | 30 | def _concat(z, z_, _a): 31 | feats = [z] 32 | if z_ is not None: 33 | feats.append(z_) 34 | if _a is not None: 35 | _a = tf.reshape(_a, [-1, 1, 1, _a.get_shape()[-1] ]) 36 | _a = tf.tile(_a, [1, z.get_shape()[1],z.get_shape()[2], 1]) 37 | feats.append(_a) 38 | return tf.concat(feats, axis=3) 39 | 40 | with tf.compat.v1.variable_scope('Gdec', reuse=tf.compat.v1.AUTO_REUSE): 41 | z = _concat(zs[-1], None, _a)#z.shape is (32, 2, 2, 1037) 42 | for i in range(n_layers): 43 | if i < n_layers - 1: 44 | d = min(dim * 2**(n_layers - 1 - i), MAX_DIM) 45 | #z = slim.conv2d_transpose(z,d,4,2,activation_fn=tf.nn.relu) 46 | z = KL.Conv2DTranspose(d,4,2,activation=tf.nn.relu)(z)#z.shape is (32, 6, 6, 1037) 47 | #z = slim.batch_norm(z,scale=True,updates_collections=None, is_training=is_training) 48 | z = KL.BatchNormalization(trainable=is_training)(z)#z.shape is (32, 6, 6, 1037) 49 | if shortcut_layers > i: 50 | z = _concat(z, zs[n_layers - 2 - i], None) 51 | if inject_layers > i: 52 | z = _concat(z, None, _a) 53 | else: 54 | #x = slim.conv2d_transpose(z, 3, 4, 2,activation_fn=tf.nn.tanh) 55 | x = KL.Conv2DTranspose(3, 6, 2,activation=tf.nn.tanh)(z)#(32,126,126,3) 56 | return x 57 | 58 | 59 | def D(x, n_att, dim=64, fc_dim=MAX_DIM, n_layers=5): 60 | with tf.compat.v1.variable_scope('D', reuse=tf.compat.v1.AUTO_REUSE): 61 | y = x 62 | for i in range(n_layers): 63 | d = min(dim * 2**i, MAX_DIM) 64 | #y= slim.conv2d(y,d,4,2, normalizer_fn=slim.instance_norm,activation_fn=tf.nn.leaky_relu) 65 | y= KL.Conv2D(d,4,2, activation=tf.nn.leaky_relu)(y) 66 | print(y.shape,y.shape.ndims) 67 | if y.shape.ndims > 2:#大于2维,需要展开。变成2维的再做全连接 68 | #y = KL.Flatten(y) 69 | y=tf.compat.v1.layers.flatten(y) 70 | #logit_gan = slim.fully_connected(y, fc_dim,activation_fn =tf.nn.leaky_relu ) 71 | logit_gan = KL.Dense(fc_dim,activation =tf.nn.leaky_relu )(y) 72 | #logit_gan = slim.fully_connected(logit_gan, 1,activation_fn =None ) 73 | logit_gan = KL.Dense(1,activation =None )(logit_gan) 74 | #logit_att = slim.fully_connected(y, fc_dim,activation_fn =tf.nn.leaky_relu ) 75 | logit_att = KL.Dense(fc_dim,activation =tf.nn.leaky_relu )(y) 76 | #logit_att = slim.fully_connected(logit_att, n_att,activation_fn =None ) 77 | logit_att = KL.Dense(n_att,activation =None )(logit_att) 78 | 79 | return logit_gan, logit_att 80 | 81 | 82 | def gradient_penalty(f, real, fake=None): 83 | def _interpolate(a, b=None): 84 | with tf.compat.v1.name_scope('interpolate'): 85 | if b is None: # interpolation in DRAGAN 86 | beta = tf.random.uniform(shape=tf.shape(input=a), minval=0., maxval=1.) 87 | _, variance = tf.nn.moments(x=a, axes=range(a.shape.ndims)) 88 | b = a + 0.5 * tf.sqrt(variance) * beta 89 | shape = [tf.shape(input=a)[0]] + [1] * (a.shape.ndims - 1) 90 | alpha = tf.random.uniform(shape=shape, minval=0., maxval=1.) 91 | inter = a + alpha * (b - a) 92 | inter.set_shape(a.get_shape().as_list()) 93 | return inter 94 | 95 | with tf.compat.v1.name_scope('gradient_penalty'): 96 | x = _interpolate(real, fake) 97 | pred = f(x) 98 | if isinstance(pred, tuple): 99 | pred = pred[0] 100 | grad = tf.gradients(ys=pred, xs=x)[0] 101 | #norm = tf.norm(tensor=slim.flatten(grad), axis=1) 102 | norm = tf.norm(tensor=tf.compat.v1.layers.flatten(grad), axis=1) 103 | gp = tf.reduce_mean(input_tensor=(norm - 1.)**2) 104 | return gp 105 | -------------------------------------------------------------------------------- /code/代码8-13 testattgan.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author: 代码医生工作室 3 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 4 | @来源: 配套代码 5 | @配套代码技术支持:bbs.aianaconda.com 6 | """ 7 | from functools import partial 8 | import os 9 | import traceback 10 | import numpy as np 11 | import tensorflow as tf 12 | tf.compat.v1.disable_v2_behavior() 13 | 14 | mydataset = __import__("代码8-10 mydataset") 15 | data = mydataset#.data 16 | 17 | AttGANmodels = __import__("代码8-11 AttGANmodels") 18 | models = AttGANmodels#.models 19 | 20 | 21 | 22 | img_size = 128 23 | shortcut_layers = 1 24 | inject_layers =1 25 | enc_dim = 64 26 | dec_dim = 64 27 | dis_dim = 64 28 | dis_fc_dim = 1024 29 | enc_layers = 5 30 | dec_layers = 5 31 | dis_layers = 5 32 | 33 | batch_size = 32 34 | thres_int = 0.5 #训练时,特征的上下限值域 35 | test_int = 1.0#测试时,特征属性的上下限值域(一般要大于训练时的值域,使特征更加明显) 36 | n_sample = 64 37 | # others 38 | experiment_name = "128_shortcut1_inject1_None" 39 | att_default = ['Bald', 'Bangs', 'Black_Hair', 'Blond_Hair', 'Brown_Hair', 'Bushy_Eyebrows', 'Eyeglasses', 'Male', 'Mouth_Slightly_Open', 'Mustache', 'No_Beard', 'Pale_Skin', 'Young'] 40 | n_att = len(att_default) 41 | 42 | 43 | # ============================================================================== 44 | # = graphs = 45 | # ============================================================================== 46 | import scipy.misc 47 | def imwrite(image, path): 48 | """Save an [-1.0, 1.0] image.""" 49 | if image.ndim == 3 and image.shape[2] == 1: # for gray image 50 | image = np.array(image, copy=True) 51 | image.shape = image.shape[0:2] 52 | return scipy.misc.imsave(path, to_range(image, 0, 255, np.uint8)) 53 | 54 | 55 | 56 | tf.compat.v1.reset_default_graph() 57 | 58 | config = tf.compat.v1.ConfigProto(allow_soft_placement=True, log_device_placement=False) 59 | config.gpu_options.allow_growth = True 60 | sess = tf.compat.v1.Session(config=config) 61 | #建立数据集 62 | te_data = data.Celeba(r'D:\\01-TF\\01-TF2\\Chapter10\\code10.3\\data\\', att_default, img_size, 1, mode='test', sess=sess) 63 | 64 | #构建模型 65 | Genc = partial(models.Genc, dim=enc_dim, n_layers=enc_layers) 66 | Gdec = partial(models.Gdec, dim=dec_dim, n_layers=dec_layers, shortcut_layers=shortcut_layers, inject_layers=inject_layers) 67 | 68 | D = partial(models.D, n_att=n_att, dim=dis_dim, fc_dim=dis_fc_dim, n_layers=dis_layers) 69 | 70 | 71 | # inputs 72 | xa_sample = tf.compat.v1.placeholder(tf.float32, shape=[None, img_size, img_size, 3]) 73 | _b_sample = tf.compat.v1.placeholder(tf.float32, shape=[None, n_att]) 74 | 75 | # sample 76 | x_sample = Gdec(Genc(xa_sample, is_training=False), _b_sample, is_training=False) 77 | 78 | 79 | # ============================================================================== 80 | # = test = 81 | # ============================================================================== 82 | # initialization 83 | ckpt_dir = './output/%s/checkpoints' % experiment_name 84 | print(ckpt_dir) 85 | thisckpt_dir = tf.train.latest_checkpoint(ckpt_dir) 86 | print(thisckpt_dir) 87 | restorer = tf.compat.v1.train.Saver() 88 | restorer.restore(sess, thisckpt_dir) 89 | 90 | try: 91 | 92 | thisckpt_dir = tf.train.latest_checkpoint(ckpt_dir) 93 | restorer = tf.compat.v1.train.Saver() 94 | restorer.restore(sess, thisckpt_dir) 95 | except: 96 | raise Exception(' [*] No checkpoint!') 97 | 98 | 99 | ####################################################################### 100 | # sample-slide 101 | n_slide =10 102 | test_int_min = 0.7 103 | test_int_max = 1.2 104 | test_att = 'Eyeglasses' 105 | try: 106 | for idx, batch in enumerate(te_data): 107 | xa_sample_ipt = batch[0] 108 | b_sample_ipt = batch[1] 109 | 110 | x_sample_opt_list = [xa_sample_ipt, np.full((1, img_size, img_size // 10, 3), -1.0)] 111 | for i in range(n_slide): 112 | test_int = (test_int_max - test_int_min) / (n_slide - 1) * i + test_int_min 113 | _b_sample_ipt = (b_sample_ipt * 2 - 1) * thres_int 114 | _b_sample_ipt[..., att_default.index(test_att)] = test_int 115 | x_sample_opt_list.append(sess.run(x_sample, feed_dict={xa_sample: xa_sample_ipt, _b_sample: _b_sample_ipt})) 116 | sample = np.concatenate(x_sample_opt_list, 2) 117 | 118 | save_dir = './output/%s/sample_testing_slide_%s' % (experiment_name, test_att) 119 | 120 | os.makedirs(save_dir, exist_ok=True) 121 | imwrite(sample.squeeze(0), '%s/%d.png' % (save_dir, idx + 182638)) 122 | print('%d.png done!' % (idx + 182638)) 123 | 124 | except: 125 | traceback.print_exc() 126 | finally: 127 | sess.close() 128 | 129 | -------------------------------------------------------------------------------- /code/代码8-14 MINE.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | from tensorflow.keras.layers import * 9 | from tensorflow.keras.models import * 10 | import tensorflow as tf 11 | import tensorflow.keras.backend as K 12 | import numpy as np 13 | import matplotlib.pyplot as plt 14 | 15 | batch_size = 1000 #定义批次大小 16 | #生成模拟数据 17 | def train_generator(): 18 | while(True): 19 | x = np.sign(np.random.normal(0.,1.,[batch_size,1])) 20 | y = x+np.random.normal(0.,0.5,[batch_size,1]) 21 | y_shuffle=np.random.permutation(y) 22 | yield ((x,y,y_shuffle),None) 23 | 24 | #可视化 25 | for inputs in train_generator(): 26 | x_sample=inputs[0][0] 27 | y_sample=inputs[0][1] 28 | plt.scatter(np.arange(len(x_sample)), x_sample, s=10,c='b',marker='o') 29 | plt.scatter(np.arange(len(y_sample)), y_sample, s=10,c='y',marker='o') 30 | plt.show() 31 | break 32 | 33 | 34 | class Net(tf.keras.Model): 35 | def __init__(self): 36 | super(Net, self).__init__() 37 | self.fc1 = Dense(10) 38 | self.fc2 = Dense(10) 39 | self.fc3 = Dense(1) 40 | 41 | def call(self, x, y): 42 | # x, y = inputs[0],inputs[1] 43 | h1 = tf.nn.relu(self.fc1(x)+self.fc2(y)) 44 | h2 = self.fc3(h1) 45 | return h2 46 | 47 | model = Net() 48 | optimizer = tf.keras.optimizers.Adam(lr=0.01)#定义优化器 49 | 50 | inputs_x = Input(batch_shape=(batch_size, 1)) 51 | inputs_y = Input(batch_shape=(batch_size, 1)) 52 | inputs_yshuffle = Input(batch_shape=(batch_size, 1)) 53 | pred_xy = model(inputs_x,inputs_y) 54 | pred_x_y = model(inputs_x,inputs_yshuffle) 55 | 56 | 57 | # loss 58 | loss = -(K.mean(pred_xy) - K.log(K.mean(K.exp(pred_x_y)))) 59 | 60 | 61 | modeMINE = Model([inputs_x,inputs_y,inputs_yshuffle], [pred_xy,pred_x_y,loss], name='modeMINE') 62 | modeMINE.add_loss(loss) 63 | modeMINE.compile(optimizer=optimizer) 64 | modeMINE.summary() 65 | 66 | 67 | 68 | n = 100 69 | H = modeMINE.fit(x=train_generator(), epochs=n,steps_per_epoch=40, 70 | validation_data=train_generator(),validation_steps=4) 71 | 72 | 73 | plot_y = np.array(H.history["loss"]).reshape(-1,) 74 | plt.plot(np.arange(len(plot_y)), -plot_y, 'r') 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /code/代码8-2 变分自编码模型的无标签训练.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | from scipy.stats import norm 11 | 12 | from tensorflow.keras.layers import * 13 | from tensorflow.keras.models import * 14 | import tensorflow as tf 15 | import tensorflow.keras.backend as K 16 | from tensorflow.keras.datasets import mnist 17 | from tensorflow.keras.optimizers import Adam 18 | 19 | from tensorflow.keras import metrics 20 | # tf.compat.v1.disable_v2_behavior() 21 | 22 | batch_size = 100 23 | original_dim = 784 #28*28 24 | latent_dim = 2 25 | intermediate_dim = 256 26 | nb_epoch = 50 27 | 28 | 29 | class Encoder(tf.keras.Model): # 提取图片特征 30 | def __init__(self ,intermediate_dim,latent_dim, **kwargs): 31 | super(Encoder, self).__init__(**kwargs) 32 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 33 | self.z_mean = Dense(units=latent_dim) 34 | self.z_log_var = Dense(units=latent_dim) 35 | 36 | def call(self, x): 37 | activation = self.hidden_layer(x) 38 | z_mean = self.z_mean(activation) 39 | z_log_var= self.z_log_var(activation) 40 | return z_mean,z_log_var 41 | 42 | 43 | def sampling(args): 44 | z_mean, z_log_var = args 45 | epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., 46 | stddev=1.0) 47 | return z_mean + K.exp(z_log_var / 2) * epsilon 48 | 49 | class Decoder(tf.keras.Model): # 提取图片特征 50 | def __init__(self ,intermediate_dim,original_dim,**kwargs): 51 | super(Decoder, self).__init__(**kwargs) 52 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 53 | self.output_layer = Dense(units=original_dim, activation='sigmoid') 54 | 55 | def call(self, z): 56 | activation = self.hidden_layer(z) 57 | output_layer = self.output_layer(activation) 58 | return output_layer 59 | 60 | 61 | 62 | encoder = Encoder(intermediate_dim,latent_dim) 63 | decoder = Decoder(intermediate_dim,original_dim) 64 | 65 | inputs = Input(batch_shape=(batch_size, original_dim)) 66 | z_mean,z_log_var = encoder(inputs) 67 | z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var]) 68 | y_pred = decoder(z) 69 | autoencoder = Model(inputs, y_pred, name='autoencoder') 70 | 71 | # 重构loss 72 | xent_loss = original_dim * metrics.binary_crossentropy(inputs, y_pred) 73 | # KL loss 74 | kl_loss = - 0.5 * K.sum(1 + z_log_var - 75 | K.square(z_mean) - K.exp(z_log_var), axis=-1) 76 | vae_loss = K.mean(xent_loss + kl_loss) 77 | 78 | #########################################y 79 | autoencoder.add_loss(vae_loss) 80 | autoencoder.compile(optimizer='rmsprop') 81 | ############################no 82 | # autoencoder.compile(optimizer='rmsprop', loss=vae_loss) 83 | ############################################# 84 | 85 | 86 | # train the VAE on MNIST digits 87 | (x_train, y_train), (x_test, y_test) = mnist.load_data(path='mnist.pkl.gz') 88 | 89 | x_train = x_train.astype('float32') / 255. 90 | x_test = x_test.astype('float32') / 255. 91 | x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:]))) 92 | x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:]))) 93 | 94 | ################################################ 95 | # autoencoder.fit(x_train, x_train, 96 | # shuffle=True, 97 | # epochs=5,#nb_epoch, 98 | # verbose=2, 99 | # batch_size=batch_size, 100 | # validation_data=(x_test, x_test)) 101 | 102 | autoencoder.fit(x_train, validation_split=0.05, epochs=5, batch_size=batch_size) 103 | ################################################# 104 | 105 | 106 | for i in autoencoder.layers: 107 | print(i) 108 | 109 | print(autoencoder.layers[1]) #Encoder 110 | print(autoencoder.layers[-1]) #Decoder 111 | 112 | # build a model to project inputs on the latent space 113 | modencoder = Model(inputs, z_mean) 114 | 115 | 116 | print(modencoder.layers[1]) #Encoder 117 | 118 | # display a 2D plot of the digit classes in the latent space 119 | x_test_encoded = modencoder.predict(x_test, batch_size=batch_size) 120 | plt.figure(figsize=(6, 6)) 121 | plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test) 122 | plt.colorbar() 123 | plt.show() 124 | -------------------------------------------------------------------------------- /code/代码8-3 将张量损失封装成损失函数.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | from scipy.stats import norm 11 | 12 | from tensorflow.keras.layers import * 13 | from tensorflow.keras.models import * 14 | import tensorflow as tf 15 | import tensorflow.keras.backend as K 16 | from tensorflow.keras.datasets import mnist 17 | from tensorflow.keras.optimizers import Adam 18 | 19 | from tensorflow.keras import metrics 20 | 21 | # tf.compat.v1.disable_v2_behavior() 22 | 23 | batch_size = 100 24 | original_dim = 784 #28*28 25 | latent_dim = 2 26 | intermediate_dim = 256 27 | nb_epoch = 50 28 | 29 | 30 | class Encoder(tf.keras.Model): # 提取图片特征 31 | def __init__(self ,intermediate_dim,latent_dim, **kwargs): 32 | super(Encoder, self).__init__(**kwargs) 33 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 34 | self.z_mean = Dense(units=latent_dim) 35 | self.z_log_var = Dense(units=latent_dim) 36 | 37 | def call(self, x): 38 | activation = self.hidden_layer(x) 39 | z_mean = self.z_mean(activation) 40 | z_log_var= self.z_log_var(activation) 41 | return z_mean,z_log_var 42 | 43 | 44 | def sampling(args): 45 | z_mean, z_log_var = args 46 | epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., 47 | stddev=1.0) 48 | return z_mean + K.exp(z_log_var / 2) * epsilon 49 | 50 | class Decoder(tf.keras.Model): # 提取图片特征 51 | def __init__(self ,intermediate_dim,original_dim,**kwargs): 52 | super(Decoder, self).__init__(**kwargs) 53 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 54 | self.output_layer = Dense(units=original_dim, activation='sigmoid') 55 | 56 | def call(self, z): 57 | activation = self.hidden_layer(z) 58 | output_layer = self.output_layer(activation) 59 | return output_layer 60 | 61 | 62 | 63 | encoder = Encoder(intermediate_dim,latent_dim) 64 | decoder = Decoder(intermediate_dim,original_dim) 65 | 66 | inputs = Input(batch_shape=(batch_size, original_dim)) 67 | z_mean,z_log_var = encoder(inputs) 68 | z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var]) 69 | y_pred = decoder(z) 70 | autoencoder = Model(inputs, y_pred, name='autoencoder') 71 | 72 | # 重构loss 73 | xent_loss = original_dim * metrics.binary_crossentropy(inputs, y_pred) 74 | # KL loss 75 | kl_loss = - 0.5 * K.sum(1 + z_log_var - 76 | K.square(z_mean) - K.exp(z_log_var), axis=-1) 77 | # vae_loss = K.mean(xent_loss + kl_loss) 78 | 79 | vae_loss = xent_loss + kl_loss 80 | 81 | 82 | #########################################y 83 | #autoencoder.add_loss(vae_loss) 84 | #autoencoder.compile(optimizer='rmsprop') 85 | ############################n 86 | #autoencoder.compile(optimizer='rmsprop', loss=vae_loss) 87 | ############################################# 88 | # def vae_lossfun(loss): 89 | def vae_lossfun(x, loss): 90 | return loss 91 | lossautoencoder = Model(inputs, vae_loss, name='lossautoencoder') 92 | lossautoencoder.compile(optimizer='rmsprop', loss=vae_lossfun) 93 | ###################################### 94 | 95 | # train the VAE on MNIST digits 96 | (x_train, y_train), (x_test, y_test) = mnist.load_data(path='mnist.pkl.gz') 97 | 98 | x_train = x_train.astype('float32') / 255. 99 | x_test = x_test.astype('float32') / 255. 100 | x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:]))) 101 | x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:]))) 102 | 103 | ################################################n 104 | #autoencoder.fit(x_train, x_train, 105 | # shuffle=True, 106 | # epochs=5,#nb_epoch, 107 | # verbose=2, 108 | # batch_size=batch_size, 109 | # validation_data=(x_test, x_test)) 110 | ###################################################y 111 | # autoencoder.fit(x_train, validation_split=0.05, epochs=5, batch_size=batch_size) 112 | ################################################# 113 | lossautoencoder.fit(x_train, x_train, 114 | shuffle=True, 115 | epochs=5,#nb_epoch, 116 | verbose=2, 117 | batch_size=batch_size, 118 | validation_data=(x_test, x_test)) 119 | ################################################### 120 | 121 | 122 | 123 | for i in autoencoder.layers: 124 | print(i) 125 | 126 | print(autoencoder.layers[1]) #Encoder 127 | print(autoencoder.layers[-1]) #Decoder 128 | 129 | # build a model to project inputs on the latent space 130 | modencoder = Model(inputs, z_mean) 131 | 132 | 133 | print(modencoder.layers[1]) #Encoder 134 | 135 | # display a 2D plot of the digit classes in the latent space 136 | x_test_encoded = modencoder.predict(x_test, batch_size=batch_size) 137 | plt.figure(figsize=(6, 6)) 138 | plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test) 139 | plt.colorbar() 140 | plt.show() 141 | -------------------------------------------------------------------------------- /code/代码8-4 在动态图中实现变分自编码.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | from scipy.stats import norm 11 | 12 | from tensorflow.keras.layers import * 13 | from tensorflow.keras.models import * 14 | import tensorflow as tf 15 | import tensorflow.keras.backend as K 16 | from tensorflow.keras.datasets import mnist 17 | from tensorflow.keras.optimizers import Adam 18 | 19 | from tensorflow.keras import metrics 20 | 21 | 22 | batch_size = 100 23 | original_dim = 784 #28*28 24 | latent_dim = 2 25 | intermediate_dim = 256 26 | nb_epoch = 50 27 | 28 | 29 | class Encoder(tf.keras.Model): # 提取图片特征 30 | def __init__(self ,intermediate_dim,latent_dim, **kwargs): 31 | super(Encoder, self).__init__(**kwargs) 32 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 33 | self.z_mean = Dense(units=latent_dim) 34 | self.z_log_var = Dense(units=latent_dim) 35 | 36 | def call(self, x): 37 | activation = self.hidden_layer(x) 38 | z_mean = self.z_mean(activation) 39 | z_log_var= self.z_log_var(activation) 40 | return z_mean,z_log_var 41 | 42 | 43 | def samplingfun(z_mean, z_log_var): 44 | epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., 45 | stddev=1.0) 46 | return z_mean + K.exp(z_log_var / 2) * epsilon 47 | 48 | def sampling(args): 49 | z_mean, z_log_var = args 50 | return samplingfun(z_mean, z_log_var) 51 | 52 | class Decoder(tf.keras.Model): # 提取图片特征 53 | def __init__(self ,intermediate_dim,original_dim,**kwargs): 54 | super(Decoder, self).__init__(**kwargs) 55 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 56 | self.output_layer = Dense(units=original_dim, activation='sigmoid') 57 | 58 | def call(self, z): 59 | activation = self.hidden_layer(z) 60 | output_layer = self.output_layer(activation) 61 | return output_layer 62 | 63 | 64 | 65 | encoder = Encoder(intermediate_dim,latent_dim) 66 | decoder = Decoder(intermediate_dim,original_dim) 67 | 68 | #inputs = Input(batch_shape=(batch_size, original_dim)) 69 | #z_mean,z_log_var = encoder(inputs) 70 | #z= samplingfun(z_mean, z_log_var) #ok 71 | ##z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var]) #ok 72 | #y_pred = decoder(z) 73 | #autoencoder = Model(inputs, y_pred, name='autoencoder') 74 | 75 | 76 | 77 | 78 | 79 | # train the VAE on MNIST digits 80 | (x_train, y_train), (x_test, y_test) = mnist.load_data(path='mnist.pkl.gz') 81 | 82 | x_train = x_train.astype('float32') / 255. 83 | x_test = x_test.astype('float32') / 255. 84 | x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:]))) 85 | x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:]))) 86 | 87 | ################################################n 88 | optimizer = Adam(lr=0.001)#定义优化器 89 | 90 | import os 91 | 92 | training_dataset = tf.data.Dataset.from_tensor_slices(x_train).batch(batch_size) 93 | nb_epoch = 5 94 | for epoch in range(nb_epoch): # 按照指定迭代次数进行训练 95 | for dataone in training_dataset: # 遍历数据集 96 | img = np.reshape(dataone, (batch_size, -1)) 97 | with tf.GradientTape() as tape: 98 | 99 | z_mean,z_log_var = encoder(img) 100 | z= samplingfun(z_mean, z_log_var) #ok 101 | x_decoded_mean = decoder(z) 102 | 103 | xent_loss = K.sum(K.square(x_decoded_mean - img), axis=-1) 104 | kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1) 105 | 106 | thisloss = K.mean(xent_loss)*0.5+K.mean(kl_loss) 107 | 108 | 109 | gradients = tape.gradient(thisloss, encoder.trainable_variables+decoder.trainable_variables) 110 | gradient_variables = zip(gradients, encoder.trainable_variables+decoder.trainable_variables) 111 | optimizer.apply_gradients(gradient_variables) 112 | print(epoch," loss:",thisloss.numpy()) 113 | 114 | 115 | inputs = Input(batch_shape=(batch_size, original_dim)) 116 | z_mean,z_log_var = encoder(inputs) 117 | z= samplingfun(z_mean, z_log_var) #ok #只能执行一次 118 | z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var]) #ok 可以执行多次 119 | y_pred = decoder(z) 120 | autoencoder = Model(inputs, y_pred, name='autoencoder') 121 | 122 | # build a model to project inputs on the latent space 123 | modencoder = Model(inputs, z_mean) 124 | 125 | 126 | print(modencoder.layers[1]) #Encoder 127 | 128 | # display a 2D plot of the digit classes in the latent space 129 | x_test_encoded = modencoder.predict(x_test, batch_size=batch_size) 130 | plt.figure(figsize=(6, 6)) 131 | plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test) 132 | plt.colorbar() 133 | plt.show() 134 | 135 | -------------------------------------------------------------------------------- /code/代码8-5 以类的方式封装模型损失函数.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | 9 | 10 | import numpy as np 11 | import matplotlib.pyplot as plt 12 | from scipy.stats import norm 13 | 14 | from tensorflow.keras.layers import * 15 | from tensorflow.keras.models import * 16 | import tensorflow as tf 17 | import tensorflow.keras.backend as K 18 | from tensorflow.keras.datasets import mnist 19 | from tensorflow.keras.optimizers import Adam 20 | 21 | from tensorflow.keras import metrics 22 | 23 | 24 | #import sys 25 | #saveout = sys.stdout 26 | #file = open('variational_autoencoder.txt','w') 27 | #sys.stdout = file 28 | # 29 | batch_size = 100 30 | original_dim = 784 #28*28 31 | latent_dim = 2 32 | intermediate_dim = 256 33 | nb_epoch = 50 34 | 35 | 36 | class Encoder(tf.keras.Model): # 提取图片特征 37 | def __init__(self ,intermediate_dim,latent_dim, **kwargs): 38 | super(Encoder, self).__init__(**kwargs) 39 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 40 | self.z_mean = Dense(units=latent_dim) 41 | self.z_log_var = Dense(units=latent_dim) 42 | 43 | def call(self, x): 44 | activation = self.hidden_layer(x) 45 | z_mean = self.z_mean(activation) 46 | z_log_var= self.z_log_var(activation) 47 | return z_mean,z_log_var 48 | 49 | 50 | #encoder.summary() 51 | 52 | 53 | def sampling(args): 54 | z_mean, z_log_var = args 55 | epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., 56 | stddev=1.0) 57 | return z_mean + K.exp(z_log_var / 2) * epsilon 58 | 59 | class Decoder(tf.keras.Model): # 提取图片特征 60 | def __init__(self ,intermediate_dim,original_dim,**kwargs): 61 | super(Decoder, self).__init__(**kwargs) 62 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 63 | self.output_layer = Dense(units=original_dim, activation='sigmoid') 64 | 65 | def call(self, z): 66 | activation = self.hidden_layer(z) 67 | output_layer = self.output_layer(activation) 68 | return output_layer 69 | 70 | 71 | 72 | class VAE(tf.keras.Model): # 提取图片特征 73 | def __init__(self ,intermediate_dim,original_dim,latent_dim,**kwargs): 74 | super(VAE, self).__init__(**kwargs) 75 | self.encoder = Encoder(intermediate_dim,latent_dim) 76 | self.decoder = Decoder(intermediate_dim,original_dim) 77 | 78 | def call(self, x): 79 | z_mean,z_log_var = self.encoder(x) 80 | z = sampling( (z_mean,z_log_var) ) 81 | y_pred = self.decoder(z) 82 | xent_loss = original_dim * metrics.binary_crossentropy(x, y_pred) #ok 83 | kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1) 84 | loss = xent_loss + kl_loss 85 | return loss 86 | 87 | 88 | #encoder = Encoder(intermediate_dim,latent_dim) 89 | #decoder = Decoder(intermediate_dim,original_dim) 90 | 91 | vae = VAE(intermediate_dim,original_dim,latent_dim) 92 | 93 | 94 | #inputs = Input(batch_shape=(batch_size, original_dim)) 95 | #vae_lossmode = vae(inputs) 96 | #lossautoencoder = Model(inputs, vae_lossmode, name='lossautoencoder') 97 | #lossautoencoder.add_loss(vae_lossmode) 98 | #lossautoencoder.compile(optimizer='rmsprop') 99 | 100 | 101 | def vae_loss(x, loss): 102 | return loss 103 | vae.compile(optimizer='rmsprop', loss=vae_loss) 104 | 105 | 106 | # train the VAE on MNIST digits 107 | (x_train, y_train), (x_test, y_test) = mnist.load_data(path='mnist.pkl.gz') 108 | x_train = x_train.astype('float32') / 255. 109 | x_test = x_test.astype('float32') / 255. 110 | x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:]))) 111 | x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:]))) 112 | 113 | #lossautoencoder.fit(x_train, validation_split=0.05, epochs=5, batch_size=batch_size) 114 | #vae.fit(x_train, x_train, 115 | # shuffle=True, 116 | # epochs=5,#nb_epoch, 117 | # verbose=2, 118 | # batch_size=batch_size, 119 | # validation_data=(x_test, x_test)) 120 | optimizer = Adam(lr=0.001) 121 | training_dataset = tf.data.Dataset.from_tensor_slices(x_train).batch(batch_size) 122 | nb_epoch = 5 123 | for epoch in range(nb_epoch): # 按照指定迭代次数进行训练 124 | for dataone in training_dataset: # 遍历数据集 125 | img = np.reshape(dataone, (batch_size, -1)) 126 | with tf.GradientTape() as tape: 127 | thisloss = K.mean( vae(img) ) 128 | 129 | gradients = tape.gradient(thisloss, vae.trainable_variables) 130 | gradient_variables = zip(gradients, vae.trainable_variables) 131 | optimizer.apply_gradients(gradient_variables) 132 | print(epoch," loss:",thisloss.numpy()) 133 | 134 | 135 | 136 | 137 | 138 | 139 | inputs = Input(batch_shape=(batch_size, original_dim)) 140 | z_mean,z_log_var = vae.encoder(inputs) 141 | 142 | # build a model to project inputs on the latent space 143 | modencoder = Model(inputs, z_mean) 144 | 145 | 146 | print(modencoder.layers[1]) #Encoder 147 | 148 | # display a 2D plot of the digit classes in the latent space 149 | #x_test_encoded = modencoder.predict(x_test, batch_size=batch_size) 150 | x_test_encoded,_ = vae.encoder(x_test) 151 | 152 | 153 | 154 | plt.figure(figsize=(6, 6)) 155 | plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test) 156 | plt.colorbar() 157 | plt.show() 158 | -------------------------------------------------------------------------------- /code/代码8-6 更合理的类封装方式.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | from scipy.stats import norm 11 | 12 | from tensorflow.keras.layers import * 13 | from tensorflow.keras.models import * 14 | import tensorflow as tf 15 | import tensorflow.keras.backend as K 16 | from tensorflow.keras.datasets import mnist 17 | from tensorflow.keras.optimizers import Adam 18 | 19 | from tensorflow.keras import metrics 20 | 21 | 22 | batch_size = 100 23 | original_dim = 784 #28*28 24 | latent_dim = 2 25 | intermediate_dim = 256 26 | nb_epoch = 50 27 | 28 | 29 | class Featuremodel(tf.keras.Model): # 提取图片特征 30 | def __init__(self ,intermediate_dim,latent_dim, **kwargs): 31 | super(Featuremodel, self).__init__(**kwargs) 32 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 33 | 34 | def call(self, x): 35 | activation = self.hidden_layer(x) 36 | return x,activation 37 | 38 | class Encoder(tf.keras.Model): # 提取图片特征 39 | def __init__(self ,intermediate_dim,latent_dim, **kwargs): 40 | super(Encoder, self).__init__(**kwargs) 41 | self.z_mean = Dense(units=latent_dim) 42 | self.z_log_var = Dense(units=latent_dim) 43 | 44 | def call(self, activation): 45 | z_mean = self.z_mean(activation) 46 | z_log_var= self.z_log_var(activation) 47 | return z_mean,z_log_var 48 | 49 | 50 | 51 | def sampling(args): 52 | z_mean, z_log_var = args 53 | epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., 54 | stddev=1.0) 55 | return z_mean + K.exp(z_log_var / 2) * epsilon 56 | 57 | class Decoder(tf.keras.Model): # 提取图片特征 58 | def __init__(self ,intermediate_dim,original_dim,**kwargs): 59 | super(Decoder, self).__init__(**kwargs) 60 | self.hidden_layer = Dense(units=intermediate_dim, activation=tf.nn.relu) 61 | self.output_layer = Dense(units=original_dim, activation='sigmoid') 62 | 63 | def call(self, z): 64 | activation = self.hidden_layer(z) 65 | output_layer = self.output_layer(activation) 66 | return output_layer 67 | 68 | 69 | 70 | class Autoencoder(tf.keras.Model): 71 | def __init__(self, intermediate_dim, original_dim,latent_dim): 72 | super(Autoencoder, self).__init__() 73 | self.featuremodel = Featuremodel(intermediate_dim,latent_dim) 74 | self.encoder = Encoder(intermediate_dim,latent_dim) 75 | self.decoder = Decoder(intermediate_dim,original_dim) 76 | 77 | def call(self, input_features): 78 | x,feature = self.featuremodel(input_features) 79 | z_mean,z_log_var = self.encoder(feature) 80 | epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., 81 | stddev=1.0) 82 | code = z_mean + K.exp(z_log_var / 2) * epsilon 83 | reconstructed = self.decoder(code) 84 | return reconstructed,z_mean,z_log_var 85 | 86 | autoencoder = Autoencoder(intermediate_dim, original_dim,latent_dim) 87 | 88 | 89 | # train the VAE on MNIST digits 90 | (x_train, y_train), (x_test, y_test) = mnist.load_data(path='mnist.pkl.gz') 91 | 92 | x_train = x_train.astype('float32') / 255. 93 | x_test = x_test.astype('float32') / 255. 94 | x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:]))) 95 | x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:]))) 96 | 97 | 98 | 99 | #optimizer = tf.train.AdamOptimizer()#定义优化器 100 | optimizer = Adam(lr=0.001) 101 | 102 | import os 103 | 104 | 105 | K.set_learning_phase(True) 106 | #autoencoder.trainable=True 107 | training_dataset = tf.data.Dataset.from_tensor_slices(x_train).batch(batch_size) 108 | nb_epoch = 5 109 | for epoch in range(nb_epoch): # 按照指定迭代次数进行训练 110 | for dataone in training_dataset: # 遍历数据集 111 | img = np.reshape(dataone, (batch_size, -1)) 112 | with tf.GradientTape() as tape: 113 | x_decoded_mean,z_mean,z_log_var = autoencoder(img) 114 | xent_loss = K.sum(K.square(x_decoded_mean - img), axis=-1) 115 | kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1) 116 | 117 | thisloss = K.mean(xent_loss)*0.5+K.mean(kl_loss) 118 | # thisloss = K.mean(xent_loss)+K.mean(kl_loss) 119 | # print("thisloss:",thisloss.numpy()) 120 | gradients = tape.gradient(thisloss, autoencoder.trainable_variables) 121 | gradient_variables = zip(gradients, autoencoder.trainable_variables) 122 | optimizer.apply_gradients(gradient_variables) 123 | print(epoch," loss:",thisloss.numpy()) 124 | 125 | 126 | for i in autoencoder.layers: 127 | print(i) 128 | 129 | print(autoencoder.layers[1]) #Encoder 130 | print(autoencoder.layers[-1]) #Decoder 131 | 132 | inputs = Input(batch_shape=(None, original_dim)) 133 | #z_mean,z_log_var = autoencoder.encoder(inputs) 134 | #modencoder = Model(inputs, z_mean) 135 | 136 | 137 | 138 | reconstructed,feature = autoencoder.featuremodel(inputs) 139 | z_mean,z_log_var = autoencoder.encoder(feature) 140 | modencoder = Model(inputs, z_mean) #在1.13.1版本会有问题,需要使用 K.function来替换model 141 | 142 | 143 | 144 | 145 | print(modencoder.layers[1]) #Encoder 146 | 147 | # display a 2D plot of the digit classes in the latent space 148 | x_test_encoded = modencoder.predict(x_test, batch_size=batch_size) 149 | plt.figure(figsize=(6, 6)) 150 | plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test) 151 | plt.colorbar() 152 | plt.show() 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /code/代码8-7 deblurmodel.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author: 代码医生工作室 3 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 4 | @来源: 配套代码 5 | @配套代码技术支持:bbs.aianaconda.com 6 | """ 7 | import tensorflow as tf 8 | from tensorflow.keras import layers as KL 9 | from tensorflow.keras import models as KM 10 | from switchnorm import SwitchNormalization 11 | tf.compat.v1.disable_v2_behavior() 12 | ngf = 64 #定义生成器原始卷积核个数 13 | ndf = 64#定义判别器原始卷积核个数 14 | input_nc = 3#定义输入通道 15 | output_nc = 3#定义输出通道 16 | 17 | n_blocks_gen = 9#定义残差层数量 18 | 19 | 20 | #定义残差块函数 21 | def res_block(input, filters, kernel_size=(3, 3), strides=(1, 1), use_dropout=False): 22 | 23 | x = KL.Conv2D(filters=filters, #使用步长为1的卷积,保持大小不变 24 | kernel_size=kernel_size, 25 | strides=strides, padding='same')(input) 26 | 27 | x = SwitchNormalization()(x) 28 | x = KL.Activation('relu')(x) 29 | 30 | if use_dropout: #使用dropout 31 | x = KL.Dropout(0.5)(x) 32 | 33 | x = KL.Conv2D(filters=filters, #再来一次步长为1的卷积 34 | kernel_size=kernel_size, 35 | strides=strides,padding='same')(x) 36 | 37 | 38 | x = SwitchNormalization()(x) 39 | 40 | #将卷积后的结果与原始输入相加 41 | merged = KL.Add()([input, x])#残差层 42 | return merged 43 | 44 | 45 | 46 | 47 | def generator_model(image_shape,istrain = True):#构建生成器模型 48 | 49 | #构建输入层(与动态图不兼容) 50 | inputs = KL.Input(shape=(image_shape[0],image_shape[1], input_nc)) 51 | #步长为1的卷积操作,尺寸不变 52 | x = KL.Conv2D(filters=ngf, kernel_size=(7, 7), padding='same')(inputs) 53 | 54 | x = SwitchNormalization()(x) 55 | x = KL.Activation('relu')(x) 56 | 57 | n_downsampling = 2 58 | for i in range(n_downsampling):#两次下采样 59 | mult = 2**i 60 | x = KL.Conv2D(filters=ngf*mult*2, kernel_size=(3, 3), strides=2, padding='same')(x) 61 | x = SwitchNormalization()(x) 62 | x = KL.Activation('relu')(x) 63 | 64 | mult = 2**n_downsampling 65 | for i in range(n_blocks_gen):#定义多个残差层 66 | x = res_block(x, ngf*mult, use_dropout=istrain) 67 | 68 | for i in range(n_downsampling):#两次上采样 69 | mult = 2**(n_downsampling - i) 70 | x = KL.UpSampling2D()(x) 71 | x = KL.Conv2D(filters=int(ngf * mult / 2), kernel_size=(3, 3), padding='same')(x) 72 | x = SwitchNormalization()(x) 73 | x = KL.Activation('relu')(x) 74 | 75 | #步长为1的卷积操作 76 | x = KL.Conv2D(filters=output_nc, kernel_size=(7, 7), padding='same')(x) 77 | x = KL.Activation('tanh')(x) 78 | 79 | outputs = KL.Add()([x, inputs])#与最外层的输入完成一次大残差 80 | #防止特征值域过大,进行除2操作(取平均数残差) 81 | outputs = KL.Lambda(lambda z: z/2)(outputs) 82 | #构建模型 83 | model = KM.Model(inputs=inputs, outputs=outputs, name='Generator') 84 | return model 85 | 86 | 87 | def discriminator_model(image_shape):#构建判别器模型 88 | 89 | n_layers, use_sigmoid = 3, False 90 | inputs = KL.Input(shape=(image_shape[0],image_shape[1],output_nc)) 91 | #下采样卷积 92 | x = KL.Conv2D(filters=ndf, kernel_size=(4, 4), strides=2, padding='same')(inputs) 93 | x = KL.LeakyReLU(0.2)(x) 94 | 95 | nf_mult, nf_mult_prev = 1, 1 96 | for n in range(n_layers):#继续3次下采样卷积 97 | nf_mult_prev, nf_mult = nf_mult, min(2**n, 8) 98 | x = KL.Conv2D(filters=ndf*nf_mult, kernel_size=(4, 4), strides=2, padding='same')(x) 99 | x = KL.BatchNormalization()(x) 100 | x = KL.LeakyReLU(0.2)(x) 101 | 102 | #步长为1的卷积操作,尺寸不变 103 | nf_mult_prev, nf_mult = nf_mult, min(2**n_layers, 8) 104 | x = KL.Conv2D(filters=ndf*nf_mult, kernel_size=(4, 4), strides=1, padding='same')(x) 105 | x = KL.BatchNormalization()(x) 106 | x = KL.LeakyReLU(0.2)(x) 107 | 108 | #步长为1的卷积操作,尺寸不变。将通道压缩为1 109 | x = KL.Conv2D(filters=1, kernel_size=(4, 4), strides=1, padding='same')(x) 110 | if use_sigmoid: 111 | x = KL.Activation('sigmoid')(x) 112 | 113 | x = KL.Flatten()(x) #两层全连接,输出判别结果 114 | x = KL.Dense(1024, activation='tanh')(x) 115 | x = KL.Dense(1, activation='sigmoid')(x) 116 | 117 | model = KM.Model(inputs=inputs, outputs=x, name='Discriminator') 118 | return model 119 | 120 | #将判别器与生成器结合起来,构成完整模型 121 | def g_containing_d_multiple_outputs(generator, discriminator,image_shape): 122 | inputs = KL.Input(shape=(image_shape[0],image_shape[1],input_nc) ) 123 | generated_image = generator(inputs) 124 | outputs = discriminator(generated_image) 125 | model = KM.Model(inputs=inputs, outputs=[generated_image, outputs]) 126 | return model 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /code/代码8-8 训练deblur.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author: 代码医生工作室 3 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 4 | @来源: 配套代码 5 | @配套代码技术支持:bbs.aianaconda.com 6 | """ 7 | import os 8 | import datetime 9 | import numpy as np 10 | import tqdm 11 | import tensorflow as tf 12 | import glob 13 | from tensorflow.python.keras.applications.vgg16 import VGG16 14 | from functools import partial 15 | from tensorflow.keras import models as KM 16 | from tensorflow.keras import backend as K #载入keras的后端实现 17 | 18 | tf.compat.v1.disable_v2_behavior() 19 | deblurmodel = __import__("代码8-7 deblurmodel") 20 | generator_model = deblurmodel.generator_model 21 | discriminator_model = deblurmodel.discriminator_model 22 | g_containing_d_multiple_outputs = deblurmodel.g_containing_d_multiple_outputs 23 | 24 | RESHAPE = (256,256) #定义处理图片的大小 25 | #RESHAPE = (360,640) # 26 | epoch_num = 500 #定义迭代训练次数 27 | 28 | batch_size =2 #定义批次大小 29 | critic_updates = 5 #定义每训练一次生成器,所需要训练判别器的次数 30 | #保存模型 31 | BASE_DIR = 'weights/' 32 | def save_all_weights(d, g, epoch_number, current_loss): 33 | now = datetime.datetime.now() 34 | save_dir = os.path.join(BASE_DIR, '{}{}'.format(now.month, now.day)) 35 | os.makedirs(save_dir, exist_ok=True)#创建目录 36 | g.save_weights(os.path.join(save_dir, 'generator_{}_{}.h5'.format(epoch_number, current_loss)), True) 37 | d.save_weights(os.path.join(save_dir, 'discriminator_{}.h5'.format(epoch_number)), True) 38 | 39 | 40 | path = r'./image/train' 41 | A_paths, B_paths = os.path.join(path, 'A', "*.png"), os.path.join(path, 'B', "*.png") 42 | #获取该路径下的png文件 43 | A_fnames, B_fnames = glob.glob(A_paths),glob.glob(B_paths) 44 | #生成Dataset对象 45 | dataset = tf.data.Dataset.from_tensor_slices((A_fnames, B_fnames)) 46 | 47 | print(A_fnames[0]) 48 | 49 | def _processimg(imgname):#定义函数调整图片大小 50 | image_string = tf.io.read_file(imgname) #读取整个文件 51 | image_decoded = tf.image.decode_image(image_string) 52 | image_decoded.set_shape([None, None, None])#形状变化,不然下面会转化失败 53 | #变化尺寸 54 | img =tf.image.resize( image_decoded,RESHAPE)#[RESHAPE[0],RESHAPE[1],3]) 55 | image_decoded = (img - 127.5) / 127.5 56 | return image_decoded 57 | 58 | def _parseone(A_fname, B_fname): #解析一个图片文件 59 | #读取并预处理图片 60 | image_A,image_B = _processimg(A_fname),_processimg(B_fname) 61 | return image_A,image_B 62 | 63 | dataset = dataset.shuffle(buffer_size=len(B_fnames)) 64 | dataset = dataset.map(_parseone) #转化为有图片内容的数据集 65 | #dataset = dataset.repeat(epoch_num) #将数据集重复num_epochs次 66 | dataset = dataset.batch(batch_size) #将数据集按照batch_size划分 67 | dataset = dataset.prefetch(1) 68 | 69 | 70 | #获得模型 71 | g = generator_model(RESHAPE) #生成器模型 72 | d = discriminator_model(RESHAPE)#判别器模型 73 | d_on_g = g_containing_d_multiple_outputs(g, d,RESHAPE)#联合模型 74 | 75 | #定义优化器 76 | d_opt = tf.keras.optimizers.Adam(lr=1E-4, beta_1=0.9, beta_2=0.999, epsilon=1e-08) 77 | d_on_g_opt = tf.keras.optimizers.Adam(lr=1E-4, beta_1=0.9, beta_2=0.999, epsilon=1e-08) 78 | 79 | 80 | 81 | #WGAN的损失 82 | def wasserstein_loss(y_true, y_pred): 83 | return tf.reduce_mean(input_tensor=y_true*y_pred) 84 | 85 | d.trainable = True 86 | d.compile(optimizer=d_opt, loss=wasserstein_loss)#编译模型 87 | d.trainable = False 88 | 89 | #计算特征空间损失 90 | def perceptual_loss(y_true, y_pred,image_shape): 91 | vgg = VGG16(include_top=False, weights="vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5", 92 | input_shape=(image_shape[0],image_shape[1],3) ) 93 | 94 | loss_model = KM.Model(inputs=vgg.input, outputs=vgg.get_layer('block3_conv3').output) 95 | loss_model.trainable = False 96 | return tf.reduce_mean(input_tensor=tf.square(loss_model(y_true) - loss_model(y_pred))) 97 | 98 | myperceptual_loss = partial(perceptual_loss, image_shape=RESHAPE) 99 | myperceptual_loss.__name__ = 'myperceptual_loss' 100 | 101 | #构建损失 102 | loss = [myperceptual_loss, wasserstein_loss] 103 | loss_weights = [100, 1]#将损失调为统一数量级 104 | d_on_g.compile(optimizer=d_on_g_opt, loss=loss, loss_weights=loss_weights) 105 | d.trainable = True 106 | 107 | output_true_batch, output_false_batch = np.ones((batch_size, 1)), -np.ones((batch_size, 1)) 108 | 109 | #生成数据集迭代器 110 | iterator = tf.compat.v1.data.make_initializable_iterator(dataset) 111 | datatensor = iterator.get_next() 112 | 113 | #定义配置文件 114 | config = tf.compat.v1.ConfigProto() 115 | config.gpu_options.allow_growth = True 116 | config.gpu_options.per_process_gpu_memory_fraction = 0.9 117 | sess = tf.compat.v1.Session(config=config)#建立session 118 | 119 | def pre_train_epoch(sess, iterator,datatensor):#迭代整个数据集进行训练 120 | d_losses = [] 121 | d_on_g_losses = [] 122 | sess.run( iterator.initializer ) 123 | 124 | while True: 125 | try:#获取一批次的数据 126 | (image_blur_batch,image_full_batch) = sess.run(datatensor) 127 | except tf.errors.OutOfRangeError: 128 | break #如果数据取完则退出循环 129 | 130 | #将模糊图片输入生成器 131 | generated_images = g.predict(x=image_blur_batch, batch_size=batch_size) 132 | 133 | for _ in range(critic_updates):#训练5次判别器 134 | #训练,并计算真样本的loss 135 | d_loss_real = d.train_on_batch(image_full_batch, output_true_batch) 136 | #训练,并计算模拟样本的loss 137 | d_loss_fake = d.train_on_batch(generated_images, output_false_batch) 138 | d_loss = 0.5 * np.add(d_loss_fake, d_loss_real)#二者相加,再除2 139 | d_losses.append(d_loss) 140 | 141 | d.trainable = False#固定判别器参数 142 | #训练并计算生成器loss。 143 | d_on_g_loss = d_on_g.train_on_batch(image_blur_batch, [image_full_batch, output_true_batch]) 144 | d_on_g_losses.append(d_on_g_loss) 145 | 146 | d.trainable = True#恢复判别器参数可训练的属性 147 | if len(d_on_g_losses)%10== 0: 148 | print(len(d_on_g_losses),np.mean(d_losses), np.mean(d_on_g_losses)) 149 | return np.mean(d_losses), np.mean(d_on_g_losses) 150 | 151 | tf.compat.v1.keras.backend.get_session().run(tf.compat.v1.global_variables_initializer()) 152 | for epoch in tqdm.tqdm(range(epoch_num)):#按照指定次数迭代训练 153 | 154 | #迭代训练一次数据集 155 | dloss,gloss = pre_train_epoch(sess, iterator,datatensor) 156 | with open('log.txt', 'a+') as f: 157 | f.write('{} - {} - {}\n'.format(epoch, dloss, gloss)) 158 | #保存模型 159 | save_all_weights(d, g, epoch, int(gloss)) 160 | 161 | sess.close() 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /code/代码8-9 使用deblur模型.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author: 代码医生工作室 3 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 4 | @来源: 配套代码 5 | @配套代码技术支持:bbs.aianaconda.com 6 | """ 7 | import numpy as np 8 | from PIL import Image 9 | import glob 10 | import os 11 | import tensorflow as tf 12 | 13 | deblurmodel = __import__("代码8-7 deblurmodel") 14 | generator_model = deblurmodel.generator_model 15 | 16 | def deprocess_image(img): 17 | img = img * 127.5 + 127.5 18 | return img.astype('uint8') 19 | 20 | 21 | batch_size = 4 22 | #RESHAPE = (256,256) #定义处理图片的大小 23 | RESHAPE = (360,640) #定义处理图片的大小 24 | 25 | path = r'./image/test' 26 | A_paths, B_paths = os.path.join(path, 'A', "*.png"), os.path.join(path, 'B', "*.png") 27 | #获取该路径下的png文件 28 | A_fnames, B_fnames = glob.glob(A_paths),glob.glob(B_paths) 29 | #生成Dataset对象 30 | dataset = tf.data.Dataset.from_tensor_slices((A_fnames, B_fnames)) 31 | 32 | def _processimg(imgname):#定义函数调整图片大小 33 | image_string = tf.io.read_file(imgname) #读取整个文件 34 | image_decoded = tf.image.decode_image(image_string) 35 | image_decoded.set_shape([None, None, None])#形状变化,不然下面会转化失败 36 | #变化尺寸 37 | img =tf.image.resize( image_decoded,RESHAPE)#[RESHAPE[0],RESHAPE[1],3]) 38 | image_decoded = (img - 127.5) / 127.5 39 | return image_decoded 40 | 41 | def _parseone(A_fname, B_fname): #解析一个图片文件 42 | #读取并预处理图片 43 | image_A,image_B = _processimg(A_fname),_processimg(B_fname) 44 | return image_A,image_B 45 | 46 | dataset = dataset.map(_parseone) #转化为有图片内容的数据集 47 | dataset = dataset.batch(batch_size) #将数据集按照batch_size划分 48 | dataset = dataset.prefetch(1) 49 | 50 | #生成数据集迭代器 51 | iterator = tf.compat.v1.data.make_initializable_iterator(dataset) 52 | datatensor = iterator.get_next() 53 | 54 | g = generator_model(RESHAPE,False) 55 | g.load_weights("generator_499_0.h5") 56 | 57 | #定义配置文件 58 | config = tf.compat.v1.ConfigProto() 59 | config.gpu_options.allow_growth = True 60 | config.gpu_options.per_process_gpu_memory_fraction = 0.5 61 | sess = tf.compat.v1.Session(config=config)#建立session 62 | sess.run( iterator.initializer ) 63 | ii= 0 64 | while True: 65 | try:#获取一批次的数据 66 | (x_test,y_test) = sess.run(datatensor) 67 | except tf.errors.OutOfRangeError: 68 | break #如果数据取完则退出循环 69 | generated_images = g.predict(x=x_test, batch_size=batch_size) 70 | generated = np.array([deprocess_image(img) for img in generated_images]) 71 | x_test = deprocess_image(x_test) 72 | y_test = deprocess_image(y_test) 73 | print(generated_images.shape[0]) 74 | for i in range(generated_images.shape[0]): 75 | y = y_test[i, :, :, :] 76 | x = x_test[i, :, :, :] 77 | img = generated[i, :, :, :] 78 | output = np.concatenate((y, x, img), axis=1) 79 | im = Image.fromarray(output.astype(np.uint8)) 80 | # im = im.resize( (640*3, int( 640*720/1280) ) ) 81 | print('results{}{}.png'.format(ii,i)) 82 | im.save('results{}{}.png'.format(ii,i)) 83 | im2 = Image.fromarray(img.astype(np.uint8)) 84 | # im2 = im2.resize( (640, int( 640*720/1280) ) ) 85 | im2.save('results2{}{}.png'.format(ii,i)) 86 | ii+=1 87 | 88 | 89 | -------------------------------------------------------------------------------- /code/代码9-1 Sinkhorn.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import tensorflow as tf 9 | 10 | 11 | def cost_matrix(x,y): 12 | x_col = tf.expand_dims(x,-2) 13 | y_lin = tf.expand_dims(y,-3) 14 | c = tf.reduce_sum((tf.abs(x_col-y_lin))**2,axis=-1) 15 | return c 16 | 17 | 18 | def sinkhorn_loss(x,y,epsilon,niter,reduction = 'mean'): 19 | ''' 20 | Parameters 21 | ---------- 22 | x : 输入A 23 | y : 输入B 24 | epsilon :缩放参数 25 | n : A/B中元素个数 26 | niter : 迭代次数 27 | Return: 28 | 返回结果和sinkhorn距离 29 | ''' 30 | def M(C,u,v): 31 | "Modified cost for logarithmic updates" 32 | "$M_{ij} = (-c_{ij} + u_i + v_j) / \epsilon$" 33 | return (-C + tf.expand_dims(u,-1) + tf.expand_dims(v,-2)) / epsilon 34 | def lse(A): 35 | return tf.reduce_logsumexp(A,axis=1,keepdims=True) 36 | 37 | 38 | x_points = tf.shape(x)[-2] 39 | y_points = tf.shape(y)[-2] 40 | 41 | 42 | dim = len( tf.shape(x) ) 43 | if dim == 2: 44 | batch = 1 45 | else: 46 | batch = tf.shape(x)[0] 47 | 48 | mu = tf.ones([batch,x_points] , dtype = tf.float32)*(1.0/tf.cast(x_points,tf.float32)) 49 | nu = tf.ones([batch,y_points] , dtype = tf.float32)*(1.0/tf.cast(y_points,tf.float32)) 50 | mu = tf.squeeze(mu) 51 | nu = tf.squeeze(nu) 52 | 53 | 54 | u, v = 0. * mu, 0. * nu 55 | C = cost_matrix(x, y) # Wasserstein cost function 56 | for i in range(niter): 57 | 58 | u1 = u #保存上一步U值 59 | 60 | u = epsilon * (tf.math.log(mu+1e-8) - tf.squeeze(lse(M(C,u, v)) ) ) + u 61 | v = epsilon * (tf.math.log(nu+1e-8) - tf.squeeze( lse(tf.transpose(M(C,u, v))) ) ) + v 62 | 63 | err = tf.reduce_mean( tf.reduce_sum( tf.abs(u - u1),-1) ) 64 | # print("err",err) 65 | if err.numpy() < 1e-1: #如果U值没有在更新,则结束 66 | break 67 | 68 | u_final,v_final = u,v 69 | pi = tf.exp(M(u_final,v_final)) 70 | if reduction == 'mean': 71 | cost = tf.reduce_mean(pi*C) 72 | elif reduction == 'sum': 73 | cost = tf.reduce_sum(pi*C) 74 | 75 | return cost,pi, C 76 | 77 | 78 | if __name__ == '__main__': 79 | A = [[0.,0.],[1.,0.],[2.,0.],[3.,0.]] 80 | B = [[0.,1.],[1.,1.],[2.,1.],[3.,1.]] 81 | 82 | A = tf.convert_to_tensor(A) 83 | B = tf.convert_to_tensor(B) 84 | 85 | costmatrix = cost_matrix(A,B) 86 | print(costmatrix) 87 | ''' 88 | array([[ 1, 2, 5, 10], 89 | [ 2, 1, 2, 5], 90 | [ 5, 2, 1, 2], 91 | [10, 5, 2, 1]])> 92 | ''' 93 | # result, cost ,C= sinkhorn_loss(A,B,epsilon = 1,n = 4, niter = 5) 94 | cost , result, C= sinkhorn_loss(A,B,epsilon = 1, niter = 5) 95 | print(result) 96 | print(cost) 97 | ''' 98 | tf.Tensor( 99 | [[1.8792072e-01 5.9113003e-02 2.9430646e-03 2.3191265e-05] 100 | [5.9113003e-02 1.3739800e-01 5.0545905e-02 2.9430634e-03] 101 | [2.9430634e-03 5.0545905e-02 1.3739800e-01 5.9113003e-02] 102 | [2.3191265e-05 2.9430646e-03 5.9113003e-02 1.8792072e-01]], shape=(4, 4), dtype=float32) 103 | ''' -------------------------------------------------------------------------------- /code/代码9-3 feature_extractor.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author: 代码医生工作室 3 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 4 | @来源: 配套代码 5 | @配套代码技术支持:bbs.aianaconda.com 6 | """ 7 | import glob 8 | import json 9 | import os 10 | import re 11 | import shutil 12 | import tensorflow as tf 13 | from tqdm import tqdm 14 | 15 | from sklearn.utils import shuffle 16 | from sklearn.model_selection import train_test_split, KFold, cross_val_score 17 | import numpy as np 18 | 19 | def load_sample(sample_dir,shuffleflag = True): 20 | '''递归读取文件。只支持一级。返回文件名、数值标签、数值对应的标签名''' 21 | print ('loading sample dataset..') 22 | lfilenames = [] 23 | labelsnames = [] 24 | for (dirpath, dirnames, filenames) in os.walk(sample_dir):#递归遍历文件夹 25 | for filename in filenames: #遍历所有文件名 26 | #filename:每个文件夹下,每种鸟的名字 27 | filename_path = os.sep.join([dirpath, filename]) 28 | lfilenames.append(filename_path) #添加文件名 29 | labelsnames.append( dirpath.split('\\')[-1] )#添加文件名对应的标签 30 | 31 | lab= list(sorted(set(labelsnames))) #生成标签名称列表 32 | labdict=dict( zip( lab ,list(range(len(lab))) )) #生成字典 33 | 34 | labels = [labdict[i] for i in labelsnames] 35 | 36 | if shuffleflag == True: 37 | return shuffle(np.asarray( lfilenames),np.asarray( labels)),np.asarray(lab) 38 | else: 39 | return (np.asarray( lfilenames),np.asarray( labels)),np.asarray(lab) 40 | 41 | from tensorflow.keras.applications import ResNet101V2 42 | batchsize = 1 43 | 44 | cur_root = 'E:\\Project\\08-TF\\TF2\\ZSL_TF2\\CUBfeature\\' 45 | VC_dir = 'E:\\Project\\08-TF\\TF2\\ZSL_TF2\\CUBVCfeature\\' 46 | os.makedirs(cur_root, exist_ok=True)#创建目录,用于存放视觉特征 47 | dataset_path = "E:\\Project\\08-TF\\TF2\\Caltech-UCSD-Birds-200-2011\\CUB_200_2011\\images\\" 48 | 49 | image_model = ResNet101V2(weights='resnet.h5',include_top=False, pooling = 'avg') 50 | new_input = image_model.input 51 | hidden_layer = image_model.layers[-1].output #获取ResNet的倒数第二层(池化前的卷积结果) 52 | 53 | image_features_extract_model = tf.keras.Model(new_input, hidden_layer) 54 | 55 | size = [224,224] 56 | def load_image(image_path): 57 | img = tf.io.read_file(image_path) 58 | img = tf.image.decode_jpeg(img, channels=3) 59 | img = tf.image.resize(img, size) 60 | img = tf.keras.applications.resnet_v2.preprocess_input(img)#(shape is (224,224,3)) 61 | return img, image_path 62 | 63 | def avgfeature(all_features):#计算类别的平均特征 64 | #对类别中所有图片的特征求平均值 65 | avg_features = np.sum(np.asarray(all_features),axis = 0)/len(all_features) 66 | avg_features = tf.convert_to_tensor(avg_features) 67 | avg_features = tf.linalg.normalize(avg_features)[0]#对平均特征归一化 68 | avg_features = avg_features.numpy()#形状为(2048,) 69 | return avg_features 70 | 71 | def savefeature(classdir,filename,obj): #定义函数保存特征 72 | os.makedirs(classdir, exist_ok=True)#创建子目录 73 | cur_url = os.path.join(classdir,filename)#定义文件名称 74 | json.dump(obj,open(cur_url,"w"))#保存json文件 75 | print("%s has finished ..."%(classdir)) 76 | 77 | (filenames,labels),_ =load_sample(dataset_path,shuffleflag=False) #载入文件名称与标签,length of filenames is 8822 78 | ''' 79 | filenames and labels are the same as they are in pytorch 80 | ''' 81 | image_dataset = tf.data.Dataset.from_tensor_slices(filenames).map(load_image).batch(batchsize) 82 | ith_features = [] 83 | all_features = [] 84 | target_VC = [] 85 | test_VC = [] 86 | classsplit = 150 87 | number = 1 88 | for img, path in tqdm(image_dataset): 89 | ''' 90 | shape of img:(1,224,224,3) 91 | ''' 92 | batch_features = image_features_extract_model(img) 93 | batch_features = tf.squeeze(batch_features) 94 | batch_features = tf.linalg.normalize(batch_features)[0] 95 | path_of_feature = path[0].numpy().decode("utf-8") 96 | path_of_feature = path_of_feature[path_of_feature.index('images\\')+len("images\\"):] 97 | path_of_feature = path_of_feature.replace('\\','_') 98 | current_number = int(path_of_feature[:3]) 99 | if current_number == number: 100 | ith_features.append(batch_features.numpy().tolist()) 101 | all_features.append(batch_features) 102 | else: 103 | classdir= os.path.join(cur_root,"%03d"%number) #定义第i类的路径 104 | obj={} 105 | obj["features"]=ith_features 106 | savefeature(classdir,"ResNet101.json",obj) 107 | avg_feature = avgfeature(all_features) 108 | if number < classsplit+1: 109 | target_VC.append(avg_feature.tolist()) 110 | else: 111 | test_VC.append(avg_feature.tolist()) 112 | all_features.clear() 113 | ith_features.clear() 114 | number += 1 115 | continue 116 | 117 | classdir= os.path.join(cur_root,str(number)) #定义第i类的路径 118 | obj={} 119 | obj["features"]=ith_features 120 | savefeature(classdir,"ResNet101.json",obj) 121 | 122 | avg_feature = avgfeature(all_features) 123 | test_VC.append(avg_feature.tolist()) 124 | obj = {} 125 | obj["train"] = target_VC 126 | obj["test"] = test_VC 127 | savefeature(VC_dir,"ResNet101VC.json",obj) 128 | 129 | alltestfeatures = [] 130 | feature_json_list = os.listdir(cur_root) 131 | feature_json_list.sort() 132 | for dirpath in feature_json_list[classsplit:]: 133 | cur=os.path.join(cur_root,dirpath) 134 | fea_name="" 135 | url=os.path.join(cur,"ResNet101.json") 136 | js = json.load(open(url, "r")) 137 | cur_features=js["features"] 138 | alltestfeatures =alltestfeatures+cur_features 139 | 140 | from sklearn.cluster import KMeans 141 | 142 | def KM(features): 143 | clf = KMeans(n_clusters=len(feature_json_list)-classsplit, 144 | n_init=50, max_iter=100000, init="k-means++") 145 | 146 | print("Start Cluster ...") 147 | s=clf.fit(features) 148 | print("Finish Cluster ...") 149 | 150 | obj={} 151 | obj["VC"]=clf.cluster_centers_.tolist() 152 | 153 | print('Start writing ...') 154 | savefeature(VC_dir,"ResNet101VC_testCenter.json",obj) 155 | print("Finish writing ...") 156 | 157 | KM(alltestfeatures) 158 | 159 | 160 | -------------------------------------------------------------------------------- /code/代码9-4 ZSL_train.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import json 9 | import numpy as np 10 | import os 11 | import tensorflow as tf 12 | 13 | SinkhornDistance = __import__("代码9-1 Sinkhorn") 14 | 15 | 16 | 17 | class FC(tf.keras.Model): 18 | ''' 19 | 定义全连接模型将属性特征从312维映射至2048维度 20 | ''' 21 | def __init__(self): 22 | super(FC, self).__init__() 23 | self.flatten = tf.keras.layers.Flatten() 24 | 25 | self.dense1 = tf.keras.layers.Dense(1024, input_shape=(1,), name = 'dense1') 26 | self.dense2 = tf.keras.layers.Dense(2048, name = 'dense2') 27 | 28 | self.outputlayer = tf.keras.layers.Dense(2048, name = 'outputlayer') 29 | self.activation = tf.keras.layers.LeakyReLU(alpha=0.2) 30 | 31 | def call(self, input_tensor):#, training=True 32 | x = self.dense1(input_tensor) 33 | x = self.activation(x) 34 | x = self.dense2(x) 35 | x = self.activation(x) 36 | x = self.outputlayer(x) 37 | return x 38 | 39 | def WDVSc(x,y,epsilon,niter,no_use_VSC=False): 40 | ''' 41 | 定义损失函数 42 | ''' 43 | sum_ = 0 44 | for mask_idx in range(150): 45 | sum_ += (x[mask_idx] - y[mask_idx]) ** 2 46 | L2_loss = tf.reduce_sum(sum_) / (150 * 2) ## L2_Loss of seen classes 47 | A = x[150:] 48 | B = y[150:] 49 | if no_use_VSC: 50 | WD_loss=0. 51 | P=None 52 | C=None 53 | else: 54 | WD_loss,P,C = SinkhornDistance.sinkhorn_loss(A,B,epsilon,niter,reduction = 'sum') 55 | lamda=0.001 56 | tot_loss=L2_loss+WD_loss*lamda 57 | return tot_loss 58 | 59 | 60 | def ParsingAtt(lines):#312列依次转成浮点 61 | line=lines.strip().split() 62 | cur=[] 63 | for x in line: 64 | y=float(x) 65 | y=y/100.0 66 | if y<0.0: 67 | y=0.0 68 | cur.append(y) 69 | return cur 70 | 71 | def ParsingClass(lines):#类名,取第二项 72 | line=lines.strip().split() 73 | return line[1] 74 | 75 | def get_attributes(url,function=None): 76 | data=[] 77 | with open(url,"r") as f: 78 | for lines in f: 79 | cur =function(lines) 80 | data.append(cur) 81 | return data 82 | 83 | 84 | input_dim=312 85 | classNum=200 86 | unseenclassnum=50 87 | data_path=r'D:\样本\图片\Caltech-UCSD Birds-200-2011\Caltech-UCSD Birds-200-2011' 88 | attributes_url = os.path.join(data_path,"CUB_200_2011/attributes/class_attribute_labels_continuous.txt") 89 | all_class_url = os.path.join(data_path, "CUB_200_2011/classes.txt") 90 | 91 | att = get_attributes(attributes_url,ParsingAtt) #获得属性 92 | classname = get_attributes(all_class_url,ParsingClass)#获得类名 93 | 94 | word_vectors = tf.convert_to_tensor(att)#(200,312) 95 | word_vectors = tf.linalg.normalize(word_vectors)[0]#(200,312) 96 | 97 | vcdir= os.path.join(r'./CUBVCfeature/',"ResNet101VC.json") #可见类的VC中心文件json file 98 | #保存可见类的VC中心文件json file 99 | obj=json.load(open(vcdir,"r")) 100 | VC=obj["train"] #获得可见类的中心点 101 | 102 | # Obtain the approximated VC of unseen class 103 | vcdir= os.path.join(r'./CUBVCfeature/',"ResNet101VC_testCenter.json") #可见类的VC中心文件json file 104 | obj=json.load(open(vcdir,"r")) 105 | test_center=obj["VC"] 106 | 107 | 108 | VC = VC+test_center #源域类别中心点和目的域类别聚类中心点 109 | vc_tensor = tf.convert_to_tensor(VC)#加载平均视觉特征 110 | 111 | print("vc_tensor,word_vectors",tf.shape(vc_tensor),tf.shape(word_vectors)) 112 | 113 | 114 | 115 | 116 | batch_size = 1 117 | lr=0.001 118 | wd=0.0005 119 | max_epoch=5000 120 | 121 | 122 | 123 | optimizer = tf.keras.optimizers.Adam(learning_rate=lr) 124 | 125 | Net = FC() 126 | 127 | loss_list = [] 128 | 129 | 130 | ################################################ 131 | 132 | for i in range(max_epoch): 133 | 134 | with tf.GradientTape() as tape: 135 | tape.watch(Net.variables) 136 | syn_vc = Net(word_vectors) 137 | loss = WDVSc(vc_tensor,syn_vc,epsilon = 0.01, niter = 1000) 138 | grad=tape.gradient(target=loss,sources=Net.variables) 139 | optimizer.apply_gradients(zip(grad,Net.variables)) 140 | loss_list.append(loss) 141 | print("{}-th loss = {}".format(i, loss )) 142 | if i+1 % 1000 == 0: 143 | checkpoint_path = "check_point\\" 144 | if os.path.exists(checkpoint_path): 145 | pass 146 | else: 147 | os.mkdir(checkpoint_path) 148 | Net.save_weights(checkpoint_path+'model_%s.ckpt'%str(i)) 149 | 150 | print('training is over') 151 | 152 | #################################################### 153 | 154 | 155 | output_vectors = Net(word_vectors) #调用模型,根据属性生成特征 156 | 157 | np.save("Pred_Center.npy",output_vectors) 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /code/代码9-5 ZSL_test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @author: 代码医生工作室 4 | @公众号:xiangyuejiqiren (内有更多优秀文章及学习资料) 5 | @来源: 配套代码 6 | @配套代码技术支持:bbs.aianaconda.com 7 | """ 8 | import json 9 | import numpy as np 10 | import os 11 | 12 | 13 | def ParsingClass(lines):#类名,取第二项 14 | line=lines.strip().split() 15 | return line[1] 16 | 17 | def get_attributes(url,function=None): 18 | data=[] 19 | with open(url,"r") as f: 20 | for lines in f: 21 | cur =function(lines) 22 | data.append(cur) 23 | return data 24 | 25 | 26 | input_dim=312 27 | classNum=200 28 | unseenclassnum=50 29 | data_path=r'D:\样本\图片\Caltech-UCSD Birds-200-2011\Caltech-UCSD Birds-200-2011' 30 | attributes_url = os.path.join(data_path,"CUB_200_2011/attributes/class_attribute_labels_continuous.txt") 31 | all_class_url = os.path.join(data_path, "CUB_200_2011/classes.txt") 32 | 33 | 34 | classname = get_attributes(all_class_url,ParsingClass)#获得类名 35 | 36 | 37 | 38 | vcdir= os.path.join(r'./CUBVCfeature/',"ResNet101VC.json") #可见类的VC中心文件json file 39 | #保存可见类的VC中心文件json file 40 | obj=json.load(open(vcdir,"r")) 41 | VC=obj["train"] #获得可见类的中心点 42 | 43 | # Obtain the approximated VC of unseen class 44 | vcdir= os.path.join(r'./CUBVCfeature/',"ResNet101VC_testCenter.json") #可见类的VC中心文件json file 45 | obj=json.load(open(vcdir,"r")) 46 | test_center=obj["VC"] 47 | 48 | 49 | VC = VC+test_center #源域类别中心点和目的域类别聚类中心点 50 | 51 | def NN_search(x,center): 52 | ret="" 53 | MINI=-1 54 | for c in center.keys(): 55 | tmp=np.sum((x-center[c])*(x-center[c]))#L2_dis 56 | # print(c,tmp) 57 | if MINI==-1: 58 | MINI=tmp 59 | ret=c 60 | if tmp