图像分类项目1:基于卷积神经网络的动物图像分类
一、选题背景及动机
在现代社会中,图像分类是计算机视觉领域的一个重要任务。动物图像分类具有广泛的应用,例如生态学研究、动物保护、农业监测等。通过对动物图像进行自动分类,可以帮助人们更好地了解动物种类、数量和分布情况,从而支持相关领域的决策和研究。本研究的目标是使用卷积神经网络(CNN)对动物图像进行分类。通过对大量的猫、狗和野生动物图像进行训练,建立一个准确分类不同动物类别的模型。该模型可以用于自动识别和分类新的动物图像,从而提供快速、准确的动物分类结果。
动机:
(1)对于宠物猫和狗的图像分类,可以帮助饲养者或宠物主人快速准确地识别自己的宠物。这对于宠物寻找、宠物遗失的寻找以及宠物社交媒体的管理和组织都非常有用。
(2)通过在大规模的动物图像数据库中进行分类,可以构建一个便捷的图像检索系统。用户可以根据感兴趣的类别,如猫、狗或野生动物,快速搜索和浏览相关的图像内容。
二、研究内容
1、本次训练的数据来源
https://www.kaggle.com/datasets/andrewmvd/animal-faces/data
注册登录之后,下载即可。然后把下载好的数据集放在该项目路径下的data文件中
2、使用PyTorch和scikit-learn框架进行机器学习任务的实现和评估
3、技术难点:
(1)如何准确评估模型的性能和分析分类结果
(2)每个类别的数据样本不一致
解决方法:
(1)对模型进行评估,并计算准确率、精确度、召回率等指标,绘制混淆矩阵和学习曲线,以可视化模型的性能和错误情况
(2)通过对数据样本多的数据集进行欠采样,使所有类别的数据集统一样本数量
三、步骤
1、导入必要的库
import pandas as pd
from PIL import Image
import torch.nn as nn
import torch.optim as optim
from torch.utils.data.sampler import SubsetRandomSampler
from torch.utils.data import Dataset
import torchvision.transforms as transforms
import matplotlib.font_manager as fm
import torch
import torch.nn.functional as F
from sklearn.metrics import accuracy_score, precision_score, recall_score, confusion_matrix, roc_curve, auc
import matplotlib.pyplot as plt
import seaborn as sns
from collections import Counter
from sklearn.utils import resample
import numpy as np
2、加载数据集和对数据预处理
通过对数据的加载和数据预处理之后,打印出每个类别(猫、狗、野兽)的图片总数,并绘制出直方图,更直观的表示出图片每个类别的数量。
class InvalidDatasetException(Exception):def __init__(self, len_of_paths, len_of_labels):super().__init__(f"Number of paths ({len_of_paths}) is not compatible with number of labels ({len_of_labels})")
transform = transforms.Compose([transforms.ToTensor()])
class AnimalDataset(Dataset):def __init__(self, img_paths, img_labels, size_of_images):self.img_paths = img_pathsself.img_labels = img_labelsself.size_of_images = size_of_imagesif len(self.img_paths) != len(self.img_labels):raise InvalidDatasetException(self.img_paths, self.img_labels)def __len__(self):return len(self.img_paths)def __getitem__(self, index):PIL_IMAGE = Image.open(self.img_paths[index]).resize(self.size_of_images)TENSOR_IMAGE = transform(PIL_IMAGE)label = self.img_labels[index]return TENSOR_IMAGE, label
import glob
paths = []
labels = []
label_map = {0: "Cat",1: "Dog",2: "Wild"}
cat_paths = glob.glob("D:/test/pythonProject/data/afhq/train/cat/*") + glob.glob("D:/test/pythonProject/data/afhq/val/cat/*") #路径需要改成自己存放项目数据的路径
for cat_path in cat_paths:paths.append(cat_path)labels.append(0)
dog_paths = glob.glob("D:/test/pythonProject/data/afhq/train/dog/*") + glob.glob("D:/test/pythonProject/data/afhq/val/dog/*")
for dog_path in dog_paths:paths.append(dog_path)labels.append(1)
wild_paths = glob.glob("D:/test/pythonProject/data/afhq/train/wild/*") + glob.glob("D:/test/pythonProject/data/afhq/val/wild/*")
for wild_path in wild_paths:paths.append(wild_path)labels.append(2)
data = pd.DataFrame({'classes': labels})num_classes = len(label_map)
print('总类别数:', num_classes)
for class_label, class_name in label_map.items():count = data[data['classes'] == class_label].shape[0]print(f"类别 {class_name}: {count} 张照片")
font_path = "C:/Windows/Fonts/msyh.ttc"
font_prop = fm.FontProperties(fname=font_path)
sns.set_style("white")
plot = sns.countplot(x=data['classes'], color='#2596be')
plt.figure(figsize=(15, 12))
sns.despine()
plot.set_title('类别分布\n', x=0.1, y=1, font=font_prop, fontsize=18)
plot.set_ylabel("数量", x=0.02, font=font_prop, fontsize=12)
plot.set_xlabel("类别", font=font_prop, fontsize=15)
for p in plot.patches:plot.annotate(format(p.get_height(), '.0f'), (p.get_x() + p.get_width() / 2, p.get_height()),ha='center', va='center', xytext=(0, -20), font=font_prop, textcoords='offset points', size=15)
plt.show()
运行截图:
通过对以上打印的数据以及可视化的图片进行观察,我们可以看到三个类别的数量存在一定的差异。虽然数量上的差距不是太大,但对于训练学习结果可能会有一定的影响。为了克服类别不平衡的问题,我们可以采取欠采样来平衡数据集,减少数量较多的类别的样本数量。
#数据集欠采样
labels = np.array(labels)
paths = np.array(paths)
counter = Counter(labels)
print("原始样本数量:", counter)
cat_indices = np.where(labels == 0)[0]
dog_indices = np.where(labels == 1)[0]
wild_indices = np.where(labels == 2)[0]
min_samples = min([len(cat_indices), len(dog_indices), len(wild_indices)])
undersampled_cat_indices = resample(cat_indices, replace=False, n_samples=min_samples, random_state=42)
undersampled_dog_indices = resample(dog_indices, replace=False, n_samples=min_samples, random_state=42)
undersampled_wild_indices = resample(wild_indices, replace=False, n_samples=min_samples, random_state=42)
undersampled_indices = np.concatenate((undersampled_cat_indices, undersampled_dog_indices, undersampled_wild_indices))
undersampled_paths = paths[undersampled_indices]
undersampled_labels = labels[undersampled_indices]
counter_undersampled = Counter(undersampled_labels)
print("欠采样后的样本数量:", counter_undersampled)
counter_undersampled = Counter(undersampled_labels)
categories = [label_map[label] for label in counter_undersampled.keys()]
sample_counts = list(counter_undersampled.values())
#可视化
sns.set_style("white")
plt.figure(figsize=(6.4, 4.8))
plot = sns.countplot(x=undersampled_labels, color='#2596be')
sns.despine()
plot.set_title('类别分布\n', x=0.1, y=1, font=font_prop, fontsize=18)
plot.set_ylabel("数量", x=0.02, font=font_prop, fontsize=12)
plot.set_xlabel("类别", font=font_prop, fontsize=15)for p in plot.patches:plot.annotate(format(p.get_height(), '.0f'), (p.get_x() + p.get_width() / 2, p.get_height()),ha='center', va='center', xytext=(0, -20), font=font_prop, textcoords='offset points', size=15)plt.show()
运行结果图:
在进行欠采样后,每个类别的图片数量已经被扩展为一致的数量,使得模型在训练过程中更加公平地对待每个类别。
3、缺失值处理
对数据进行预处理完之后,需要查看是否有缺失值,要检查路径和标签的数量是否匹配,并打印路径和标签数量,对缺失情况进行可视化
if len(undersampled_paths) != len(undersampled_labels):raise InvalidDatasetException(len(undersampled_paths), len(undersampled_labels))
#使用字符串格式化(f-string)来将整型值插入到字符串中。
print(f"打印paths列表的文件路径数量: {len(undersampled_paths)}")
print(f"打印labels列表的图片数量: {len(undersampled_labels)}")
#缺失情况数据可视化
df = pd.DataFrame({'Path': undersampled_paths, 'Label': undersampled_labels})
missing_values = df.isnull().sum()
#绘制条形图
plt.bar(missing_values.index, missing_values.values)
plt.xlabel("特征", fontproperties=font_prop, fontsize=12)
plt.ylabel("缺失值数量", fontproperties=font_prop, fontsize=12)
plt.title("缺失情况数据可视化", fontproperties=font_prop, fontsize=18)
plt.grid(False)
plt.xticks(rotation=90)
plt.show()
运行截图:
通过对打印的数据以及对条形图的查看,我们可以确认数据没有缺失。这意味着我们的数据集完整,并且可以进行进一步的分析和处理。
4、划分数据集
对将数据集划分为训练集和测试集,并创建对应的数据加载器,并定义了每个批次的样本数量。
dataset = AnimalDataset(undersampled_paths,undersampled_labels,(250,250))
from sklearn.model_selection import train_test_split
dataset_indices = list(range(0,len(dataset)))
#从数据集中划分训练集和测试集
train_indices,test_indices=train_test_split(dataset_indices,test_size=0.2,random_state=42)
print("训练集样本数量: ",len(train_indices))
print("测试集样本数量: ",len(test_indices))
#创建训练集和测试集的采样器
train_sampler = SubsetRandomSampler(train_indices)
test_sampler = SubsetRandomSampler(test_indices)
BATCH_SIZE = 128
train_loader = torch.utils.data.DataLoader(dataset, batch_size=BATCH_SIZE,sampler=train_sampler)
validation_loader = torch.utils.data.DataLoader(dataset, batch_size=BATCH_SIZE,sampler=test_sampler)
dataset[1][0].shape
images,labels = next(iter(train_loader))
type(labels)
运行截图:
5、获取一个批次的训练数据,并可视化
def add_subplot_label(ax, label):ax.text(0.5, -0.15, label, transform=ax.transAxes,ha='center', va='center', fontsize=12)
images, labels = next(iter(train_loader))
fig, axis = plt.subplots(3, 5, figsize=(15, 10))
for i, ax in enumerate(axis.flat):with torch.no_grad():npimg = images[i].numpy()npimg = np.transpose(npimg, (1, 2, 0))label = label_map[int(labels[i])]ax.imshow(npimg)ax.set(title = f"{label}")ax.grid(False)add_subplot_label(ax, f"({i // axis.shape[1]}, {i % axis.shape[1]})") # 添加编号
plt.tight_layout()
plt.show()
运行截图:
6、模型设计
定义卷积神经网络模型,并设定在哪个设备上运行,为后续的模型训练做准备
class CNN(nn.Module):#定义了卷积神经网络的各个层和全连接层。def __init__(self):super(CNN, self).__init__()# First we'll define our layersself.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=2, padding=1)self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=2, padding=1)self.batchnorm1 = nn.BatchNorm2d(64)self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=1)self.batchnorm2 = nn.BatchNorm2d(128)self.conv4 = nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1)self.batchnorm3 = nn.BatchNorm2d(256)self.maxpool = nn.MaxPool2d(2, 2)self.fc1 = nn.Linear(256 * 2 * 2, 512)self.fc2 = nn.Linear(512, 3)#定义数据在模型中的流动def forward(self, x):x = F.relu(self.conv1(x))x = F.relu(self.conv2(x))x = self.batchnorm1(x)x = self.maxpool(x)x = F.relu(self.conv3(x))x = self.batchnorm2(x)x = self.maxpool(x)x = F.relu(self.conv4(x))x = self.batchnorm3(x)x = self.maxpool(x)x = x.view(-1, 256 * 2 * 2)x = self.fc1(x)x = self.fc2(x)x = F.log_softmax(x, dim=1)return x
#选择模型运行的设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
7、模型训练
执行模型的训练过程,使用交叉熵损失函数和RMSprop优化器来定义损失计算和参数优化的方法,设置了训练的轮次数,并记录每个训练轮次的损失和准确率,对每个训练轮次的损失和准确率进行可视化
model = CNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.RMSprop(model.parameters(),lr=1e-4)
EPOCH_NUMBER = 6
TRAIN_LOSS = []
TRAIN_ACCURACY = []
#训练过程
for epoch in range(1, EPOCH_NUMBER + 1):epoch_loss = 0.0correct = 0total = 0#遍历训练数据加载器for data_, target_ in train_loader:target_ = target_.to(device).long()data_ = data_.to(device).float()#清零优化器中之前的梯度,准备计算当前轮次的梯度。optimizer.zero_grad()#将输入数据传递给模型,获取模型的预测输出。outputs = model(data_)loss = criterion(outputs, target_)loss.backward()optimizer.step()epoch_loss = epoch_loss + loss.item()_, pred = torch.max(outputs, dim=1)#统计预测正确的样本数量,将预测值与真实标签进行比较,并累计正确预测的数量。correct = correct + torch.sum(pred == target_).item()total += target_.size(0)#记录每个训练轮次的损失和准确率,并输出当前训练轮次的准确率和损失。TRAIN_LOSS.append(epoch_loss)TRAIN_ACCURACY.append(100 * correct / total)print(f"Epoch {epoch}: Accuracy: {100 * correct / total}, Loss: {epoch_loss}")
#可视化训练过程中的损失和准确率
plt.subplots(figsize=(6, 4))
plt.plot(range(EPOCH_NUMBER), TRAIN_LOSS, color="blue", label="Loss")
plt.legend()
plt.xlabel("轮次", fontproperties=font_prop)
plt.ylabel("损失值", fontproperties=font_prop)
plt.title("训练损失", fontproperties=font_prop)
plt.show()
plt.subplots(figsize=(6, 4))
plt.plot(range(EPOCH_NUMBER), TRAIN_ACCURACY, color="green", label="Accuracy")
plt.legend()
plt.xlabel("轮次", fontproperties=font_prop)
plt.ylabel("准确率", fontproperties=font_prop)
plt.title("训练准确率", fontproperties=font_prop)
plt.show()
运行截图:
通过上面的数据以及图形,我们可以观察到,随着训练轮次的增加,训练损失逐渐降低,训练准确率逐渐提高。这表明模型在学习过程中逐渐减小了预测值与真实标签之间的差异,提高了对训练数据的拟合能力。每轮的训练损失率都比上一轮的损失率低,说明模型的优化算法有效地调整了参数,使模型逐渐逼近最优解。也意味着模型在训练数据上的分类性能不断改善,更准确地预测了样本的标签。每轮的训练准确率都比上一轮的高,说明模型逐渐学习到了更多的特征和模式,提高了对训练数据的分类准确性。总体来说损失下降和准确率提高是我们期望在训练过程中看到的趋势,表明模型正在逐渐优化和提升性能。
8、性能评估
评估模型在每个类别上的性能,并绘制ROC曲线以衡量模型的分类准确性
def predict_labels(model, data_loader):model.eval()y_pred = []y_true = []with torch.no_grad():for images, labels in data_loader:images = images.to(device)labels = labels.to(device)outputs = model(images)_, predicted = torch.max(outputs.data, 1)y_pred.extend(predicted.cpu().numpy())y_true.extend(labels.cpu().numpy())return np.array(y_pred), np.array(y_true)
#获取预测结果
y_pred, y_true = predict_labels(model, validation_loader)
#计算每个类别的ROC曲线
fpr = dict()
tpr = dict()
roc_auc = dict()
num_classes = len(label_map)
for i in range(num_classes):fpr[i], tpr[i], _ = roc_curve((np.array(y_true) == i).astype(int), (np.array(y_pred) == i).astype(int))roc_auc[i] = auc(fpr[i], tpr[i])
#绘制ROC曲线
plt.figure(figsize=(10, 8))
colors = ['b', 'g', 'r'] # 每个类别的曲线颜色
for i in range(num_classes):plt.plot(fpr[i], tpr[i], color=colors[i], lw=2, label='类别 {0} 的ROC曲线 (AUC = {1:.2f})'.format(i, roc_auc[i]))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('假阳性率', fontproperties=font_prop)
plt.ylabel('真阳性率', fontproperties=font_prop)
plt.title('接收者操作特征曲线', fontproperties=font_prop)
plt.legend(loc="lower right", prop=font_prop)
plt.show()
运行截图:
从图片中可以看出来,cat类别的ROC曲线相对于其他类别的曲线更加接近左上角,而dog和wild类别的曲线则相对较低。这意味着在不同的阈值下,模型更容易将cat类别正确分类为正例,并且在cat类别上具有较高的真阳性率和较低的假阳性率。相比之下,dog和wild类别在模型分类能力方面相对较弱,表明模型更容易将它们错误地分类为其他类别。
9、测试
评估模型在验证集上对模型进行测试,并计算评估指标(准确率、精确率、召回率)以及混淆矩阵,并使用可视化工具将混淆矩阵进行可视化。
model.eval() # 将模型设置为评估模式
predictions = [] # 存储预测结果和真实标签
true_labels = []
#使用测试集进行预测
with torch.no_grad():for images, labels in validation_loader:images = images.to(device)labels = labels.to(device)outputs = model(images) # 前向传播_, predicted = torch.max(outputs.data, 1) # 获取预测结果predictions.extend(predicted.tolist()) # 存储预测结果和真实标签true_labels.extend(labels.tolist())
#将预测结果和真实标签转换为NumPy数组
predictions = np.array(predictions)
true_labels = np.array(true_labels)
accuracy = accuracy_score(true_labels, predictions) # 计算准确率
precision = precision_score(true_labels, predictions, average='macro') # 计算精确率
recall = recall_score(true_labels, predictions, average='macro') # 计算召回率
confusion = confusion_matrix(true_labels, predictions) # 计算混淆矩阵
# 打印评估结果
print("准确率:", accuracy)
print("精确率:", precision)
print("召回率:", recall)
print("混淆矩阵:")
print(confusion)
# 可视化混淆矩阵
labels = ['Cat', 'Dog', 'Wild']
plt.rcParams['font.sans-serif'] = ['SimSun']
plt.figure(figsize=(8, 6))
sns.heatmap(confusion, annot=True, fmt="d", cmap="Blues", xticklabels=labels, yticklabels=labels)
plt.xlabel('预测标签')
plt.ylabel('真实标签')
plt.title('混淆矩阵')
plt.show()
运行截图:
四 思考
1、换数据集行不行?
比如动物数据集换成植物数据集等,大家可以自行找公开数据集进行测试。
2、换模型行不行?
用其它卷积神经网络模型试一试:
- LeNet-5:由Yann LeCun等人于1998年提出,主要用于手写数字识别。LeNet-5包含了卷积层、池化层和全连接层,是第一个成功应用于数字识别任务的卷积神经网络模型。
- AlexNet:由Alex Krizhevsky等人在2012年的ImageNet图像分类竞赛中提出。AlexNet采用了更深的网络结构和更大的数据集,使用了ReLU激活函数和Dropout正则化技术,取得了突破性的性能提升。
- VGGNet:由Karen Simonyan和Andrew Zisserman在2014年提出。VGGNet的特点是使用了非常小的卷积核(3x3),并通过堆叠多个卷积层来增加网络的深度,提高了特征提取的效果。
- GoogLeNet (Inception):由Google团队在2014年提出。GoogLeNet采用了Inception模块结构,通过并行的多个卷积分支来提取不同尺度的特征,并使用1x1的卷积核来降低计算复杂度。
- ResNet:由Microsoft团队在2015年提出。ResNet引入了残差学习的思想,通过跨层连接解决了深度网络训练中的梯度消失和梯度爆炸问题,适用于大规模图像识别任务。
- MobileNet:由Google团队在2017年提出。MobileNet采用了深度可分离卷积的结构,减少了参数数量,适用于移动设备等资源受限的场景。
3、图像出现以下情况怎么处理?
(1)模糊
(2)光照不均匀
(3)扭曲变形
(4)有雨有雾
(5)图上除了动物外还有其它物体
相关文章:

图像分类项目1:基于卷积神经网络的动物图像分类
一、选题背景及动机 在现代社会中,图像分类是计算机视觉领域的一个重要任务。动物图像分类具有广泛的应用,例如生态学研究、动物保护、农业监测等。通过对动物图像进行自动分类,可以帮助人们更好地了解动物种类、数量和分布情况,…...

Kali Linux 2024.4版本全局代理(wide Proxy)配置,适用于浏览器、命令行
1. 网络拓扑介绍(不使用虚拟机直接跳到2) 虚拟机:VMware 17 Pro,为本机开启桥接模式。 我的究极套娃网络:手机V2rayNG代理端口为10808,开热点 -> 电脑连接wifi -> 虚拟机中运行kali 2. kali 配置…...

[Windows] 批量为视频或者音频生成字幕 video subtitle master 1.5.2
Video Subtitle Master 1.5.2 介绍 Video Subtitle Master 1.5.2 是一款功能强大的客户端工具,能够批量为视频或音频生成字幕,还支持批量将字幕翻译成其他语言。该工具具有跨平台性,无论是 mac 系统还是 windows 系统都能使用。 参考原文&a…...

不要升级,Flutter Debug 在 iOS 18.4 beta 无法运行,提示 mprotect failed: Permission denied
近期如果有开发者的 iOS 真机升级到 18.4 beta,大概率会发现在 debug 运行时会有 Permission denied 的相关错误提示,其实从 log 可以很直观看出来,就是 Dart VM 在初始化时,对内核文件「解释运行(JIT)」时…...

介绍 torch-mlir 从 pytorch 生态到 mlir 生态
一、引言 The Torch-MLIR project provides core infrastructure for bridging the PyTorch ecosystem and the MLIR ecosystem. For example, Torch-MLIR enables PyTorch models to be lowered to a few different MLIR dialects. Torch-MLIR does not attempt to provide a…...

upload
(上传一句话木马,用蚁剑链接验证是否成功/传有回显的:<?php phpinfo();?>) 学看代码 #function checkfile(){}:定义了一个名叫checkfile的函数 #var file方法.(获取名为‘upload_file’的元素)[获取哪些&…...

InterHand26M(handposeX-json 格式)数据集-release >> DataBall
DataBall 助力快速掌握数据集的信息和使用方式,会员享有 百种数据集,持续增加中。 需要更多数据资源和技术解决方案,知识星球: “DataBall - X 数据球(free)” 贵在坚持! ---------------------------------------…...

[Java基础] JVM常量池介绍(BeanUtils.copyProperties(source, target)中的属性值引用的是同一个对象吗)
文章目录 1. JVM内存模型2. 常量池中有什么类型?3. 常量池中真正存储的内容是什么4. 判断一个字符串(引用)是否在常量池中5. BeanUtils.copyProperties(source, target)中的属性值引用的是同一个对象吗?6. 获取堆内存使用情况、非堆内存使用情况 1. JVM内…...
`maturin`是什么:matu rus in python
maturin是什么 maturin 是一个用于构建和发布 Rust 编写的 Python 绑定库的工具。它简化了将 Rust 代码集成到 Python 项目中的过程,支持创建不同类型的 Python 包,如纯 Python 包、包含 **Rust (系统编程语言)**扩展模块的包等。以下为你详细介绍 maturin 的相关信息并举例…...

spring boot整合flyway实现数据的动态维护
1、简单介绍一下flyway Flyway 是一款开源的数据库版本控制工具,主要用于管理数据库结构的变更(如创建表、修改字段、插入数据等)。它通过跟踪和执行版本化的迁移脚本,帮助团队实现数据库变更的自动化。接下来简单介绍一下flyway…...

unity中使用spine详解
一.Spine概述 Spine 是一款针对游戏开发的 2D 骨骼动画编辑工具。 Spine 旨在提供更高效和简洁 的工作流程,以创建游戏所需的动画。 Spine原理:将一个模型,根据动画的需求分成一些骨骼,一个骨骼对应一张贴图,控制骨骼…...

14. LangChain项目实战1——基于公司制度RAG回答机器人
教学视频: 12. 基于Gradio搭建基于公司制度RAG_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV11VXRYTErZ/ 环境配置: python版本:3.10.8 服务器:Ubuntu 依赖包requirements.txt文件内容: aiofiles23.2.1 …...

利用STM32TIM自制延迟函数实验
一、实验目的 掌握STM32定时器(TIM)的工作原理及配置方法学习使用HAL库实现微秒级/毫秒级延时函数理解定时器中断服务程序的编写规范 二、实验原理 定时器基础: STM32定时器包含向上计数器、向下计数器、中心对齐模式通过预分频器&#x…...

创建一个MCP服务器,并在Cline中使用,增强自定义功能。
MCP介绍 MCP 是一个开放协议,它标准化了应用程序如何向LLMs提供上下文。可以将 MCP 视为 AI 应用程序的 USB-C 端口。正如 USB-C 提供了一种标准化的方法来将您的设备连接到各种外围设备和配件一样,MCP 提供了一种标准化的方法来将 AI 模型连接到不同的…...
Android Activity栈关系解析
在 Android 系统中,这些类共同构成了 Activity 任务栈管理的核心架构。它们的关系可以类比为一栋大楼的管理体系,每个类负责不同层级的任务。以下是它们的详细解释和实际场景示例: 1. ActivityRecord(活动记录) 是什么…...
java使用word模板填充内容,再生成pdf
1.word模板填充内容 使用EasyPoi写入Word文档。 import cn.afterturn.easypoi.word.WordExportUtil; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.poi.xwpf.usermodel.XWPFDocument;import java.io.File; import java…...

回归实战详细代码+解析:预测新冠感染人数
回归实战:预测新冠感染人数 先回顾下回归是个啥玩意 首先需要一组训练集,说人话就是通过一系列x[x1,x2…xn]通过神秘计算得到y的过程,当然人和机器现在都不知道什么计算是什么,这是一个黑箱。 黑箱比喻:把模型想象成自…...

AI人工智能机器学习之聚类分析
1、概要 本篇学习AI人工智能机器学习之聚类分析,以KMeans、AgglomerativeClustering、DBSCAN为例,从代码层面讲述机器学习中的聚类分析。 2、聚类分析 - 简介 聚类分析是一种无监督学习的方法,用于将数据集中的样本划分为不同的组ÿ…...

(下:补充——五个模型的理论基础)深度学习——图像分类篇章
目录 1.1 卷积神经网络基础 3.1 AlexNet网络结构详解与花分类数据集下载 4.1 VGG网络详解及感受野的计算 5.1 GoogLeNet网络详解 6.1 ResNet网络结构,BN以及迁移学习详解 总结(可以直接看总结) 1.1 卷积神经网络基础 视频讲解…...
使用Python自动生成图文并茂的网页分析报告
在数据分析中,不管是市场研究还是科学分析,经常需要使用Python进行数据分析并生成图表报告。一般使用Python生成和展示图表时都是使用matplotlib 库生成静态图片文件,这种方式不便之处是不方便跟动态文字段落结合在一起,也不方便分…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...