Tensorflow实现深度学习8:猫狗识别

本文为为🔗365天深度学习训练营内部文章

原作者:K同学啊

 一 导入数据

import matplotlib.pyplot as plt
import tensorflow as tf
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号import os,PIL,pathlib#隐藏警告
import warnings
warnings.filterwarnings('ignore')data_dir = "./data"
data_dir = pathlib.Path(data_dir)image_count = len(list(data_dir.glob('*/*')))print("图片总数为:",image_count)
图片总数为: 3400

二、数据预处理

1. 加载数据

使用image_dataset_from_directory方法将磁盘中的数据加载到tf.data.Dataset

batch_size = 8
img_height = 224
img_width = 224
train_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split=0.2,subset="training",seed=12,image_size=(img_height, img_width),batch_size=batch_size)
Found 3400 files belonging to 2 classes.
Using 2720 files for training.
val_ds = tf.keras.preprocessing.image_dataset_from_directory(data_dir,validation_split=0.2,subset="validation",seed=12,image_size=(img_height, img_width),batch_size=batch_size)
Found 3400 files belonging to 2 classes.
Using 680 files for validation.
class_names = train_ds.class_names
print(class_names)
['cat', 'dog']

2. 再次检查数据 

for image_batch, labels_batch in train_ds:print(image_batch.shape)print(labels_batch.shape)break
(8, 224, 224, 3)
(8,)

3. 配置数据集

  • shuffle() : 打乱数据
  • prefetch() :预取数据,加速运行
  • cache() :将数据集缓存到内存当中,加速运行
AUTOTUNE = tf.data.AUTOTUNEdef preprocess_image(image,label):return (image/255.0,label)# 归一化处理
train_ds = train_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
val_ds   = val_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds   = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

 在这里数据处理的过程中,比前几次稍微不同的是多加了一个归一化的处理

4.可视化数据 

plt.figure(figsize=(15, 10))  # 图形的宽为15高为10for images, labels in train_ds.take(1):for i in range(8):ax = plt.subplot(5, 8, i + 1) plt.imshow(images[i])plt.title(class_names[labels[i]])plt.axis("off")

三、构建VG-16网络

VGG优缺点分析:

  • VGG优点

VGG的结构非常简洁,整个网络都使用了同样大小的卷积核尺寸(3x3)和最大池化尺寸(2x2)。

  • VGG缺点

1)训练时间过长,调参难度大。2)需要的存储容量大,不利于部署。例如存储VGG-16权重值文件的大小为500多MB,不利于安装到嵌入式系统中。

结构说明:

  • 13个卷积层(Convolutional Layer),分别用blockX_convX表示
  • 3个全连接层(Fully connected Layer),分别用fcXpredictions表示
  • 5个池化层(Pool layer),分别用blockX_pool表示

VGG-16包含了16个隐藏层(13个卷积层和3个全连接层),故称为VGG-16

 

构建方法1:调用官网封装好的模型函数 

model = tf.keras.applications.VGG16(weights='imagenet')
model.summary()
Model: "vgg16"
_________________________________________________________________Layer (type)                Output Shape              Param #   
=================================================================input_1 (InputLayer)        [(None, 224, 224, 3)]     0         block1_conv1 (Conv2D)       (None, 224, 224, 64)      1792      block1_conv2 (Conv2D)       (None, 224, 224, 64)      36928     block1_pool (MaxPooling2D)  (None, 112, 112, 64)      0         block2_conv1 (Conv2D)       (None, 112, 112, 128)     73856     block2_conv2 (Conv2D)       (None, 112, 112, 128)     147584    block2_pool (MaxPooling2D)  (None, 56, 56, 128)       0         block3_conv1 (Conv2D)       (None, 56, 56, 256)       295168    block3_conv2 (Conv2D)       (None, 56, 56, 256)       590080    block3_conv3 (Conv2D)       (None, 56, 56, 256)       590080    block3_pool (MaxPooling2D)  (None, 28, 28, 256)       0         block4_conv1 (Conv2D)       (None, 28, 28, 512)       1180160   block4_conv2 (Conv2D)       (None, 28, 28, 512)       2359808   block4_conv3 (Conv2D)       (None, 28, 28, 512)       2359808   block4_pool (MaxPooling2D)  (None, 14, 14, 512)       0         block5_conv1 (Conv2D)       (None, 14, 14, 512)       2359808   block5_conv2 (Conv2D)       (None, 14, 14, 512)       2359808   block5_conv3 (Conv2D)       (None, 14, 14, 512)       2359808   block5_pool (MaxPooling2D)  (None, 7, 7, 512)         0         flatten (Flatten)           (None, 25088)             0         fc1 (Dense)                 (None, 4096)              102764544 fc2 (Dense)                 (None, 4096)              16781312  predictions (Dense)         (None, 1000)              4097000   =================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________

构建方法二:自己手动搭建模型 

from tensorflow.keras import layers, models, Input
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropoutdef VGG16(nb_classes, input_shape):input_tensor = Input(shape=input_shape)# 1st blockx = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv1')(input_tensor)x = Conv2D(64, (3,3), activation='relu', padding='same',name='block1_conv2')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block1_pool')(x)# 2nd blockx = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv1')(x)x = Conv2D(128, (3,3), activation='relu', padding='same',name='block2_conv2')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block2_pool')(x)# 3rd blockx = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv1')(x)x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv2')(x)x = Conv2D(256, (3,3), activation='relu', padding='same',name='block3_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block3_pool')(x)# 4th blockx = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv1')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv2')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block4_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block4_pool')(x)# 5th blockx = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv1')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv2')(x)x = Conv2D(512, (3,3), activation='relu', padding='same',name='block5_conv3')(x)x = MaxPooling2D((2,2), strides=(2,2), name = 'block5_pool')(x)# full connectionx = Flatten()(x)x = Dense(4096, activation='relu',  name='fc1')(x)x = Dense(4096, activation='relu', name='fc2')(x)output_tensor = Dense(nb_classes, activation='softmax', name='predictions')(x)model = Model(input_tensor, output_tensor)return modelmodel=VGG16(1000, (img_width, img_height, 3))
model.summary()
Model: "model"
_________________________________________________________________Layer (type)                Output Shape              Param #   
=================================================================input_1 (InputLayer)        [(None, 224, 224, 3)]     0         block1_conv1 (Conv2D)       (None, 224, 224, 64)      1792      block1_conv2 (Conv2D)       (None, 224, 224, 64)      36928     block1_pool (MaxPooling2D)  (None, 112, 112, 64)      0         block2_conv1 (Conv2D)       (None, 112, 112, 128)     73856     block2_conv2 (Conv2D)       (None, 112, 112, 128)     147584    block2_pool (MaxPooling2D)  (None, 56, 56, 128)       0         block3_conv1 (Conv2D)       (None, 56, 56, 256)       295168    block3_conv2 (Conv2D)       (None, 56, 56, 256)       590080    block3_conv3 (Conv2D)       (None, 56, 56, 256)       590080    block3_pool (MaxPooling2D)  (None, 28, 28, 256)       0         block4_conv1 (Conv2D)       (None, 28, 28, 512)       1180160   block4_conv2 (Conv2D)       (None, 28, 28, 512)       2359808   block4_conv3 (Conv2D)       (None, 28, 28, 512)       2359808   block4_pool (MaxPooling2D)  (None, 14, 14, 512)       0         block5_conv1 (Conv2D)       (None, 14, 14, 512)       2359808   block5_conv2 (Conv2D)       (None, 14, 14, 512)       2359808   block5_conv3 (Conv2D)       (None, 14, 14, 512)       2359808   block5_pool (MaxPooling2D)  (None, 7, 7, 512)         0         flatten (Flatten)           (None, 25088)             0         fc1 (Dense)                 (None, 4096)              102764544 fc2 (Dense)                 (None, 4096)              16781312  predictions (Dense)         (None, 1000)              4097000   =================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________

四、编译

在准备对模型进行训练之前,还需要再对其进行一些设置。以下内容是在模型的编译步骤中添加的:

  • 损失函数(loss):用于衡量模型在训练期间的准确率。
  • 优化器(optimizer):决定模型如何根据其看到的数据和自身的损失函数进行更新。
  • 评价函数(metrics):用于监控训练和测试步骤。以下示例使用了准确率,即被正确分类的图像的比率。

 

# 设置初始学习率
initial_learning_rate = 1e-4lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(initial_learning_rate, decay_steps=30,      # 敲黑板!!!这里是指 steps,不是指epochsdecay_rate=0.92,     # lr经过一次衰减就会变成 decay_rate*lrstaircase=True)# 设置优化器
opt = tf.keras.optimizers.Adam(learning_rate=initial_learning_rate)model.compile(optimizer=opt,loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['accuracy'])

 早停法:

from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStoppingepochs = 10# 保存最佳模型参数
checkpointer = ModelCheckpoint('best_model.h5',monitor='val_accuracy',verbose=1,save_best_only=True,save_weights_only=True)# 设置早停
earlystopper = EarlyStopping(monitor='val_accuracy', min_delta=0.001,patience=20, verbose=1)

五、训练模型

history = model.fit(train_ds,validation_data=val_ds,epochs=epochs,callbacks=[checkpointer, earlystopper])
Epoch 1/10
340/340 [==============================] - ETA: 0s - loss: 0.2396 - accuracy: 0.8930
Epoch 1: val_accuracy improved from -inf to 0.99412, saving model to best_model.h5
340/340 [==============================] - 1376s 4s/step - loss: 0.2396 - accuracy: 0.8930 - val_loss: 0.0210 - val_accuracy: 0.9941
Epoch 2/10
340/340 [==============================] - ETA: 0s - loss: 0.0276 - accuracy: 0.9908
Epoch 2: val_accuracy did not improve from 0.99412
340/340 [==============================] - 1345s 4s/step - loss: 0.0276 - accuracy: 0.9908 - val_loss: 0.0465 - val_accuracy: 0.9853
Epoch 3/10
340/340 [==============================] - ETA: 0s - loss: 0.1150 - accuracy: 0.9717
Epoch 3: val_accuracy did not improve from 0.99412
340/340 [==============================] - 1316s 4s/step - loss: 0.1150 - accuracy: 0.9717 - val_loss: 0.0704 - val_accuracy: 0.9750
Epoch 4/10
340/340 [==============================] - ETA: 0s - loss: 0.0192 - accuracy: 0.9949
Epoch 4: val_accuracy improved from 0.99412 to 0.99853, saving model to best_model.h5
340/340 [==============================] - 1336s 4s/step - loss: 0.0192 - accuracy: 0.9949 - val_loss: 0.0083 - val_accuracy: 0.9985
Epoch 5/10
340/340 [==============================] - ETA: 0s - loss: 0.0248 - accuracy: 0.9930
Epoch 5: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1321s 4s/step - loss: 0.0248 - accuracy: 0.9930 - val_loss: 0.0036 - val_accuracy: 0.9985
Epoch 6/10
340/340 [==============================] - ETA: 0s - loss: 0.0240 - accuracy: 0.9937
Epoch 6: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1323s 4s/step - loss: 0.0240 - accuracy: 0.9937 - val_loss: 0.0074 - val_accuracy: 0.9956
Epoch 7/10
340/340 [==============================] - ETA: 0s - loss: 0.0039 - accuracy: 0.9982
Epoch 7: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1324s 4s/step - loss: 0.0039 - accuracy: 0.9982 - val_loss: 0.0069 - val_accuracy: 0.9971
Epoch 8/10
340/340 [==============================] - ETA: 0s - loss: 8.3202e-04 - accuracy: 1.0000
Epoch 8: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1318s 4s/step - loss: 8.3202e-04 - accuracy: 1.0000 - val_loss: 0.0205 - val_accuracy: 0.9956
Epoch 9/10
340/340 [==============================] - ETA: 0s - loss: 0.0759 - accuracy: 0.9801
Epoch 9: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1326s 4s/step - loss: 0.0759 - accuracy: 0.9801 - val_loss: 0.0372 - val_accuracy: 0.9882
Epoch 10/10
340/340 [==============================] - ETA: 0s - loss: 0.0242 - accuracy: 0.9934
Epoch 10: val_accuracy did not improve from 0.99853
340/340 [==============================] - 1328s 4s/step - loss: 0.0242 - accuracy: 0.9934 - val_loss: 0.0072 - val_accuracy: 0.9985

六 模型评估 

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']loss = history.history['loss']
val_loss = history.history['val_loss']epochs_range = range(epochs)plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

预测 

import numpy as np# 采用加载的模型(new_model)来看预测结果
plt.figure(figsize=(18, 3))  # 图形的宽为18高为5
plt.suptitle("预测结果展示")for images, labels in val_ds.take(1):for i in range(8):ax = plt.subplot(1,8, i + 1)  # 显示图片plt.imshow(images[i].numpy())# 需要给图片增加一个维度img_array = tf.expand_dims(images[i], 0) # 使用模型预测图片中的人物predictions = model.predict(img_array)plt.title(class_names[np.argmax(predictions)])plt.axis("off")
1/1 [==============================] - 1s 609ms/step
1/1 [==============================] - 0s 123ms/step
1/1 [==============================] - 0s 140ms/step
1/1 [==============================] - 0s 134ms/step
1/1 [==============================] - 0s 129ms/step
1/1 [==============================] - 0s 126ms/step
1/1 [==============================] - 0s 124ms/step
1/1 [==============================] - 0s 123ms/step

 

在训练模型的时候,除了用上述的代码之外,还可以用另一种方式。

改用model.train_on_batch方法。两种方法的比较:

  • model.fit():用起来十分简单,对新手非常友好
  • model.train_on_batch():封装程度更低,可以玩更多花样。

此外我也引入了进度条的显示方式,更加方便我们及时查看模型训练过程中的情况,可以及时打印各项指标

 

model.compile(optimizer="adam",loss     ='sparse_categorical_crossentropy',metrics  =['accuracy'])
from tqdm import tqdm
import tensorflow.keras.backend as Kepochs = 10
lr     = 1e-4# 记录训练数据,方便后面的分析
history_train_loss     = []
history_train_accuracy = []
history_val_loss       = []
history_val_accuracy   = []for epoch in range(epochs):train_total = len(train_ds)val_total   = len(val_ds)"""total:预期的迭代数目ncols:控制进度条宽度mininterval:进度更新最小间隔,以秒为单位(默认值:0.1)"""with tqdm(total=train_total, desc=f'Epoch {epoch + 1}/{epochs}',mininterval=1,ncols=100) as pbar:lr = lr*0.92K.set_value(model.optimizer.lr, lr)for image,label in train_ds:   """训练模型,简单理解train_on_batch就是:它是比model.fit()更高级的一个用法想详细了解 train_on_batch 的同学,可以看看我的这篇文章:https://www.yuque.com/mingtian-fkmxf/hv4lcq/ztt4gy"""history = model.train_on_batch(image,label)train_loss     = history[0]train_accuracy = history[1]pbar.set_postfix({"loss": "%.4f"%train_loss,"accuracy":"%.4f"%train_accuracy,"lr": K.get_value(model.optimizer.lr)})pbar.update(1)history_train_loss.append(train_loss)history_train_accuracy.append(train_accuracy)print('开始验证!')with tqdm(total=val_total, desc=f'Epoch {epoch + 1}/{epochs}',mininterval=0.3,ncols=100) as pbar:for image,label in val_ds:      history = model.test_on_batch(image,label)val_loss     = history[0]val_accuracy = history[1]pbar.set_postfix({"loss": "%.4f"%val_loss,"accuracy":"%.4f"%val_accuracy})pbar.update(1)history_val_loss.append(val_loss)history_val_accuracy.append(val_accuracy)print('结束验证!')print("验证loss为:%.4f"%val_loss)print("验证准确率为:%.4f"%val_accuracy)

 ​​​​​

 对比之前的model.fit()方法,这次还引用了更详细的进度条。后续的操作和上述方法一样

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

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

相关文章

本地部署Xinference实现智能体推理工作流(二)

第二篇章 Dify接入 Xinference 部署的本地模型 1. 安装Dify 克隆 Dify 源代码至本地。 git clone https://github.com/langgenius/dify.git 2. 启动Dify 进入 Dify 源代码的 docker 目录,执行一键启动命令: cd dify/docker cp .env.example .env d…

Linux学习(15)-网络编程:滑动窗口、拥塞控制、udp

本节学习内容 1.滑动窗口(1.滑动窗口的作用2.如果如果接收端填充的接收窗口为0,发送端接下来怎么处理3.糊涂窗口综合征4.tcp中nagle算法是什么) 2.拥塞控制 3.udp协议特点及编程流程 本节可能会用到的指令 ifconfig查看自己的ip地址 pi…

Amazon Bedrock 实践:零基础创建贪吃蛇游戏

本文探讨了如何利用 Amazon Bedrock 和大型语言模型,快速创建经典的贪吃蛇游戏原型代码。重点展示了利用提示工程,将创新想法高效转化为可运行代码方面的过程。文章还介绍了评估和优化提示词质量的最佳实践。 亚马逊云科技开发者社区为开发者们提供全球的…

C# UserControl、Dockpanel和DockContent、Cursor、

一、UserControl类 UserControl 是 .NET 中的一个基类,用于创建自定义控件,主要用于 Windows Forms 和 WPF。通过继承 UserControl,你可以设计和实现具有特定界面和功能的控件组件。UserControl 允许你将多个标准控件组合在一起,…

网络层 III(划分子网和构造超网)【★★★★★★】

(★★)代表非常重要的知识点,(★)代表重要的知识点。 一、网络层转发分组的过程 分组转发都是基于目的主机所在网络的,这是因为互联网上的网络数远小于主机数,这样可以极大地压缩转发表的大小。…

C++和QT

引用 概念 引用是个别名 格式 数据类型 &引用名 同类型的变量名 (&引用符号) 数据类型 &引用名 同类型的变量名 (&引用符号)int a 10;int &b a; //给a取个别名叫b, b引用a 数组引用 int a;a10;int &…

【AI绘画】Midjourney前置指令/describe、/shorten详解

文章目录 💯前言💯Midjourney前置指令/describe使用方法1️⃣2️⃣3️⃣4️⃣(选择对应提示词生成图片)🔄(重新识别生成提示词)🎉Imagine all(一次性生成所有&#xff09…

BERT:Pre-training of Deep Bidirectional Transformers forLanguage Understanding

个人觉着BERT是一篇读起来很爽的论文 摘要 我们引入了一种新的语言表示模型BERT,它代表Bidirectional Encoder Representations from Transformers。与最近的语言表示模型不同(Peters et al., 2018a;Radford et al., 2018), BER…

Prometheus+Grafana的安装和入门

概念 什么是Prometheus? Prometheus受启发于Google的Brogmon监控系统(相似kubernetes是从Brog系统演变而来), 从2012年开始由google工程师Soundclouds使用Go语言开发的开源监控报警系统和时序列数据库(TSDB)。,并且与2015年早起…

使用LinkedHashMap实现固定大小的LRU缓存

使用LinkedHashMap实现固定大小的LRU缓存 1. 什么是LRU? LRU是"Least Recently Used"的缩写,意为"最近最少使用"。LRU缓存是一种常用的缓存淘汰算法,它的核心思想是:当缓存满时,优先淘汰最近最少…

18959 二叉树的之字形遍历

### 思路 1. **输入读取**: - 读取输入字符串,表示完全二叉树的顺序存储结构。 2. **构建二叉树**: - 使用队列构建二叉树,按层次顺序插入节点。 3. **之字形层序遍历**: - 使用双端队列进行层序遍历&…

【开端】基于nginx部署的具有网关的web日志分析

一、绪论 基于nginx部署的具有网关的web日志分析,我们可以分析的日志有nginx的access.log ,网关的日志和应用的日志 二、日志分析 1、nginx日志 参数 说明 示例 $remote_addr 客户端地址 172.17.0.1 $remote_user 客户端用户名称 -- $time_lo…

简化WPF开发:CommunityToolkit.Mvvm在MVVM架构中的实践与优势

文章目录 前言一、CommunityToolkit.Mvvm1.特点2.优点3.缺点 二、WPF项目应用1.引入到 WPF 项目2.使用示例 总结 前言 CommunityToolkit.Mvvm 是 Microsoft 提供的一个社区工具包,专为 MVVM(Model-View-ViewModel)模式设计,旨在帮…

RabbitMQ练习(Topics)

1、RabbitMQ教程 《RabbitMQ Tutorials》https://www.rabbitmq.com/tutorials 2、环境准备 参考:《RabbitMQ练习(Hello World)》和《RabbitMQ练习(Work Queues)》。 确保RabbitMQ、Sender、Receiver、Receiver2容器…

“重启就能解决一切问题”,iPhone重启方法大揭秘

随着iPhone不断更新换代,其设计与操作方式也在不断进化。从最初的实体Home键到如今的全面屏设计,iPhone的操作逻辑也随之发生了改变。 对于那些习惯了传统安卓手机操作的用户来说,iPhone的重启方式可能会显得有些不同寻常。下面我们就来一起…

SQL血缘解析

Druid 作为使用率特别高的的数据库连接池工具,在具备完善的连接池管理功能外,同时Druid 的 SQL解析功能可以用来防止 SQL注入等安全风险。通过对 SQL 语句进行解析和检查,Druid 可以识别并阻止潜在的恶意 SQL 语句执行,黑名单(阻止特定的 SQL 语句执行)、白名单(仅允许特…

★ 算法OJ题 ★ 力扣11 - 盛水最多的容器

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将和大家一起做一道双指针算法题--盛水最多的容器~ 目录 一 题目 二 算法解析 三 编写算法 一 题目 11. 盛最多水的容器 - 力扣&#xff08;LeetCode&#xff09; 二 算法解析 解法1&#xff1a;暴力枚举 …

文本数据分析-(TF-IDF)(1)

文章目录 一、TF-IDF简介1.意义2.TF与IDF1).TF&#xff08;Term Frequency&#xff09;2).IDF&#xff08;Inverse Document Frequency&#xff09;3).TF-IDF 二、应用三、代码实现1.文件读取2.数据预处理3.排序和输出4.全部代码 一、TF-IDF简介 1.意义 TF-IDF&#xff08;Te…

28 TreeView组件

Tkinter ttk.Treeview 组件使用指南 ttk.Treeview 是 Tkinter 的一个高级控件&#xff0c;用于显示和管理层次化数据。它类似于电子表格或列表视图&#xff0c;但提供了更丰富的功能&#xff0c;如可展开的节点、多列显示等。ttk 模块是 Tkinter 的一个扩展&#xff0c;提供了…

Golang | Leetcode Golang题解之第382题链表随机节点

题目&#xff1a; 题解&#xff1a; type Solution struct {head *ListNode }func Constructor(head *ListNode) Solution {return Solution{head} }func (s *Solution) GetRandom() (ans int) {for node, i : s.head, 1; node ! nil; node node.Next {if rand.Intn(i) 0 { …