# TensorFlow定制模型和训练算法（上）

import：

import sys
assert sys.version_info >= (3, 5)

import sklearn
assert sklearn.__version__ >= "0.20"

try:

%tensorflow_version 2.x
except Exception:
pass

import tensorflow as tf
from tensorflow import keras
assert tf.__version__ >= "2.4"

import numpy as np
import os

np.random.seed(42)
tf.random.set_seed(42)

%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt


## 1、自定义损失函数

def huber_fn(y_true, y_pred):
error = y_true - y_pred
is_small_error = tf.abs(error) < 1
squared_loss = tf.square(error) / 2
linear_loss  = tf.abs(error) - 0.5
return tf.where(is_small_error, squared_loss, linear_loss)


from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

housing = fetch_california_housing()
X_train_full, X_test, y_train_full, y_test = train_test_split(
housing.data, housing.target.reshape(-1, 1), random_state=42)
X_train, X_valid, y_train, y_valid = train_test_split(
X_train_full, y_train_full, random_state=42)

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_valid_scaled = scaler.transform(X_valid)
X_test_scaled = scaler.transform(X_test)

plt.figure(figsize=(8, 3.5))
z = np.linspace(-4, 4, 200)
plt.plot(z, huber_fn(0, z), "b-", linewidth=2, label="huber($z$)")
plt.plot(z, z**2 / 2, "b:", linewidth=1, label=r"$\frac{1}{2}z^2$")
plt.plot([-1, -1], [0, huber_fn(0., -1.)], "r--")
plt.plot([1, 1], [0, huber_fn(0., 1.)], "r--")
plt.gca().axhline(y=0, color='k')
plt.gca().axvline(x=0, color='k')
plt.axis([-4, 4, 0, 4])
plt.grid(True)
plt.xlabel("$z$")
plt.legend(fontsize=14)
plt.title("Huber loss", fontsize=14)
plt.show()


input_shape = X_train.shape[1:]

model = keras.models.Sequential([
keras.layers.Dense(30, activation="selu", kernel_initializer="lecun_normal",
input_shape=input_shape),
keras.layers.Dense(1),
])

model.fit(X_train_scaled, y_train, epochs=2,
validation_data=(X_valid_scaled, y_valid))

Epoch 1/2
363/363 [==============================] - 1s 2ms/step - loss: 1.0443 - mae: 1.4660 - val_loss: 0.2862 - val_mae: 0.5866
Epoch 2/2
363/363 [==============================] - 0s 737us/step - loss: 0.2379 - mae: 0.5407 - val_loss: 0.2382 - val_mae: 0.5281


## 2、保存和加载包含自定义组件的模型

（1）直接映射：

model.save("my_model_with_a_custom_loss.h5")

custom_objects={"huber_fn": huber_fn})
model.fit(X_train_scaled, y_train, epochs=2,
validation_data=(X_valid_scaled, y_valid))

Epoch 1/2
363/363 [==============================] - 1s 970us/step - loss: 0.2054 - mae: 0.4982 - val_loss: 0.2209 - val_mae: 0.5050
Epoch 2/2
363/363 [==============================] - 0s 769us/step - loss: 0.1999 - mae: 0.4900 - val_loss: 0.2127 - val_mae: 0.4986


（2）为了要不同的阈值，可以创建一个已经配置损失函数的函数：

def create_huber(threshold=1.0):
def huber_fn(y_true, y_pred):
error = y_true - y_pred
is_small_error = tf.abs(error) < threshold
squared_loss = tf.square(error) / 2
linear_loss  = threshold * tf.abs(error) - threshold**2 / 2
return tf.where(is_small_error, squared_loss, linear_loss)
return huber_fn

model.fit(X_train_scaled, y_train, epochs=2,
validation_data=(X_valid_scaled, y_valid))

Epoch 1/2
363/363 [==============================] - 1s 1ms/step - loss: 0.2318 - mae: 0.4979 - val_loss: 0.2540 - val_mae: 0.4907
Epoch 2/2
363/363 [==============================] - 0s 749us/step - loss: 0.2309 - mae: 0.4960 - val_loss: 0.2372 - val_mae: 0.4879


class HuberLoss(keras.losses.Loss):
def __init__(self, threshold=1.0, **kwargs):
self.threshold = threshold
super().__init__(**kwargs)

def call(self, y_true, y_pred): //获取标签和预测，返回计算后的实例损失。
error = y_true - y_pred
is_small_error = tf.abs(error) < self.threshold
squared_loss = tf.square(error) / 2
linear_loss  = self.threshold * tf.abs(error) - self.threshold**2 / 2
return tf.where(is_small_error, squared_loss, linear_loss)
//返回一个字典，将每个超参数名称映射到其值。
def get_config(self):                   //返回一个字典，将每个超参数名称映射到其值。
base_config = super().get_config()
return {**base_config, "threshold": self.threshold}

model = keras.models.Sequential([
keras.layers.Dense(30, activation="selu", kernel_initializer="lecun_normal",
input_shape=input_shape),
keras.layers.Dense(1),
])

//使用此类 任何实例。

//训练模型
model.fit(X_train_scaled, y_train, epochs=2,
validation_data=(X_valid_scaled, y_valid))

Epoch 1/2
363/363 [==============================] - 1s 1ms/step - loss: 1.3123 - mae: 1.3345 - val_loss: 0.3378 - val_mae: 0.5485
Epoch 2/2
363/363 [==============================] - 0s 760us/step - loss: 0.2659 - mae: 0.5270 - val_loss: 0.2660 - val_mae: 0.5089


[En]

Load the model: just map the class name to the class itself.

model.save("my_model_with_a_custom_loss_class.h5")

custom_objects={"HuberLoss": HuberLoss})
model.fit(X_train_scaled, y_train, epochs=2,
validation_data=(X_valid_scaled, y_valid))

Epoch 1/2
363/363 [==============================] - 1s 966us/step - loss: 0.2286 - mae: 0.4970 - val_loss: 0.2120 - val_mae: 0.4723
Epoch 2/2
363/363 [==============================] - 0s 757us/step - loss: 0.2216 - mae: 0.4904 - val_loss: 0.2045 - val_mae: 0.4725


## 3、自定义激活函数、初始化、正则化和约束

//自定义激活函数：
def my_softplus(z):
return tf.math.log(tf.exp(z) + 1.0)

//自定义Glorot初始化：
def my_glorot_initializer(shape, dtype=tf.float32):
stddev = tf.sqrt(2. / (shape[0] + shape[1]))
return tf.random.normal(shape, stddev=stddev, dtype=dtype)

//自定义正则化：
def my_l1_regularizer(weights):
return tf.reduce_sum(tf.abs(0.01 * weights))

//确保权重为正的自定义约束：
def my_positive_weights(weights):
return tf.where(weights < 0., tf.zeros_like(weights), weights)


[En]

The parameters depend on the type of custom function, and we can use these custom functions normally:

layer = keras.layers.Dense(1, activation=my_softplus,
kernel_initializer=my_glorot_initializer,
kernel_regularizer=my_l1_regularizer,
kernel_constraint=my_positive_weights)


[En]

In each training step, the weight is passed to the regularization function to calculate the regularization loss, which is added to the main loss to get the final loss.

[En]

Finally, the constraint function is called after each training step, and the weight of the layer is replaced by the constraint weight.

keras.backend.clear_session()
np.random.seed(42)
tf.random.set_seed(42)

model = keras.models.Sequential([
keras.layers.Dense(30, activation="selu", kernel_initializer="lecun_normal",
input_shape=input_shape),
keras.layers.Dense(1, activation=my_softplus,
kernel_regularizer=my_l1_regularizer,
kernel_constraint=my_positive_weights,
kernel_initializer=my_glorot_initializer),
])

model.fit(X_train_scaled, y_train, epochs=2,
validation_data=(X_valid_scaled, y_valid))

Epoch 1/2
363/363 [==============================] - 1s 1ms/step - loss: 2.3829 - mae: 1.1635 - val_loss: 1.4154 - val_mae: 0.5607
Epoch 2/2
363/363 [==============================] - 0s 757us/step - loss: 0.6299 - mae: 0.5410 - val_loss: 1.4399 - val_mae: 0.5137


[En]

If the function has hyperparameters that need to be saved with the model, you need to inherit the appropriate class:

class MyL1Regularizer(keras.regularizers.Regularizer):
def __init__(self, factor):
self.factor = factor
def __call__(self, weights):
return tf.reduce_sum(tf.abs(self.factor * weights))
def get_config(self):
return {"factor": self.factor}

keras.backend.clear_session()
np.random.seed(42)
tf.random.set_seed(42)

model = keras.models.Sequential([
keras.layers.Dense(30, activation="selu", kernel_initializer="lecun_normal",
input_shape=input_shape),
keras.layers.Dense(1, activation=my_softplus,
kernel_regularizer=MyL1Regularizer(0.01),
kernel_constraint=my_positive_weights,
kernel_initializer=my_glorot_initializer),
])
model.fit(X_train_scaled, y_train, epochs=2,
validation_data=(X_valid_scaled, y_valid))

Epoch 1/2
363/363 [==============================] - 1s 1ms/step - loss: 2.3829 - mae: 1.1635 - val_loss: 1.4154 - val_mae: 0.5607
Epoch 2/2
363/363 [==============================] - 0s 757us/step - loss: 0.6299 - mae: 0.5410 - val_loss: 1.4399 - val_mae: 0.5137


ps：必须为 损失、层函数和模型 实现call（）方法。为正则化、初始化和约束实现 call()方法。

## 4、自定义指标

Lost：用于通过梯度下降来训练模型，因此它必须是可微的；并且梯度不是0。

[En]

Loss: used to train the model by gradient descent, so it must be differentiable; and the gradient is not 0.

[En]

Indicators: used to evaluate the model. It has to be easy to understand.

[En]

In most cases, defining a custom metric function is exactly the same as defining a custom loss function.


model = keras.models.Sequential([
keras.layers.Dense(30, activation="selu", kernel_initializer="lecun_normal",
input_shape=input_shape),
keras.layers.Dense(1),
])
//指标

model.fit(X_train_scaled, y_train, epochs=2)

Epoch 1/2
363/363 [==============================] - 1s 572us/step - loss: 3.5903 - huber_fn: 1.5558
Epoch 2/2
363/363 [==============================] - 0s 552us/step - loss: 0.8054 - huber_fn: 0.3095



[En]

The indicator updated batch by batch is the flow indicator (or status indicator).

precision = keras.metrics.Precision()
precision([0, 1, 1, 1, 0, 1, 0, 1], [1, 1, 0, 1, 0, 1, 0, 1])


<tf.Tensor: shape=(), dtype=float32, numpy=0.8>


precision([0, 1, 0, 0, 1, 0, 1, 1], [1, 0, 1, 1, 0, 0, 0, 0])

<tf.Tensor: shape=(), dtype=float32, numpy=0.5>


precision.result()

<tf.Tensor: shape=(), dtype=float32, numpy=0.5>


precision.variables


[<tf.Variable 'true_positives:0' shape=(1,) dtype=float32, numpy=array([4.], dtype=float32)>,
<tf.Variable 'false_positives:0' shape=(1,) dtype=float32, numpy=array([4.], dtype=float32)>]


precision.reset_states()


class HuberMetric(keras.metrics.Metric):
def __init__(self, threshold=1.0, **kwargs):
super().__init__(**kwargs)
self.threshold = threshold
self.huber_fn = create_huber(threshold)
//给定一个批次的标签和预测值（以及采样权重（此例忽略）），它会更新变量。
def update_state(self, y_true, y_pred, sample_weight=None):
metric = self.huber_fn(y_true, y_pred)
//计算并返回最终结果。
def result(self):
return self.total / self.count
//确保threshold与模型一起被保存。
def get_config(self):
base_config = super().get_config()
return {**base_config, "threshold": self.threshold}


Keras会处理变量的持久性，无需采取任何措施。

Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow, 2nd Edition, 作者： Aurelien Geron(法语) , 又 O Reilly 出版， 书号 978-1-492-03264-9。
🆗

Original: https://blog.csdn.net/qq_51153436/article/details/124512001
Author: 看到我你要笑一下
Title: TensorFlow定制模型和训练算法（上）

(0)

### 大家都在看

• #### Python数据挖掘项目：基于三种肝癌样本数据的PCA分析以及神经网络分类模型的构建

作者CSDN：进击的西西弗斯本文链接：https://blog.csdn.net/qq_42216093/article/details/116994199版权声明：本文为作者原创…

人工智能 2023年7月2日
0145
• #### 22种图分析算法介绍

图分析算法，以图论为驱动，进行算法优化，结合应用工程，业务形态研究，不同领域场景模拟不同网络结构，通过自由刻画网络图形关系，验证结构合理性，如边的有向和无向及权重，从而辅助分析图形…

人工智能 2023年6月1日
0309
• #### 深度学习之医学影像分割与分类_Matlab完整开发流程

文章目录 前言 一、基本介绍 二、DeepLabV3+分割网络 * 1.语义分割网络数据集制备 2.加载数据集图像和标签 3.DeepLabV3+网络搭建 – 3.1用…

人工智能 2023年6月17日
0174
• #### 海康线阵相机调试指导

前段时间应公司结构要求，需评估结构和硬件，主要围绕线阵相机图像质量上，在此记录下调试过程中的一些经验，希望能给同行一些方向，互相学习。 * 确认外界光源是否满足 评估光源是否满足的…

人工智能 2023年7月28日
0271
• #### yolov5s模型转tensorrt+deepstream检测+CSI和USB摄像头检测

软硬件版本 ubuntu 18.04 Jetson Nano 4GJP 4.5.1CUDA 10.2TensorRT 7.1.3.0 python 3.6 前言 把自己训练好的yo…

人工智能 2023年7月23日
0134
• #### 无人驾驶虚拟仿真（十二）–图像处理之红绿灯识别

简介：在交通地图中有红绿灯组件，一般放置在T形或者十字路口处，车辆行驶过程中，需要检测红绿灯信号来控制车辆启停，以符合基本的交通规则。红绿灯识别基本分为图像截取、斑点检测、颜色识别…

人工智能 2023年6月20日
0143
• #### 使用SVM分类器进行图像多分类

ResNet backbone + SVM分类器 对于样本较为均衡小型数据集，SVM作为分类器的效果与MLP的效果相近。从经验上看，对于样本不均衡的大型数据集，MLP的效果强于SV…

人工智能 2023年6月15日
0171
• #### 高德地图哪个语音包最好_高德地图妲己语音

AMAP大集语音包是王者荣耀海外版中的一款大集智能语音导航。使用小大集语音系统，你可以听到大集语音的导航，就像玩游戏一样，给你不一样的感受体验。如果你喜欢小大吉，千万不要错过这个语…

人工智能 2023年5月25日
0141
• #### OpenCV基础操作_视频读取

1.1 cv2. VideoCapture () 在OpenCV中，可以使用 VideoCapture来读取视频文件，或是摄像头数据。 Python: cv2. VideoCapt…

人工智能 2023年7月27日
0134
• #### 【PAT甲级 – C++题解】1048 Find Coins

✍个人博客：https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343📚专栏地址：PAT题解集合📝原题地址：题目详情 &#821…

人工智能 2023年6月27日
0145
• #### Arduino与LU-ASR01语音识别模块的双向串口通信实现

之前我写了一篇《Arduino的智能语言输入实现》，讨论了Arduino与LU-ASR01之间通过串口通信实现Arduino的中文语音输入，不过那个通信是不完整的，因为LU-ASR…

人工智能 2023年5月23日
0152
• #### 【生成对抗网络】GAN入门与代码实现（一）

文章目录 * – 1. 生成对抗网络介绍 – 2. 基于TensorFlow2的GAN的简单实现 – + 2.1 导包与参数设置 + 2.2 生…

人工智能 2023年6月17日
0169
• #### 股票python量化交易015-计算累积收益率

*累积收益率的概念 通过上面图的演算就可以得出累积收益率的公式： 累积收益率 = （1 + 当天收益率） 的累计乘积 – 1 *累计乘积在python中怎么使用？ 针对…

人工智能 2023年7月15日
0183
• #### PIM其它特性——IPv6、Anycast RP

PIM IPv6 MLD 接收端到组播路由器之间使用MLD协议来支持IPv6组播MLD 版本MLDv1同ICMPv2MLDv2同ICMPv3MLD 报文通过ICMPv6进行发包IC…

人工智能 2023年6月26日
0186
• #### hⅰgh怎么读音发音英语_赞！！！48个英语国际音标的知识都在这里了

英语音标是标示英语发音的符号，用来规范英语口语的发音，就像汉语拼音是标示汉字发音的符号一样。因此，学习英语音标是记忆英语单词、学习英语语法、学习英语发音的必要基础，也是学习标准英语…

人工智能 2023年5月27日
0175
• #### pandas数据分组groupby()和统计函数agg()

数据分组 使用 groupby() 方法进行分组 group. size()查看分组后每组的数量 group. groups 查看分组情况 group. get_group(‘&a…

人工智能 2023年7月6日
0140