为什么

俊瑶先森为什么翻译这本书?

用了7年redis,为什么要重新梳理了。因为发现了很多盲区。将在这次完整梳理。

关于这本书

Redis是一个开源的内存键值数据存储,以其灵活性、性能和广泛的语言支持。NoSQL数据库,Redis不使用结构化查询语言(也称为SQL)来存储、操作和检索数据。Redis自带一套用于管理和访问数据的命令。本书的章节涵盖了广泛的Redis命令,但是它们通常专注于连接到Redis数据库,管理各种数据类型,以及故障排除和调试问题,以及还有一些更具体的功能。

本书的章节涵盖了广泛的Redis命令,但是它们通常专注于连接到Redis数据库,管理各种数据类型,以及故障排除和调试问题,以及还有一些更具体的功能。我们鼓励你跳到无论哪一章与你要完成的任务相关。

本书的动机

每个可用的Redis命令都在官方的Redis命令文档,以及其他许多印刷和在线资源。然而,许多资源倾向于各自独立互相指挥,不把他们绑在一起。

这本书旨在提供一个平易近人的介绍Redis通过概述键值存储的许多命令,读者可以可以学习它们的模式和语法,从而建立起读者的逐渐理解。这本书涵盖了从连接到对于Redis数据存储,对于管理各种Redis数据类型,错误排除,等等。

学习目标和成果

本书的目标是为那些有兴趣开始使用Redis或一般键值存储的用户提供Redis的简介。对于经验丰富的用户,这本书可以作为有用的资料集备忘单和深入参考。每章都是独立的,可以独立于其他人。通过阅读并关注伴随着每一章,您将熟悉Redis的许多内容。最广泛使用的命令,它将在您开始构建利用其功能和速度的应用程序时为您提供帮助。

如何使用这本书

本书各章均以备忘单形式编写,且内容齐全例子。我们鼓励您跳至与您要完成的任务。本书中显示的命令已在Ubuntu 18.04上进行了测试运行Redis版本4.0.9的服务器。要设置类似的环境,您可以可以按照关于如何安装和保护Redis的指南中的步骤1进行操作。Ubuntu 18.04。我们将通过以下方式演示这些命令的行为使用Redis命令行界面redis-cli运行它们。注意如果您使用其他Redis界面(例如Redli),某些命令的确切输出可能会有所不同。或者,您可以将托管Redis数据库实例设置为探索Redis的功能。但是,取决于控制级别在数据库提供商允许的情况下,本指南中的某些命令可能不会按照说明进行工作。将此书与DigitalOcean Managed一起使用数据库,请遵循我们的托管数据库产品文档。然后,您必须安装Redli或设置TLS隧道才能连接到TLS上的托管数据库。

原著:how to manage a redis database
翻译: 俊瑶先森

工具及规范

uPic 图床配置及安装

1.mac用户直接下载安装包运行安装
https://github.com/gee1k/uPic/releases
3DsQWM

2.偏好设置中设置图床
ACkWHA
nnVASV
3.配置剪贴板上传快捷键

建议配置快捷键为 shift+command + c 与复制快捷键 command + c 快速组合
一般剪贴板上传就解决了99%的需求

GchLGT

AntDocs of VuePress配置及安装

文档:https://antdocs.seeyoz.cn/guide/using-vuepress-creator.html

使用

  • 示例:如何快速插入图片,例如桌面有一张图片。

1.打开图片,按command + c 将图片复制到剪贴板。
2.shift+command + c 上传
3.command + v 粘贴 图片链接

influxdb备忘

influxdb的两个http端口:8083和8086

  • port 8083:管理页面端口,访问localhost:8083可以进入你本机的influxdb管理页面;
  • port 8086:http连接influxdb client端口,一般使用该端口往本机的influxdb读写数据。

在1.3以后,8083端口被弃用,admin模块也失效,但是可以使用 Chronograf 专用的开源web应用,方便的可视化监控数据,与grafana等可视化工具功能相同。

名词解释

  • database:数据库;
  • measurement:数据库中的表;
  • points:表里面的一行数据。

influxDB中独有的一些概念
Point由时间戳(time)、数据(field)和标签(tags)组成。

  • time:每条数据记录的时间,也是数据库自动生成的主索引;
  • fields:各种记录的值;
  • tags:各种有索引的属性。

docker创建

1.3后无admin界面,官方推荐使用chronograf ui管理

docker

1
2
3
4
5
$ docker run -p 8086:8086 -p 8083:8083 \
-e INFLUXDB_DB=db0 -e INFLUXDB_ADMIN_ENABLED=true \
-e INFLUXDB_ADMIN_USER=admin -e INFLUXDB_ADMIN_PASSWORD=supersecretpassword \
-e INFLUXDB_USER=telegraf -e INFLUXDB_USER_PASSWORD=secretpassword \
-v $PWD:/var/lib/influxdb

docker-compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
version: "3.3"

services:
influxdb:
image: "influxdb"
container_name: "influxdb"
environment:
- TZ=Asia/Shanghai
- INFLUXDB_DB=testDb
- INFLUXDB_ADMIN_USER=admin
- INFLUXDB_ADMIN_PASSWORD=admin
- INFLUXDB_HTTP_AUTH_ENABLED=true
- INFLUXDB_ADMIN_ENABLED=true
- INFLUXDB_USER=bulolo
- INFLUXDB_USER_PASSWORD=hjyhjy0927
ports:
- "8086:8086"
volumes:
- "./data/influxdb:/var/lib/influxdb"

chronograf:
image: chronograf:latest
ports:
- '8888:8888'
volumes:
- ./data/chronograf:/var/lib/chronograf
depends_on:
- influxdb
environment:
- INFLUXDB_URL=http://influxdb:8086

简单命令示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
influx -username 'admin' -password 'admin'  登录
precision rfc3339 --把时间戳转化为方便阅读的时间格式
SHOW USERS --显示用户
CREATE USER "username" WITH PASSWORD 'password' WITH ALL PRIVILEGES --创建管理员权限的用户
DROP USER "username" --删除用户
CREATE DATABASE mydb --创建数据库
SHOW DATABASES --展示所有数据库
SHOW RETENTION POLICIES ON mydb --查看保留策略
USE mydb --使用数据库

DROP DATABASE mydb --删除数据库
SHOW MEASUREMENTS --查询当前数据库中含有的表
SHOW CONTINUOUS QUERIES --查看连续执行命令
SHOW FIELD KEYS FROM mytable --查看当前数据库下的mytable表的字段
SHOW SERIES FROM mytable --查看key数据
SHOW TAG KEYS FROM mytable --查看key中tag key值
SELECT * FROM mytable --查询当前数据库下mytable表的记录
INSERT cpu,host=serverA,region=us_west value=0.64 --在cpu表中插入相关的数据
SELECT * FROM cpu ORDER BY DESC LIMIT 3 --查询cpu表下最近的三条数据
DROP MEASUREMENT mytable --删除表
precision rfc3339 --把时间戳转化为方便阅读的时间格式


授权语法

创建用户:CREATE USER <username> WITH PASSWORD ‘<password>‘
授权权限:GRANT [READ,WRITE,ALL] ON <database_name> TO <username>
创建并授权:CREATE USER <username> WITH PASSWORD ‘<password>‘ WITH ALL PRIVILEGES
取消授权:REVOKE ALL PRIVILEGES FROM <username>
修改密码:SET PASSWORD FOR <username> = ‘<password>‘
删除用户:DROP USER <username>

集成到ChirpStack

到Applications-某个应用-INTEGRATIONS,增加InfluxDB
s5nzE3
这里有个坑,记得将influxdb的docker的网络加入到ChirpStack,并且以[http://]+[influxDB容器名称]:8086/write 来填写API endpoint.
例如:

1
http://influxdb:8086/write

indexfuxDB数据说明

所有 measurements 名称都是将 object 的几个元素用下划线来连接下来。其中的 Payload 数据是以 device_frmpayload_data 做前缀,同时要求 Payload 存入 InfluxDB 之前需要保证为 JSON 格式, 键为:object。也就是要开启 ChirpStack 编解码函数功能

Payload 示例:

1
2
3
4
5
6
7
8
9
10
11
12
{
"object": {
"DeviceType": "4A",
"Mulitplier1": "00",
"ReportType": "02",
"Version": "01",
"a_current": 257,
"b_current": 0,
"battery": 36,
"c_current": 0
}
}

其实也就是编解码函数解析出来的object字段。

例如:DeviceType最终 measurements 名称将为device_frmpayload_data_DeviceType

sr6WEE

每个 measurements 都有如下的 tag:

1
2
3
4
application_name
device_name
dev_eui
f_port (LoRaWAN port used for uplink)
Ium28Z

ChirpStack 还支持几类数据的记录:
Device uplink meta-data,为了监控扩频因子、信道等数据,每个上行数据都会记录到名为 device_uplink 的 measurement。 其中的 value 固定为 1。

备忘进度。待输出详细文章

day1: 2020.10.21

lora基础概念入门
从头部署ChirpStack,并完成接入网关及3个lora设备。

网关ISM频段标准:

EU868和EU433主要是欧洲标准,
US915是美国标准,
CN779、CN470是中国标准,
AU915主要是澳大利亚标注,
AS923主要是亚洲其余国家标准,
KR923主要是韩国标准,
IN865主要是印度标准,
RU864主要是俄罗斯标准。

节点的入网/激活

每个要接入LoRaWAN网络的节点,必须经过入网/激活的过程,节点入网的目的是获得云端分配的DevAddr、AppSKey、NwkSEncKey等通信必须的信息,入网方式分以下两种。

OTAA(Over-The-Air Activation)空中激活

OTAA中,节点的AppSKey和NwkSEncKey信息是临时从云端获取的,节点中需要提前烧录NwkKey和Appkey、JoinEUI等信息,节点向云端发送Join-request message请求,云端返回Join-accept message,节点提取Join-accept message中的DevAddr,JoinNonce等信息,并自己计算生成AppSKey和NwkSEncKey等信息。

ABP (Activation By Personalization)人工激活

ABP中,节点需要的DevAddr、AppSKey、NwkSEncKey等信息,不是从云端获取的,而是提前在云端配置好,并烧录到节点固件中,节点使用这些信息可以直接和云端通信,省去了OTAA中的Join-request流程。

ChirpStack 编解码函数功能

在 Device Profile 中有一个 codec 模块。

  • Custom JavaScript codec functions 即JS 编解码函数
Decode解析数据

启动 Decode 之后的数据,多了一个 object 对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function toHexString(bytes) {
return bytes.map(function(byte) {
return ("00" + (byte & 0xFF).toString(16)).slice(-2)
}).join('').toUpperCase()
}

function Decode(fPort, bytes, variables) {
var hex = toHexString(bytes)
return {
"Version": hex.substring(0, 2),
"DeviceType": hex.substring(2, 4),
"ReportType": hex.substring(4, 6),
"battery": parseInt(hex.substring(6, 8), 16),
"a_current": parseInt(hex.substring(8, 12), 16),
"b_current": parseInt(hex.substring(12, 16), 16),
"c_current": parseInt(hex.substring(16, 20), 16),
"Mulitplier1": hex.substring(20, 22),
}
}
1
2
3
function Encode(fPort, obj, variables) {
return [];
}

day2: 2020.10.22

通过mqtt打通ChirpStack上下行数据,操作lora设备。

ChirpStack中的mqtt主题示例:

ApplicationID和 DevEUI 可以直接从订阅主题中获得

Events

application/[ApplicationID]/device/[DevEUI]/event/[EventType]

application/[ApplicationID]/device/[DevEUI]/command/down

day3: 2020.10.23

熟悉lora设备的指令操作解析
主要有2种方式,一种是从上面讲的mqtt中进行publish,
另外一种是从ChirpStrack进行上行数据查看及下发数据

下发数据:
9k6kPm
查看上行数据
EWBRYB

待评估处理:

1.调研lora采用的时序数据库,通过美观的方式展现lora的数据

ChirpStack 在应用集成中配置将数据的收发存储到 InfluxDB,再通过 Granfana 进行可视化观察。

时序数据库 InfluxDB集成
Grafana

2.调研lora的监控及报警

Prometheus

3.chripstack整合平台的可行性

评估chripstack的开放api接口的操作能力

4.对硬件实际测试效果

对实际lora设备进行测试,评估lora实际运用的效果

简单记录下这个过程。最后再输出完整过程。

发现 9.23

偶然机会,我到专壹自习室进行了体验,发现专壹自习室内的是由全自动化的设备进行无人化运营的。勾起了我的兴趣。打算把家里改造成智能化
以此记录整个俊瑶的智能家的始末。

cgUJfv

调研-立项-立flag 9.25

再次调研专壹自习室、考拉自习室、一隅自习室。立项,我要把家里改造成智能家居,并确认一下自己提出的几个要求

1.尽可能能接入各个厂商的设备
2.网关协议尽可能的自主可控
3.外网可控。

立个最终效果flag,以此作为目标

o80tAU 1q64kZ QxC8wg

技术初步调研及尝试

首先买个小米多模网关。结论-坑,只兼容小米的部分zigbee设备,对别的设备不兼容。放弃
WzSFZr

技术最终选型

  1. home assistant+群晖(树莓派也可)vuMYFd WfX0H5
  2. zigbee2mqtt9gQejz 3.网关板子 有线版 mFPTeZ 无线版 mFWj6b

初步原理:将所有设备连如网关,再由网关上云,通过云来控制网关下发控制子设备。

进度:

1.接入米家台灯

发现家里的小米台灯是yeelight,立刻接入尝试。

2.接入智能插座wifi版+智能插座蓝牙网关版

pTP7Zz

3.接入人体红外

5P5g7Z

4.接入落地灯

HjxUy6

5.接入慧作吸顶风扇灯 ✖️2

6I5MiW

6.接入无线开关六键版

jAVKcO

激活函数是深度学习,亦或者说人工神经网络中一个十分重要的组成部分,它可以对神经元的接收信息进行非线性变换,将变换后的信息输出到下一层神经元。激活函数作用方式如下公式所示:

01d9Nn

其中,𝐴𝑐𝑡𝑖𝑣𝑎𝑡𝑖𝑜𝑛()就是激活函数。

为什么要使用激活函数呢?当我们不用激活函数时,网络中各层只会根据权重𝑤和偏差𝑏只会进行线性变换,就算有多层网络,也只是相当于多个线性方程的组合,依然只是相当于一个线性回归模型,解决复杂问题的能力有限。我们希望我们的神经网络能够处理复杂任务,如语言翻译和图像分类等,线性变换永远无法执行这样的任务。激活函数得加入能对输入进行非线性变换,使其能够学习和执行更复杂的任务。

另外,激活函数使反向传播成为可能,因为激活函数的误差梯度可以用来调整权重和偏差。如果没有可微的非线性函数,这就不可能实现。

总之,激活函数的作用是能够给神经网络加入一些非线性因素,使得神经网络可以更好地解决较为复杂的问题。

常用激活函数

1、sigmoid函数

sigmoid函数可以将整个实数范围的的任意值映射到[0,1]范围内,当当输入值较大时,sigmoid将返回一个接近于1的值,而当输入值较小时,返回值将接近于0。sigmoid函数数学公式和函数图像如下所示:

m9JssL

感受一下TensorFlow中的sigmoid函数:

1
2
3
import tensorflow as tf
x = tf.linspace(-5., 5.,6)
x

<tf.Tensor: id=3, shape=(6,), dtype=float32, numpy=array([-5., -3., -1., 1., 3., 5.], dtype=float32)>

有两种方式可以调用sigmoid函数:
方式一:

1
tf.keras.activations.sigmoid(x)
1
2
<tf.Tensor: id=4, shape=(6,), dtype=float32, numpy=
array([0.00669285, 0.04742587, 0.26894143, 0.7310586 , 0.95257413 , 0.9933072 ], dtype=float32)>

方式二:

1
tf.sigmoid(x)
1
2
<tf.Tensor: id=5, shape=(6,), dtype=float32, numpy=
array([0.00669285, 0.04742587, 0.26894143, 0.7310586 , 0.95257413 , 0.9933072 ], dtype=float32)>

看,𝑥中所有值都映射到了[0,1]范围内。

sigmoid优缺点总结:

  • 优点:输出的映射区间(0,1)内单调连续,非常适合用作输出层,并且比较容易求导。
  • 缺点:具有软饱和性,即当输入x趋向于无穷的时候,它的导数会趋于0,导致很容易产生梯度消失。
2、relu函数

Relu(Rectified Linear Units修正线性单元),是目前被使用最为频繁得激活函数,relu函数在x<0时,输出始终为0。由于x>0时,relu函数的导数为1,即保持输出为x,所以relu函数能够在x>0时保持梯度不断衰减,从而缓解梯度消失的问题,还能加快收敛速度,还能是神经网络具有稀疏性表达能力,这也是relu激活函数能够被使用在深层神经网络中的原因。由于当x<0时,relu函数的导数为0,导致对应的权重无法更新,这样的神经元被称为”神经元死亡”。

relu函数公式和图像如下:
fMAhbi
在TensorFlow中,relu函数的参数情况比sigmoid复杂,我们先来看一下:

1
tf.keras.activations.relu( x, alpha=0.0, max_value=None, threshold=0 )
  • x:输入的变量
  • alpha:上图中左半边部分图像的斜率,也就是x值为负数(准确说应该是小于threshold)部分的斜率,默认为0
  • max_value:最大值,当x大于max_value时,输出值为max_value
  • threshold:起始点,也就是上面图中拐点处x轴的值
    1
    2
    3
    x = tf.linspace(-5., 5.,6)
    x
    <tf.Tensor: id=9, shape=(6,), dtype=float32, numpy=array([-5., -3., -1., 1., 3., 5.], dtype=float32)>
    1
    2
    tf.keras.activations.relu(x)
    <tf.Tensor: id=10, shape=(6,), dtype=float32, numpy=array([0., 0., 0., 1., 3., 5.], dtype=float32)>
    1
    2
    tf.keras.activations.relu(x,alpha=2.)
    <tf.Tensor: id=11, shape=(6,), dtype=float32, numpy=array([-10., -6., -2., 1., 3., 5.], dtype=float32)>
    1
    2
    tf.keras.activations.relu(x,max_value=2.)  # 大于2部分都将输出为2.
    <tf.Tensor: id=16, shape=(6,), dtype=float32, numpy=array([0., 0., 0., 1., 2., 2.], dtype=float32)>
    1
    2
    tf.keras.activations.relu(x,alpha=2., threshold=3.5)  # 小于3.5的值按照alpha * (x - threshold)计算
    <tf.Tensor: id=27, shape=(6,), dtype=float32, numpy=array([-17., -13., -9., -5., -1., 5.], dtype=float32)>
3、softmax函数

softmax函数是sigmoid函数的进化,在处理分类问题是很方便,它可以将所有输出映射到成概率的形式,即值在[0,1]范围且总和为1。例如输出变量为[1.5,4.4,2.0],经过softmax函数激活后,输出为[0.04802413, 0.87279755, 0.0791784 ],分别对应属于1、2、3类的概率。softmax函数数学公式如下:
mgdmhg

1
2
3
tf.nn.softmax(tf.constant([[1.5,4.4,2.0]]))
<tf.Tensor: id=29, shape=(1, 3), dtype=float32, numpy=
array([[0.04802413, 0.87279755, 0.0791784 ]], dtype=float32)>
1
2
3
tf.keras.activations.softmax(tf.constant([[1.5,4.4,2.0]]))
<tf.Tensor: id=31, shape=(1, 3), dtype=float32, numpy=
array([[0.04802413, 0.87279755, 0.0791784 ]], dtype=float32)>
1
2
x = tf.random.uniform([1,5],minval=-2,maxval=2)
x
1
2
<tf.Tensor: id=38, shape=(1, 5), dtype=float32, numpy=
array([[ 1.9715171 , 0.49954653, -0.37836075, 1.6178164 , 0.80509186]] , dtype=float32)>
1
2
3
tf.keras.activations.softmax(x)
<tf.Tensor: id=39, shape=(1, 5), dtype=float32, numpy=
array([[0.42763966, 0.09813169, 0.04078862, 0.30023944, 0.13320053]] , dtype=float32)>
4、tanh函数

tanh函数无论是功能还是函数图像上斗鱼sigmoid函数十分相似,所以两者的优缺点也一样,区别在于tanh函数将值映射到[-1,1]范围,其数学公式和函数图像如下:

bu58hv

1
2
3
x = tf.linspace(-5., 5.,6)
x
<tf.Tensor: id=43, shape=(6,), dtype=float32, numpy=array([-5., -3., -1., 1., 3., 5.], dtype=float32)>
1
2
3
4
tf.keras.activations.tanh(x)
<tf.Tensor: id=44, shape=(6,), dtype=float32, numpy=
array([-0.99990916, -0.9950547 , -0.7615942 , 0.7615942 , 0.9950547 ,
0.99990916], dtype=float32)>

总结

神经网络中,隐藏层之间的输出大多需要通过激活函数来映射(当然,也可以不用,没有使用激活函数的层一般称为logits层),在构建模型是,需要根据实际数据情况选择激活函数。TensorFlow中的激活函数可不止这4个,本文只是介绍最常用的4个,当然,其他激活函数大多是这几个激活函数的变种。

模型构建

1
2
3
4
5
6
7
8
9
10
11
12
import tensorflow as tf
from tensorflow.keras import layers
print(tf.__version__)
print(tf.keras.__version__)

model = tf.keras.Sequential()
# 往模型中添加一个有64个神经元组成的层,激活函数为relu:
model.add(layers.Dense(64, activation='relu'))
# 再添加一个:
model.add(layers.Dense(64, activation='relu'))
# 添加一个有10个神经元的softmax层作为输出层:
model.add(layers.Dense(10, activation='softmax'))

等价于:

1
2
3
4
5
model = tf.keras.Sequential([
layers.Dense(64, activation='relu'),
layers.Dense(64, activation='relu'),
layers.Dense(10, activation='softmax')]
)

定义神经网络层通过tf.keras.layers模块中的Dense类实现,Dense类构造参数如下:

  • units:指定神经元个数,必须是一个正整数。
  • activation:激活函数,可以是可以是一个可调用对象或标识一个对象的字符串
  • use_bias:布尔型,是否使用是否使用偏置项
  • kernel_initializer和bias_initializer:权值、偏置初始化方法,可以是一个可调用对象或标识一个对象的字符串
  • kernel_regularizer和bias_regularizer:对权值、偏置进行正则化的方法,可以是一个可调用对象或标识一个对象的字符串
  • activity_regularizer:对层的输出进行正则化的方法,可以是一个可调用对象或标识一个对象的字符串
  • kernel_constraint和bias_constraint:对权值矩阵、偏置矩阵的约束方法,可以是一个可调用对象或标识一个对象的字符串

训练模型

建立好模型之后,接下来当然是要进行训练模型了。不过,在训练前还需要做一些配置工作,例如指定优化器、损失函数、评估指标等,这些配置参数的过程一般通过tf.keras.Model.compile方法进行,先来熟悉一下tf.keras.Model.compile方法的三个常用参数:

  • optimizer:tf.keras.optimizers模块中的优化器实例化对象,例如 tf.keras.optimizers.Adam或 tf.keras.optimizers.SGD的实例化对象,当然也可以使用字符串来指代优化器,例如’adam’和’sgd’。
  • loss:损失函数,例如交叉熵、均方差等,通常是tf.keras.losses模块中定义的可调用对象,也可以用用于指代损失函数的字符串。
  • metrics:元素为评估方法的list,通常是定义在tf.keras.metrics模块中定义的可调用对象,也可以用于指代评估方法的字符串。

在知道怎么配置模型训练参数后,就可以根据实际应用情况合理选择优化器、损失函数、评估方法等:

1
2
3
4
5
6
7
8
9
# 回归模型
model.compile(optimizer=tf.keras.optimizers.Adam(0.01), # 指定优化器,学习率为0.01
loss='mse', # 指定均方差作为损失函数
metrics=['mae']) # 添加绝对值误差作为评估方法

# 分类模型
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.01),
loss=tf.keras.losses.CategoricalCrossentropy(), # 分类模型多用交叉熵作为损失函数
metrics=[tf.keras.metrics.CategoricalAccuracy()])

通过compile()配置好模型后,就可以开始训练了。tf.keras中提供了fit()方法对模型进行训练,先来看看fit()方法的主要参数:

  • x和y:训练数据和目标数据
  • epochs:训练周期数,每一个周期都是对训练数据集的一次完整迭代
  • batch_size:簇的大小,一般在数据集是numpy数组类型时使用
  • validation_data:验证数据集,模型训练时,如果你想通过一个额外的验证数据集来监测模型的性能变换,就可以通过这个参数传入验证数据集
  • verbose:日志显示方式,verbose=0为不在标准输出流输出日志信息,verbose=1为输出进度条记录,verbose=2为每个epoch输出一行记录
  • callbacks:回调方法组成的列表,一般是定义在tf.keras.callbacks中的方法
  • validation_split:从训练数据集抽取部分数据作为验证数据集的比例,是一个0到1之间的浮点数。这一参数在输入数据为dataset对象、生成器、keras.utils.Sequence对象是无效。
  • shuffle:是否在每一个周期开始前打乱数据

下面分别说说如何使用fit()方法结合numpy数据和tf.data.Dataset数据进行模型训练。

1
2
3
4
5
6
import numpy as np

data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))

model.fit(data, labels, epochs=10, batch_size=32)

评估与预测

训练好的模型性能如何,评估测试一下就知道了。可以使用模型自带的evaluate()方法和predict()方法对模型进行评估和预测。

1
2
3
4
5
# 如果是numpy数据,可以这么使用
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))

model.evaluate(data, labels, batch_size=32)
1
2
3
4
5
# 如果数Dataset对象,可以这么使用
dataset = tf.data.Dataset.from_tensor_slices((data, labels))
dataset = dataset.batch(32)

model.evaluate(dataset)

使用predict()方法进行预测:

1
2
3
# numpy数据
result = model.predict(data, batch_size=32)
print(result.shape)
1
2
3
# dataset数据
result = model.predict(dataset)
print(result.shape)

traefik之docker-compose.yml

traefik 一般需要一个配置文件来管理路由,服务,证书等。我们可以通过 docker 启动 traefik 时来挂载配置文件,docker-compose.yaml 文件如下
traefik 默认有一个 dashboard,通过 :8080 端口暴露出去。我们可以在浏览器中直接通过 :8080 访问,但是

使用 IP 地址肯定不是特别方便,此时我们可以配置 Host
在公网环境下访问有安全性问题,此时可以配置 basicAuth,digestAuth,IpWhiteList 或者 openVPN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: '3'

services:
reverse-proxy:
image: traefik
ports:
- "52080:80"
- "52081:8080"
volumes:
- ./traefik.toml:/etc/traefik/traefik.toml
- /var/run/docker.sock:/var/run/docker.sock
container_name: traefik
labels:
- "traefik.http.routers.api.rule=Host(`www.hong.local`)"
- "traefik.http.routers.api.service=api@internal"

traefik.toml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
## Static configuration
[global]
checkNewVersion = true
sendAnonymousUsage = false

[entryPoints]
[entryPoints.http]
address = ":80"

[entryPoints.traefik]
address = ":8080"

[api]
insecure = true
dashboard = true
#debug = true


[providers]
[providers.docker]
endpoint = "unix:///var/run/docker.sock"
defaultRule = "Host(`{{ normalize .Name }}.docker.localhost`)"
# 限制服务发现范围
# 如果设置为 false, 则没有 traefik.enable=true 标签的容器将从生成的路由配置中忽略
exposedByDefault = false
#[providers.file]
# filename = "dynamic_conf.toml"
# watch = true
[metrics]
[metrics.prometheus]

whoami之docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
version: '3'

services:
whoami:
image: containous/whoami
labels:
# 声明公开此容器访问
- traefik.enable=true
# 服务将响应的域
- traefik.http.routers.whoami.rule=Host(`www.jun.local`)
networks:
default:
external:
name: traefik_default

那 whoami 这个 http 服务做了什么事情呢

暴露了一个 http 服务,主要提供一些 header 以及 ip 信息
配置了容器的 labels,设置该服务的 Host 为 whoami.docker.localhost,给 traefik 提供标记

0%