深度学习(6)--Keras项目详解

目录

一.项目介绍

二.项目流程详解

2.1.导入所需要的工具包

2.2.输入参数

2.3.获取图像路径并遍历读取数据

2.4.数据集的切分和标签转换 

2.5.网络模型构建

2.6.绘制结果曲线并将结果保存到本地

三.完整代码

四.首次运行结果

五.学习率对结果的影响

六.Dropout操作对结果的影响

七.权重初始化对结果的影响

7.1.RandomNormal

7.2.TruncatedNormal(推荐)

八.正则化对结果的影响

九.加载模型进行测试


一.项目介绍

用Keras工具包搭建训练自己的一个传统神经网络,用来识别猫/狗/羊三种图片。

数据集:

二.项目流程详解

2.1.导入所需要的工具包

# 导入所需要的工具包
# 将建模的结果画出来
import matplotlib
# 做标签,数据切分,展示结果的对比
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# keras工具包的操作
from keras.models import Sequential
from keras.layers import Dropout
# from keras.layers.core import Dense
from tensorflow.python.keras.layers.core import Dense
from keras.optimizers import SGD
from keras import initializers
from keras import regularizers
# 图像路径处理操作
from my_utlis import utlis_paths
# 一些基本库
import matplotlib.pyplot as plt
import numpy as np
import argparse
import random
import pickle
import cv2
import osos.environ["CUDA_VISIBLE_DEVICES"] = "0"

(1).如果只安装了keras工具包没安装cv2库,可以参考以下链接在Anaconda的虚拟环境中安装cv2库。

https://blog.csdn.net/u011204487/article/details/86497431icon-default.png?t=N7T8https://blog.csdn.net/u011204487/article/details/86497431

(2).如果 from keras.layers.core import Dense 显示此结果

可以将导入代码改为如下方式

from tensorflow.python.keras.layers.core import Dense

(3).在代码开头加入os.environ["CUDA_VISIBLE_DEVICES"] = "0"这行代码可以用gpu训练网络,“0”为可以使用的gpu编号,可以在cmd中输入nvidia -smi查询可用的gpu编号:

2.2.输入参数

# --dataset --model --label-bin --plot
# 输入参数
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,help="path to input dataset of images")
ap.add_argument("-m", "--model", required=True,help="path to output trained model")
ap.add_argument("-L", "--Label-bin", required=True,help="path to output label binarizer")
ap.add_argument("-p", "--plot", required=True,help="path to output accuracy/loss plot")
args = vars(ap.parse_args())

设置参数

右键项目点击修改运行配置

设置参数的值

设置好参数后在对应处创建文件夹

2.3.获取图像路径并遍历读取数据

# 获取图像数据路径,方便后续读取
imagePaths = sorted(list(utlis_paths.list_images('./dataset')))
random.seed(42)
random.shuffle(imagePaths)# 遍历读取数据
for imagePath in imagePaths:# 读取图像数据,后续步骤中使用了神经网络,需要将图像数据设置成一维image = cv2.imread(imagePath)  # cv2.imread方法读取数据image = cv2.resize(image, (32, 32)).flatten()  # 将读取的图片数据设置成相同的大小data.append(image)# 读取标签label = imagePath.split(os.path.sep)[-2]labels.append(label)# scale图像数据
data = np.array(data, dtype="float") / 255.0
labels = np.array(labels)

调用utlis_paths.list_images,获取路径的文件

通过from my_utlis import utlis_paths引入utlis_paths,所以需要在my_utlis文件夹中生成一个utlis_paths文件并在其中完成相应的函数定义:

import osimage_types = (".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff")def list_images(basePath, contains=None):# 返回有效的图片路径数据集return list_files(basePath, validExts=image_types, contains=contains)def list_files(basePath, validExts=None, contains=None):# 遍历图片数据目录,生成每张图片的路径for (rootDir, dirNames, filenames) in os.walk(basePath):# 循环遍历当前目录中的文件名for filename in filenames:# if the contains string is not none and the filename does not contain# the supplied string, then ignore the fileif contains is not None and filename.find(contains) == -1:continue# 通过确定.的位置,从而确定当前文件的文件扩展名ext = filename[filename.rfind("."):].lower()# 检查文件是否为图像,是否应进行处理if validExts is None or ext.endswith(validExts):# 构造图像路径imagePath = os.path.join(rootDir, filename)yield imagePath

指定一个随机种子,确保每次的切割相同,同时将数据洗牌,打乱数据 

random.seed(42)  # 指定随机种子
random.shuffle(imagePaths)  # 把数据重新洗牌,即将数据打乱

读取数据,并将所有的数据设置为统一规格

image = cv2.imread(imagePath)  # cv2.imread方法读取数据
image = cv2.resize(image, (32, 32)).flatten()  # 将读取的图片数据设置成相同的大小
data.append(image)  # append()函数向列表末尾添加一个元素

flatten()函数将图片参数拉长。

eg.32x32x3大小的图片,拉长为3072个像素点,即变为1x3072的矩阵

给读取出来的数据设置标签(读取数据和设置标签一般放在一起)

label = imagePath.split(os.path.sep)[-2]
labels.append(label)

scale归一化获得的图片数据,使得特征值在0~1之间浮动

# scale图像数据
data = np.array(data, dtype="float") / 255.0

2.4.数据集的切分和标签转换 

# 数据集切分
(trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.25, random_state=42)# 转换标签,one-hot格式
lb = LabelBinarizer()
trainY = lb.fit_transform(trainY)
testY = lb.transform(testY)

划分训练集和测试集:

(trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.25, random_state=42)

函数原型:

X_train, X_test, y_train, y_test = train_test_split(train_data, train_target, test_size, random_state, shuffle)

变量:
X_train:划分的训练集数据
X_test:划分的测试集数据
y_train:划分的训练集标签
y_test:划分的测试集标签
参数:
train_data:还未划分的数据集
train_target:还未划分的标签
test_size:分割比例,默认为0.25,即测试集占完整数据集的比例
random_state:随机数种子,应用于分割前对数据的洗牌。可以是int,RandomState实例或None,默认值=None。设成定值意味着,对于同一个数据集,只有第一次运行是随机的,随后多次分割只要rondom_state相同,则划分结果也相同。
shuffle:是否在分割前对完整数据进行洗牌(打乱),默认为True,打乱

转换标签:

lb = LabelBinarizer()
trainY = lb.fit_transform(trainY)
testY = lb.transform(testY)

最后得到的结果是对应三个动物种类狗、猫、羊的概率值,所以就应当有三个标签,需要对当前的标签进行转换,转换为满足要求的one-hot标签格式。

2.5.网络模型构建

# 网络模型结构 3072-512-256-3
model = Sequential()
# kernel_regularizer=regularizers.12(0.01)
# keras.initializers.TruncatedNormal(mean=0.0, stddex=0.05, seed=None)
# initializers.random_normal
# #model.add(Dropout(0.8))
model.add(keras.Input(shape=(3072,)))
model.add(Dense(512, activation="relu"))
model.add(Dense(256, activation="relu"))
model.add(Dense(len(lb.classes_), activation="softmax",))# 初始化参数
INIT_LR = 0.01
EPOCHS = 200# 给定损失函数和评估方法
print("[INFO] 准备训练网络...")
opt = SGD(lr=INIT_LR)
model.compile(loss="categorical_crossentropy", optimizer=opt,metrics=["accuracy"])# 训练网络模型
H = model.fit(trainX, trainY, validation_data=(testX,testY),epochs=EPOCHS, batch_size=32)# 测试网络模型
print("[INFO] 正在评估模型")
predictions = model.predict(testX, batch_size=32)
print(classification_report(testY.argmax(axis=1),predictions.argmax(axis=1), target_names=lb.classes_))

该网络模型的共有三层,初始特征值有3072个,由3072-512-256-3,最后得到对应三个图像类别的概率值。

设置模型的类型为Sequential :

model = Sequential()

对于Sequential模型的相关信息,可以查询下述keras的官方网站:

https://keras.io/guides/sequential_model/icon-default.png?t=N7T8https://keras.io/guides/sequential_model/

向神经网络中添加三层:

第一层:

model.add(keras.Input(shape=(3072,)))
model.add(Dense(512, activation="relu"))

首先第一层一般要通过Input(n,)函数告诉网络起始层有多少个神经元,然后512表示的是转换为下一层的神经元为512个,激活函数设置的是relu。

第二层:

model.add(Dense(256, activation="relu"))

经过这一层得到的下一层的神经元应当有256个,同时激活函数设置的为relu。

第三层:

model.add(Dense(len(lb.classes_), activation="softmax",))

经过这一层得到下一层的神经元个数为len(lb.classes_)的返回值,此处为3,同时激活函数为softmax,最后得到对应的不同类别的概率值。

初始化参数:

INIT_LR = 0.01
EPOCHS = 200

INIT_LR为学习率,EPOCHS为遍历整个数据集的次数

设置损失函数和评估方法:

opt = SGD(lr=INIT_LR)
model.compile(loss="categorical_crossentropy", optimizer=opt,metrics=["accuracy"])

SGD为随机梯度下降,将opt优化器设置为随机梯度下降,同时将学习率告诉SGD。

选择的损失函数为categorical_crossentropy,即为交叉熵损失函数 。

最后再获取accuracy准确率

训练网络模型:

H = model.fit(trainX, trainY, validation_data=(testX,testY),epochs=EPOCHS, batch_size=32)

测试网络模型:

print("[INFO] 正在评估模型")
predictions = model.predict(testX, batch_size=32)
print(classification_report(testY.argmax(axis=1),predictions.argmax(axis=1), target_names=lb.classes_)))

2.6.绘制结果曲线并将结果保存到本地

# 调试完成后,绘制结果曲线
N = np.arange(0, EPOCHS)
plt.style.use("ggplot")
plt.figure()
plt.plot(N, H.history["loss"], label="train_loss")
plt.plot(N, H.history["val_loss"], label="val_loss")
plt.plot(N, H.history["acc"], label="train_acc")
plt.plot(N, H.history["val_acc"], label="val_acc")
plt.title("Training Loss and Accuracy (Simple NN)")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend()
plt.savefig('./output/simple_nn_plot.png')   # 参数为保存的路径# 保存模型到本地
print("[INFO] 正在保存模型")
model.save(args["model"])
f = open('./output/simple_nn_lb.pickle', "wb")  # 保存标签数据
f.write(pickle.dumps(lb))
f.close()

对于acc参数,不同版本的keras对应的写法不同,如果引入acc和val_acc报错,可以尝试改为accuracy和val_accuracy,反之亦然。

三.完整代码

项目结构:

nn_train.py:

# 导入所需要的工具包
# 将建模的结果画出来
import keras
import matplotlib
# 做标签,数据切分,展示结果的对比
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# keras工具包的操作
from keras.models import Sequential
from keras.layers import Dropout
# from keras.layers.core import Dense
from tensorflow.python.keras.layers.core import Dense
from keras.optimizers import SGD
from keras import initializers
from keras import regularizers
# 图像路径处理操作
from my_utlis import utlis_paths
# 一些基本库
import matplotlib.pyplot as plt
import numpy as np
import argparse
import random
import pickle
import cv2
import os# --dataset --model --label-bin --plot
# 输入参数
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,help="path to input dataset of images")
ap.add_argument("-m", "--model", required=True,help="path to output trained model")
ap.add_argument("-L", "--Label-bin", required=True,help="path to output label binarizer")
ap.add_argument("-p", "--plot", required=True,help="path to output accuracy/loss plot")
args = vars(ap.parse_args())print("[INFO] 开始读取数据")
data = []
labels = []# 获取图像数据路径,方便后续读取
imagePaths = sorted(list(utlis_paths.list_images('./dataset')))
random.seed(42)  # 指定随机种子
random.shuffle(imagePaths)  # 把数据重新洗牌,即将数据打乱# 遍历读取数据
for imagePath in imagePaths:# 读取图像数据,后续步骤中使用了神经网络,需要将图像数据设置成一维image = cv2.imread(imagePath)  # cv2.imread方法读取数据image = cv2.resize(image, (32, 32)).flatten()  # 将读取的图片数据设置成相同的大小data.append(image)# 读取标签label = imagePath.split(os.path.sep)[-2]labels.append(label)# scale图像数据
data = np.array(data, dtype="float") / 255.0
labels = np.array(labels)# 数据集切分
(trainX, testX, trainY, testY) = train_test_split(data,labels, test_size=0.25, random_state=42)# 转换标签,one-hot格式
lb = LabelBinarizer()
trainY = lb.fit_transform(trainY)
testY = lb.transform(testY)# 网络模型结构 3072-512-256-3
model = Sequential()
# kernel_regularizer=regularizers.12(0.01)
# keras.initializers.TruncatedNormal(mean=0.0, stddex=0.05, seed=None)
# initializers.random_normal
# #model.add(Dropout(0.8))
model.add(keras.Input(shape=(3072,)))
model.add(Dense(512, activation="relu"))
model.add(Dense(256, activation="relu"))
model.add(Dense(len(lb.classes_), activation="softmax",))# 初始化参数
INIT_LR = 0.01
EPOCHS = 200# 给定损失函数和评估方法
print("[INFO] 准备训练网络...")
opt = SGD(lr=INIT_LR)
model.compile(loss="categorical_crossentropy", optimizer=opt,metrics=["accuracy"])# 训练网络模型
H = model.fit(trainX, trainY, validation_data=(testX,testY),epochs=EPOCHS, batch_size=32)# 测试网络模型
print("[INFO] 正在评估模型")
predictions = model.predict(testX, batch_size=32)
print(classification_report(testY.argmax(axis=1),predictions.argmax(axis=1), target_names=lb.classes_))# 调试完成后,绘制结果曲线
N = np.arange(0, EPOCHS)
plt.style.use("ggplot")
plt.figure()
plt.plot(N, H.history["loss"], label="train_loss")
plt.plot(N, H.history["val_loss"], label="val_loss")
plt.plot(N, H.history["accuracy"], label="train_acc")
plt.plot(N, H.history["val_accuracy"], label="val_acc")
plt.title("Training Loss and Accuracy (Simple NN)")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend()
plt.savefig('./output/simple_nn_plot.png')   # 参数为保存的路径# 保存模型到本地
print("[INFO] 正在保存模型")
model.save(args["model"])
f = open('./output/simple_nn_lb.pickle', "wb")  # 保存标签数据
f.write(pickle.dumps(lb))
f.close()

utlis_paths.py:

import osimage_types = (".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff")def list_images(basePath, contains=None):# 返回有效的图片路径数据集return list_files(basePath, validExts=image_types, contains=contains)def list_files(basePath, validExts=None, contains=None):# 遍历图片数据目录,生成每张图片的路径for (rootDir, dirNames, filenames) in os.walk(basePath):# 循环遍历当前目录中的文件名for filename in filenames:# if the contains string is not none and the filename does not contain# the supplied string, then ignore the fileif contains is not None and filename.find(contains) == -1:continue# 通过确定.的位置,从而确定当前文件的文件扩展名ext = filename[filename.rfind("."):].lower()# 检查文件是否为图像,是否应进行处理if validExts is None or ext.endswith(validExts):# 构造图像路径imagePath = os.path.join(rootDir, filename)yield imagePath

四.首次运行结果

相关参数介绍参考文章:

https://blog.csdn.net/weixin_48964486/article/details/122881350

在训练集上的accuracy为1.0,与测试集上的accuracy差距过大,可能出现过拟合现象。

五.学习率对结果的影响

初始学习率为0.01(学习率过大可能产生过拟合现象)

将学习率改为0.001:

# 初始化参数
INIT_LR = 0.001
EPOCHS = 200

训练结果:

仍有过拟合现象,但是相较于学习率lr=0.01的情况略有改善。

六.Dropout操作对结果的影响

The Dropout layer randomly sets input units to 0 with a frequency of rate at each step during training time, which helps prevent overfitting

Dropout layer (keras.io)icon-default.png?t=N7T8https://keras.io/api/layers/regularization_layers/dropout/

添加Drop-out操作:

一般添加在全连接层中

from keras.layers import Dropoutmodel.add(keras.Input(shape=(3072,)))
model.add(Dense(512, activation="relu"))
model.add(Dropout(0.5))
model.add(Dense(256, activation="relu"))
model.add(Dropout(0.5))
model.add(Dense(len(lb.classes_), activation="softmax",))

Dropout=0.5,LR=0.001的训练结果:

从结果可以看出,添加Dropout层可以有效避免过拟合现象的出现。

七.权重初始化对结果的影响

查询不同的初始化方法:

Layer weight initializers (keras.io)icon-default.png?t=N7T8https://keras.io/api/layers/initializers/查看全连接层的参数设置发现,如果不初始化kernel_initializer,起默认的参数为'glorot_uniform',即正态分布初始化,常常不能满足训练的要求。

7.1.RandomNormal

将kernel_initializer设置为‘RandomNormal’,即高斯正太分布:

from keras import initializersmodel.add(keras.Input(shape=(3072,)))
model.add(Dense(512, activation="relu", kernel_initializer=keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=None)))
# model.add(Dropout(0.5))
model.add(Dense(256, activation="relu", kernel_initializer=keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=None)))
# model.add(Dropout(0.5))
model.add(Dense(len(lb.classes_), activation="softmax", kernel_initializer=keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=None)))

其中mean为均值,stddev为标准差。

正太高斯分布初始化,不使用Dropout层,LR=0.001的训练结果:

7.2.TruncatedNormal(推荐)

将kernel_initializer设置为‘TruncatedNormal’,即截断正太分布:

model.add(keras.Input(shape=(3072,)))
model.add(Dense(512, activation="relu", kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.05, seed=None)))
# model.add(Dropout(0.5))
model.add(Dense(256, activation="relu", kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.05, seed=None)))
# model.add(Dropout(0.5))
model.add(Dense(len(lb.classes_), activation="softmax", kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.05, seed=None)))

其中mean为均值,stddev为标准差。

截断正太分布初始化,不使用Dropout层,LR=0.001的训练结果:

在此基础上再加上Dropout层的结果:

八.正则化对结果的影响

Regularizers allow you to apply penalties on layer parameters or layer activity during optimization. These penalties are summed into the loss function that the network optimizes.

Layer weight regularizers (keras.io)icon-default.png?t=N7T8https://keras.io/api/layers/regularizers/

 在全连接层添加正则化:

from keras import regularizersmodel.add(keras.Input(shape=(3072,)))
model.add(Dense(512, activation="relu", kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.05, seed=None), kernel_regularizer=regularizers.L2(0.01)))
model.add(Dropout(0.5))
model.add(Dense(256, activation="relu", kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.05, seed=None), kernel_regularizer=regularizers.L2(0.01)))
model.add(Dropout(0.5))
model.add(Dense(len(lb.classes_), activation="softmax", kernel_initializer=keras.initializers.TruncatedNormal(mean=0.0, stddev=0.05, seed=None), kernel_regularizer=regularizers.L2(0.01)))

有两种正则化方法,L1为取绝对值,L2是求权重的欧几里得范数(常用L2),括号里的参数为惩罚力度\lambda(越大的惩罚力度,过拟合的风险越低)。

惩罚力度为0.01正则化,截断正态分布初始化,加入Dropout=0.5,LR=0.001的训练结果:

惩罚力度为0.1正则化,截断正态分布初始化,加入Dropout=0.5,LR=0.001的训练结果:

九.加载模型进行测试

保存模型到本地:

保存的模型:惩罚力度为0.1正则化,截断正态分布初始化,加入Dropout=0.5,LR=0.001,EPOCHS=1000.

# 保存模型到本地
print("[INFO] 正在保存模型")
model.save(args["model"])
f = open('./output/simple_nn_lb.pickle', "wb")  # 保存标签数据
f.write(pickle.dumps(lb))
f.close()

 

编写一个predict.py程序来加载模型进行测试:

# 导入所需工具包
from keras.models import load_model
import argparse
import pickle
import cv2# 加载测试数据并进行相同预处理操作
image = cv2.imread('./cs_image/dog.jpeg')  # 读取一张图片进行测试 dog/cat/sheet
output = image.copy()  # 复制图片的一份副本给output
image = cv2.resize(image, (32, 32))# scale图像数据
image = image.astype("float") / 255.0# 对图像进行拉平操作
image = image.flatten()
image = image.reshape((1, image.shape[0]))# 读取模型和标签
print("------读取模型和标签------")
model = load_model('./output/simple_nn.model')  # 设置模型
lb = pickle.loads(open('./output/simple_nn_lb.pickle', "rb").read())  # 设置标签# 预测
preds = model.predict(image)# 得到预测结果以及其对应的标签
i = preds.argmax(axis=1)[0]
label = lb.classes_[i]# 在图像中把结果画出来
text = "{}: {:.2f}%".format(label, preds[0][i] * 100)
cv2.putText(output, text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7,(0, 0, 255), 2)# 绘图
cv2.imshow("Image", output)
cv2.waitKey(0)

若出现下述报错

error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Cocoa support.

在对应的虚拟环境中安装OpenCV的拓展开发包即可解决

pip install opencv-contrib-python -i https://pypi.tuna.tsinghua.edu.cn/simple/

测试的结果:

发现对于猫的预测结果不准确,对于图片的预测,一般会用到卷积神经网络而不是本项目中构建的传统神经网络。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/651823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一个基于electron自动化桌面应用-流程图构建

前期工作已搞定,现在可以搭建桌面应用了。这个阶段可以结合前面定义好的数据格式构建流程图。 模板 还是使用熟悉的技术栈vite react electron,模板 流程图 官方文档 自定义 节点样式 因为配置化的操作类型较多,因此可以利用自定义节…

【开源】基于JAVA语言的就医保险管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 科室档案模块2.2 医生档案模块2.3 预约挂号模块2.4 我的挂号模块 三、系统展示四、核心代码4.1 用户查询全部医生4.2 新增医生4.3 查询科室4.4 新增号源4.5 预约号源 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVue…

在JavaScript中创建自定义错误

🧑‍🎓 个人主页:《爱蹦跶的大A阿》 🔥当前正在更新专栏:《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ 目录 ✨ 前言 ✨ 正文 简介 创建自定义错误 自定义错误属性 instanceof 检…

STM正点mini-跑马灯

一.库函数版 1.硬件连接 GPIO的输出方式:推挽输出 IO口输出为高电平时,P-MOS置高,输出为1,LED对应引脚处为高电平,而二极管正&#…

N-141基于springboot,vue网上拍卖平台

开发工具:IDEA 服务器:Tomcat9.0, jdk1.8 项目构建:maven 数据库:mysql5.7 系统分前后台,项目采用前后端分离 前端技术:vueelementUI 服务端技术:springbootmybatis-plusredi…

虚拟局域网、广播域、冲突域

目录 广播风暴 安全问题 虚拟局域网 VLAN 虚拟局域网优点 划分虚拟局域网的方法 基于交换机端口的方法 基于计算机网卡的 MAC 地址的方法 基于协议类型的方法 基于 IP 子网地址的方法 基于高层应用或服务的方法 虚拟局域网使用的以太网帧格式 以太网存在的主要问题&…

STM32+ESP8266 实现物联网设备节点

一、硬件准备 本设备利用STM32F103ZE和ESP8266实现了一个基本的物联网节点,所需硬件如下 1、STM32F103ZE开发板 2、ESP8266模组(uart接口) 3、ST-LINK(下载用) 4、USB转串口模块(调试用) 二…

matplotlib 波士顿房价数据及可视化 Tensorflow 2.4.0

matplotlib 波士顿房价数据及可视化 Tensorflow 2.4.0 目录 matplotlib 波士顿房价数据及可视化 Tensorflow 2.4.0 1. 认识 1.1 kears 1.2 kears常用数据集 2. 波士顿房价数据及可视化 2.1 下载波士顿房价数据集 2.2 展示一个属性对房价的影响 2.3 将是三个属性全部展…

CTF CRYPTO 密码学-6

题目名称:敲击 题目描述: 方方格格,不断敲击 “wdvtdz qsxdr werdzxc esxcfr uygbn” 解题过程: step1:根据题目描述敲击,wdvtdz对应的字符为x step2:依此类推r,z,o&…

【现代密码学基础】详解完美安全与香农定理

目录 一. 介绍 二. 完美安全的密钥与消息空间 三. 完美安全的密钥长度 四. 最优的完美安全方案 五. 香农定理 (1)理论分析 (2)严格的正向证明 (3)严格的反向证明 六. 小结 一. 介绍 一次一密方案…

【GitHub项目推荐--不错的 TypeScript 学习项目】【转载】

在线白板工具 Excalidraw 标星 33k,是一款非常轻量的在线白板工具,可以直接在浏览器打开,轻松绘制具有手绘风格的图形。 如下图所示,Excalidraw 支持最常用的图形元素:方框、圆、菱形、线,可以方便的使用…

CSS设置单行文字水平垂直居中的方法

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>单行文字水平垂直居中</title><style>div {/* 给div设置宽高 */width: 400px;height: 200px;margin: 100px auto;background-color: red;/…

NoSQL基本内容

第一章 NoSQL 1.1 什么是NoSQL NoSQL&#xff08;Not Only SQL&#xff09;即不仅仅是SQL&#xff0c;泛指非关系型的数据库&#xff0c;它可以作为关系型数据库的良好补充。随着互联网web2.0网站的兴起&#xff0c;非关系型的数据库现在成了一个极其热门的新领域&#xff0c;…

(免费领源码)java#Springboot#mysql旅游景点订票系统68524-计算机毕业设计项目选题推荐

摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#xff0c;应用软件的工作…

网络安全02--负载均衡下的webshell连接

目录 一、环境准备 1.1ubentu虚拟机一台&#xff0c;docker环境&#xff0c;蚁剑 1.2环境压缩包&#xff08;文件已上传资源&#xff09;&#xff1a; 二、开始复原 2.1上传ubentu&#xff1a; 2.2解压缩 2.3版本20没有docker-compose手动下载&#xff0c;包已上传资源 …

人类基因组计划发现的8大真相

人类基因组计划是科学史上重要的里程碑事情。该计划的成功&#xff0c;不仅开启了人类了解自身的旅程&#xff0c;而且成为了国际科技合作的典范。对于人类基因组&#xff0c;发现了以下 8 个事实。 1. 人类基因组约有 20300 个蛋白质编码基因。这与最初预估的 30000 ~ 40000 个…

pytest教程-7-用例前后置方法

上一小节&#xff0c;我们学习了pytest跳过测试用例的方法&#xff0c;本小节我们讲解一下pytest用例的前后置方法。 在unittest中就有前置setup和后置teardown来处理测试用例执行前的准备工作&#xff08;浏览器驱动实例化&#xff0c;数据库连接等&#xff09;以及执行后的处…

JS之隐式转换与布尔判定

大家思考一下 [ ] [ ] &#xff1f; 答案是空字符串 为什么呢&#xff1f; 当做加法运算的时候&#xff0c;发现左右两端存在非原始类型&#xff0c;也就是引用类型对象&#xff0c;就会对对象做隐式类型转换 如何执行的&#xff1f;或者说怎么查找的&#xff1f; 第一步&…

IntelliJ IDE 插件开发 | (五)VFS 与编辑器

系列文章 IntelliJ IDE 插件开发 |&#xff08;一&#xff09;快速入门IntelliJ IDE 插件开发 |&#xff08;二&#xff09;UI 界面与数据持久化IntelliJ IDE 插件开发 |&#xff08;三&#xff09;消息通知与事件监听IntelliJ IDE 插件开发 |&#xff08;四&#xff09;来查收…

【GitHub项目推荐--不错的 React 开源项目】【转载】

用 React Flow 连接你的想法 用 React Flow 连接你的想法&#xff0c;这是一个高度可定制的库&#xff0c;基于 React 用于构建基于节点的 交互式 UI、编辑器、流程图和图表。 开源地址&#xff1a;https://github.com/wbkd/react-flow Bulletproof React 一个简单、可扩展且…