全连接神经网络(MLP)原理与PyTorch实现详解

一、全连接神经网络概述

全连接神经网络(Fully Connected Neural Network),也称为多层感知机(Multi-Layer Perceptron, MLP),是深度学习中最基础的神经网络结构之一。它由多个全连接层组成,每一层的神经元与下一层的所有神经元相连接。

1.1 神经网络基本结构

一个典型的全连接神经网络包含以下组成部分:

  • 输入层:接收原始数据

  • 隐藏层:进行特征提取和转换(可以有多层)

  • 输出层:产生最终预测结果

  • 权重(Weights):连接神经元之间的参数

  • 偏置(Bias):每个神经元的附加参数

  • 激活函数:引入非线性因素

1.2 为什么需要激活函数?

如果不使用激活函数,无论神经网络有多少层,输出都是输入的线性组合,这与单层神经网络等价。这是因为多层线性变换可以被简化为一个等效的单层线性变换。

具体来说:

  1. 假设一个两层神经网络,第一层的权重矩阵为W1,第二层为W2
  2. 没有激活函数时,输出y = W2(W1x) = (W2W1)x
  3. 这个结果等价于一个单层网络y = W'x,其中W'=W2W1

这种线性叠加会导致神经网络的表达能力被大大限制:

  • 无法学习非线性关系(如XOR问题)
  • 无法实现复杂的特征转换
  • 无法逼近任意函数(根据通用近似定理)

常用的激活函数包括:

  1. ReLU(Rectified Linear Unit)

    • 公式:f(x) = max(0, x)
    • 特点:
      • 计算简单高效,只需判断阈值
      • 有效缓解深度网络中的梯度消失问题
      • 存在"死亡ReLU"现象(神经元可能永远不被激活)
    • 应用场景:CNN、DNN等深层网络的隐藏层
    • 示例:AlexNet、ResNet等经典网络均采用ReLU
  2. Sigmoid

    • 公式:f(x) = 1 / (1 + e^-x)
    • 特点:
      • 输出范围(0,1),可解释为概率
      • 存在梯度消失问题(当输入绝对值较大时)
      • 计算涉及指数运算,相对复杂
    • 应用场景:
      • 二分类问题的输出层
      • 传统神经网络的隐藏层(现已较少使用)
    • 示例:逻辑回归中的默认激活函数
  3. Tanh(双曲正切函数)

    • 公式:f(x) = (e^x - e^-x) / (e^x + e^-x)
    • 特点:
      • 输出范围(-1,1),以0为中心
      • 梯度比sigmoid更陡峭
      • 同样存在梯度消失问题
    • 应用场景:RNN/LSTM等序列模型的隐藏层
    • 示例:LSTM中用于控制记忆单元状态的更新
  4. Softmax

    • 公式:f(x_i) = e^x_i / Σ(e^x_j)
    • 特点:
      • 将输出转化为概率分布(总和为1)
      • 放大最大值的概率,抑制较小值
      • 通常配合交叉熵损失函数使用
    • 应用场景:
      • 多分类问题的输出层
      • 注意力机制中的注意力权重计算
    • 示例:图像分类网络(如VGG、Inception)的最后一层
  5. 其他常见激活函数

    • Leaky ReLU:f(x) = max(αx, x)(α通常取0.01)
    • ELU:f(x) = x (x>0), α(e^x-1) (x≤0)
    • Swish:f(x) = x * sigmoid(βx)(Google提出的自门控激活函数)

注:在实际应用中,ReLU及其变种(如Leaky ReLU)是目前最常用的隐藏层激活函数,而输出层根据任务类型选择Sigmoid(二分类)或Softmax(多分类)。选择激活函数时需要权衡计算效率、梯度特性和网络深度等因素。

二、使用PyTorch构建全连接神经网络

PyTorch是一个开源的Python机器学习库,基于Torch,广泛应用于计算机视觉和自然语言处理等应用领域。下面我们将详细介绍如何使用PyTorch构建全连接神经网络。

2.1 环境准备

首先需要安装PyTorch:

# 使用pip安装PyTorch CPU版本
# pip install torch torchvision# 如果有NVIDIA GPU,可以安装CUDA版本
# pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113

2.2 导入必要的库 

import torch
from torch import nn  # 神经网络模块
from torch import optim  # 优化器模块
from torch.nn import functional as F  # 常用函数模块
import numpy as np
from sklearn.datasets import make_classification  # 生成分类数据
from sklearn.model_selection import train_test_split  # 数据集划分
from sklearn.preprocessing import StandardScaler  # 数据标准化

2.3 数据准备

我们使用scikit-learn生成一个模拟的二分类数据集:

# 设置随机种子保证可复现性
torch.manual_seed(42)
np.random.seed(42)# 生成模拟数据
# n_samples: 样本数量
# n_features: 特征数量
# n_classes: 类别数量
# n_informative: 有信息的特征数量
X, y = make_classification(n_samples=1000, n_features=10, n_classes=2, n_informative=8, random_state=42)# 将数据转换为PyTorch张量
X = torch.from_numpy(X).float()  # 转换为float32类型
y = torch.from_numpy(y).float().view(-1, 1)  # 转换为float32并调整形状# 数据标准化
scaler = StandardScaler()
X = torch.from_numpy(scaler.fit_transform(X.numpy())).float()# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 转换为PyTorch的Dataset和DataLoader
from torch.utils.data import TensorDataset, DataLoadertrain_dataset = TensorDataset(X_train, y_train)
test_dataset = TensorDataset(X_test, y_test)# DataLoader参数详解:
# dataset: 数据集
# batch_size: 每批数据量
# shuffle: 是否打乱数据
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

2.4 定义模型结构

使用PyTorch的nn.Module类定义我们的全连接神经网络:

class MLP(nn.Module):def __init__(self, input_size):"""初始化MLP模型参数:input_size: 输入特征维度"""super(MLP, self).__init__()# 第一个全连接层# nn.Linear参数:# in_features: 输入特征数# out_features: 输出特征数(神经元数量)# bias: 是否使用偏置项(默认为True)self.fc1 = nn.Linear(input_size, 64)# 第二个全连接层self.fc2 = nn.Linear(64, 32)# 输出层self.fc3 = nn.Linear(32, 1)# Dropout层,防止过拟合# p: 丢弃概率self.dropout = nn.Dropout(p=0.2)def forward(self, x):"""前向传播参数:x: 输入数据返回:模型输出"""# 第一层: 线性变换 + ReLU激活 + Dropoutx = F.relu(self.fc1(x))x = self.dropout(x)# 第二层: 线性变换 + ReLU激活 + Dropoutx = F.relu(self.fc2(x))x = self.dropout(x)# 输出层: 线性变换 + Sigmoid激活(二分类问题)x = torch.sigmoid(self.fc3(x))return x

2.5 模型实例化与参数查看 

# 实例化模型
input_size = X_train.shape[1]  # 输入特征维度
model = MLP(input_size)# 打印模型结构
print(model)# 查看模型参数
for name, param in model.named_parameters():print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")

2.6 定义损失函数和优化器 

# 定义损失函数
# nn.BCELoss(): 二分类交叉熵损失函数
# 注意:使用BCELoss时,模型输出需要经过Sigmoid激活
criterion = nn.BCELoss()# 定义优化器
# optim.SGD参数:
# params: 要优化的参数(通常为model.parameters())
# lr: 学习率(learning rate)
# momentum: 动量因子(0-1)
# weight_decay: L2正则化系数
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)# 也可以使用Adam优化器
# optimizer = optim.Adam(model.parameters(), lr=0.001, betas=(0.9, 0.999))

2.7 训练模型 

# 训练参数
num_epochs = 100# 记录训练过程中的损失和准确率
train_losses = []
test_losses = []
train_accuracies = []
test_accuracies = []for epoch in range(num_epochs):# 训练模式model.train()running_loss = 0.0correct = 0total = 0for inputs, labels in train_loader:# 梯度清零optimizer.zero_grad()# 前向传播outputs = model(inputs)# 计算损失loss = criterion(outputs, labels)# 反向传播loss.backward()# 更新权重optimizer.step()# 统计信息running_loss += loss.item()predicted = (outputs > 0.5).float()total += labels.size(0)correct += (predicted == labels).sum().item()# 计算训练集上的平均损失和准确率train_loss = running_loss / len(train_loader)train_accuracy = 100 * correct / totaltrain_losses.append(train_loss)train_accuracies.append(train_accuracy)# 测试模式model.eval()test_running_loss = 0.0test_correct = 0test_total = 0with torch.no_grad():  # 不计算梯度for inputs, labels in test_loader:outputs = model(inputs)loss = criterion(outputs, labels)test_running_loss += loss.item()predicted = (outputs > 0.5).float()test_total += labels.size(0)test_correct += (predicted == labels).sum().item()# 计算测试集上的平均损失和准确率test_loss = test_running_loss / len(test_loader)test_accuracy = 100 * test_correct / test_totaltest_losses.append(test_loss)test_accuracies.append(test_accuracy)# 打印训练信息print(f'Epoch [{epoch+1}/{num_epochs}], 'f'Train Loss: {train_loss:.4f}, Train Acc: {train_accuracy:.2f}%, 'f'Test Loss: {test_loss:.4f}, Test Acc: {test_accuracy:.2f}%')

2.8 可视化训练过程 

import matplotlib.pyplot as plt# 绘制损失曲线
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(train_losses, label='Train Loss')
plt.plot(test_losses, label='Test Loss')
plt.title('Training and Test Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend()# 绘制准确率曲线
plt.subplot(1, 2, 2)
plt.plot(train_accuracies, label='Train Accuracy')
plt.plot(test_accuracies, label='Test Accuracy')
plt.title('Training and Test Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy (%)')
plt.legend()plt.tight_layout()
plt.show()

三、全连接神经网络的高级技巧

3.1 权重初始化

良好的权重初始化可以加速收敛并提高模型性能:

# 自定义权重初始化
def init_weights(m):if isinstance(m, nn.Linear):# Xavier/Glorot初始化nn.init.xavier_uniform_(m.weight)# 偏置初始化为0nn.init.zeros_(m.bias)# 应用初始化
model.apply(init_weights)

3.2 学习率调度

动态调整学习率可以提高训练效果:

# 定义学习率调度器
# optim.lr_scheduler.StepLR参数:
# optimizer: 优化器
# step_size: 多少epoch后调整学习率
# gamma: 学习率衰减因子
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)# 在训练循环中添加
# scheduler.step()

3.3 模型保存与加载 

# 保存模型
torch.save(model.state_dict(), 'mlp_model.pth')# 加载模型
loaded_model = MLP(input_size)
loaded_model.load_state_dict(torch.load('mlp_model.pth'))
loaded_model.eval()

完整示例:使用PyTorch创建并训练全连接神经网络

下面是一个完整的示例代码,展示了如何使用PyTorch创建、训练和评估一个全连接神经网络(MLP),包含详细注释和最佳实践。

 

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import numpy as np# 1. 设置随机种子保证可复现性
torch.manual_seed(42)
np.random.seed(42)# 2. 数据准备
def prepare_data():"""生成并准备训练数据"""# 生成模拟数据集 (1000个样本,20个特征,2个类别)X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, n_informative=15, random_state=42)# 数据标准化scaler = StandardScaler()X = scaler.fit_transform(X)# 转换为PyTorch张量X = torch.from_numpy(X).float()y = torch.from_numpy(y).float().view(-1, 1)  # 调整形状为(n_samples, 1)# 划分训练集和测试集 (80%训练,20%测试)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 创建DataLoadertrain_dataset = TensorDataset(X_train, y_train)test_dataset = TensorDataset(X_test, y_test)train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)return train_loader, test_loader, X_train.shape[1]# 3. 定义模型
class MLP(nn.Module):"""全连接神经网络模型"""def __init__(self, input_size):"""初始化MLP参数:input_size (int): 输入特征维度"""super(MLP, self).__init__()# 网络结构self.fc1 = nn.Linear(input_size, 128)  # 第一隐藏层self.fc2 = nn.Linear(128, 64)         # 第二隐藏层self.fc3 = nn.Linear(64, 32)          # 第三隐藏层self.fc4 = nn.Linear(32, 1)           # 输出层# Dropout层 (防止过拟合)self.dropout = nn.Dropout(p=0.3)# 批归一化层 (加速训练)self.bn1 = nn.BatchNorm1d(128)self.bn2 = nn.BatchNorm1d(64)self.bn3 = nn.BatchNorm1d(32)def forward(self, x):"""前向传播"""x = F.relu(self.bn1(self.fc1(x)))x = self.dropout(x)x = F.relu(self.bn2(self.fc2(x)))x = self.dropout(x)x = F.relu(self.bn3(self.fc3(x)))x = self.dropout(x)x = torch.sigmoid(self.fc4(x))  # 二分类使用sigmoidreturn xdef initialize_weights(self):"""自定义权重初始化"""for m in self.modules():if isinstance(m, nn.Linear):nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')if m.bias is not None:nn.init.constant_(m.bias, 0)# 4. 训练和评估函数
def train_model(model, train_loader, test_loader, num_epochs=100):"""训练模型并记录指标"""# 定义损失函数和优化器criterion = nn.BCELoss()  # 二分类交叉熵损失optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)# 学习率调度器scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=True)# 记录指标history = {'train_loss': [],'test_loss': [],'train_acc': [],'test_acc': []}for epoch in range(num_epochs):# 训练阶段model.train()running_loss = 0.0correct = 0total = 0for inputs, labels in train_loader:optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()predicted = (outputs > 0.5).float()total += labels.size(0)correct += (predicted == labels).sum().item()# 计算训练集指标train_loss = running_loss / len(train_loader)train_acc = 100 * correct / totalhistory['train_loss'].append(train_loss)history['train_acc'].append(train_acc)# 评估阶段model.eval()test_loss = 0.0test_correct = 0test_total = 0with torch.no_grad():for inputs, labels in test_loader:outputs = model(inputs)loss = criterion(outputs, labels)test_loss += loss.item()predicted = (outputs > 0.5).float()test_total += labels.size(0)test_correct += (predicted == labels).sum().item()# 计算测试集指标test_loss /= len(test_loader)test_acc = 100 * test_correct / test_totalhistory['test_loss'].append(test_loss)history['test_acc'].append(test_acc)# 更新学习率scheduler.step(test_loss)# 打印进度print(f'Epoch [{epoch+1}/{num_epochs}] | 'f'Train Loss: {train_loss:.4f}, Acc: {train_acc:.2f}% | 'f'Test Loss: {test_loss:.4f}, Acc: {test_acc:.2f}%')return historydef plot_history(history):"""绘制训练曲线"""plt.figure(figsize=(12, 5))# 损失曲线plt.subplot(1, 2, 1)plt.plot(history['train_loss'], label='Train Loss')plt.plot(history['test_loss'], label='Test Loss')plt.title('Training and Validation Loss')plt.xlabel('Epoch')plt.ylabel('Loss')plt.legend()# 准确率曲线plt.subplot(1, 2, 2)plt.plot(history['train_acc'], label='Train Accuracy')plt.plot(history['test_acc'], label='Test Accuracy')plt.title('Training and Validation Accuracy')plt.xlabel('Epoch')plt.ylabel('Accuracy (%)')plt.legend()plt.tight_layout()plt.show()# 5. 主程序
def main():# 准备数据train_loader, test_loader, input_size = prepare_data()# 初始化模型model = MLP(input_size)model.initialize_weights()  # 自定义权重初始化# 打印模型结构print(model)# 训练模型history = train_model(model, train_loader, test_loader, num_epochs=50)# 绘制训练曲线plot_history(history)# 保存模型torch.save(model.state_dict(), 'mlp_model.pth')print("Model saved to mlp_model.pth")if __name__ == '__main__':main()

四、全连接神经网络的应用场景与局限性

4.1 适用场景

  1. 结构化数据:如表格数据、金融数据等

  2. 小型图像分类:如MNIST手写数字识别

  3. 简单回归问题:如房价预测

  4. 特征重要性分析:通过权重分析特征重要性

4.2 局限性

  1. 参数量大:全连接导致参数数量随网络规模快速增长

  2. 局部模式不敏感:对图像等具有局部结构的数据处理效率低

  3. 容易过拟合:特别是在深层网络中

  4. 梯度消失/爆炸:深层网络训练困难

五、总结

通过本教程,我们详细介绍了全连接神经网络的原理和PyTorch实现方法,包括:

  1. 数据准备与预处理

  2. 模型定义与参数初始化

  3. 损失函数与优化器选择

  4. 训练过程与评估方法

  5. 高级技巧与最佳实践

全连接神经网络虽然结构简单,但仍然是深度学习的重要基础。掌握MLP的原理和实现方法,有助于理解更复杂的神经网络结构。在实际应用中,可以根据具体问题调整网络结构、激活函数、优化器等超参数,以获得最佳性能。

希望本篇文章能帮助你快速入门全连接神经网络,并为后续学习更复杂的深度学习模型打下坚实基础!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

相关文章

推荐系统-数据分割、性能验证

推荐系统基础概念前言 作者根据开源项目 gorse 的每一步提交, 系统性学习推荐系统架构组成以及gorse中使用的推荐算法的实现。 通过参考算法文档以及代码实现,作者对gorse的学习过程以及进度 与 博客发布的时间线保持一致数据集分割原因 推荐系统的根本任…

从电商新手到单日变现5000+,我是如何做到闲鱼爆单的

很多人想做项目赚钱,却总是迈不出第一步。今天给大家分享一个可以从电商小白到成功跑通项目,实现单日GMV 5000的项目。今天将分享从选品、内容制作、销售服务的全过程实战经验。1:闲鱼实战,强执行力01实操前的准备执行力就是你的动…

vue3实现pdf文件预览 - vue-pdf-embed

参考地址:https://juejin.cn/post/7105933034771185701 这个参考文章的代码直接可以复制使用,样式也是给到的,但是实现的是一页一页的显示pdf内容,我的需求是要全部展示出来,页码切换时是做一个滚动定位操作。 思路&am…

【AI论文】OmniPart:基于语义解耦与结构连贯性的部件感知三维生成

摘要:创建具有显式、可编辑部件结构的三维资产,对于推动交互式应用的发展至关重要。然而,大多数生成方法仅能生成整体式形状,限制了其实际应用价值。我们提出OmniPart——一种新型的部件感知三维物体生成框架,旨在实现…

Pandas-数据查看与质量检查

Pandas-数据查看与质量检查一、数据查看:快速掌握数据概况1. 整体概览:shape与info()2. 数值特征预览:describe()3. 随机抽样:head()与sample()二、数据质量检查:识别与处理问题1. 缺失值检查与处理处理策略&#xff1…

类和对象拓展——日期类

一.前言通过前面对类和对象的学习&#xff0c;现在我们可以开始实践日期类的代码编写。在实际操作过程中&#xff0c;我会补充之前文章中未提及的相关知识点。二.正文 1. 日期类代码实现我们先来看看要实现什么功能吧&#xff0c;把他放在Date.h中#pragma once #include<ios…

大模型KV缓存量化误差补偿机制:提升推理效率的关键技术

大模型KV缓存量化误差补偿机制&#xff1a;提升推理效率的关键技术摘要 随着大型语言模型&#xff08;LLM&#xff09;参数规模突破千亿级别&#xff0c;推理过程中的显存占用与计算延迟成为制约其实际部署的核心瓶颈。KV缓存&#xff08;Key-Value Cache&#xff09;作为Trans…

QT跨平台应用程序开发框架(6)—— 常用显示类控件

目录 一&#xff0c;Label 1.1 主要属性 1.2 文本格式 1.3 设置图片 1.4 其它常用属性 1.5 设置伙伴 二&#xff0c;LCD Number 2.1 主要属性 2.2 实现倒计时 ​2.3 两个问题 三&#xff0c;ProgressBar 3.1 主要属性 3.2 进度条按时间增长 3.3 改变样式 3.4 一个问题 四&#…

LINUX文件系统权限,命令解释器alias,文件查看和查找

1、文件査看:查看/etc/passwd文件的第5行[rootserver ~]# head -5 /etc/passwd | tail -1 #先找到前5行&#xff0c;用管道符过滤&#xff0c;显示倒数第一行2、文件查找(1)在当前目录及子目录中&#xff0c;查找大写字母开头的txt文件[rootserver ~]# find / -name "[…

AI图像修复工具CodeFormer实测:马赛克去除与画质增强效果评测

大家好&#xff01;平时看图片或视频&#xff0c;是不是特别烦人脸被马赛克遮住的地方&#xff1f;比如老照片模糊、视频关键部分被打码&#xff0c;看着很不舒服。今天给大家分享一款超好用的去马赛克神器——CodeFormer&#xff0c;完全免费&#xff0c;新手也能轻松搞定&…

知识宇宙-思考篇:AI大模型如何重塑软件开发流程?

名人说&#xff1a;博观而约取&#xff0c;厚积而薄发。——苏轼《稼说送张琥》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录AI大模型重塑软件开发&#xff1a;从码农到AI编程伙伴的华丽转身一、AI大模型的编程&…

Rocky Linux上使用NVM安装Node.js 18

问题描述 Rocky Linux 9 默认 yum 安装的 Node.js 版本是16&#xff0c;vite启动报错&#xff1a;TypeError: crypto$2.getRandomValues is not a function &#xff0c;需安装更高版本的 Node.js 使用nvm安装Node.js的好处 多版本管理&#xff0c;NVM 允许你安装多个不同版本的…

JVM 中“对象存活判定方法”全面解析

1. 前言 在 Java 开发过程中&#xff0c;我们常常听到“垃圾回收”&#xff08;Garbage Collection, GC&#xff09;这一术语。JVM 通过垃圾回收机制自动管理内存&#xff0c;极大地简化了程序员的内存控制负担。然而&#xff0c;GC 究竟是如何判断哪些对象该回收、哪些应保留…

苹果公司高ROE分析

公司通过增加负债提升净资产收益率&#xff08;ROE&#xff09;的核心机制在于财务杠杆效应和资本结构优化&#xff0c;以下从原理、操作路径、风险边界及苹果案例四维度展开分析&#xff1a;名称解释&#xff1a; ROIC(投入资本回报率)&#xff1a;ROICNOPATInvested Capital …

【Linux系统】进程概念

1. 进程概念1.1 进程的本质核心定义用户视角&#xff1a;程序的动态执行实例&#xff08;如同时运行多个Chrome窗口即多个进程&#xff09;。内核视角&#xff1a;资源分配的最小实体单位&#xff0c;独享CPU时间片、内存空间和文件资源。现代定义&#xff1a;进程 内核数据结…

从LLM到VLM:视觉语言模型的核心技术与Python实现

本教程的完整代码可以在GitHub上找到&#xff0c;如果你有任何问题或建议&#xff0c;欢迎交流讨论。 引言&#xff1a;为什么需要VLM&#xff1f; 当我们与ChatGPT对话时&#xff0c;它能够理解复杂的文字描述&#xff0c;生成流畅的回答。但如果我们给它一张图片&#xff0c…

老系统改造增加初始化,自动化数据源配置(tomcat+jsp+springmvc)

老系统改造增加初始化&#xff0c;自动化数据源配置一、前言二、改造描述1、环境说明2、实现步骤简要思考三、开始改造1、准备sql初始化文件2、启动时自动读取jdbc文件&#xff0c;创建数据源&#xff0c;如未配置&#xff0c;需要一个默认的临时数据源2.1去掉sping mvc原本配置…

卫星通信终端天线的5种对星模式之二:DVB跟踪

要实现稳定可靠的卫星通信&#xff0c;地面终端天线必须精准地对准远方的卫星。对星的过程是一个不断搜索、不断逼近的过程&#xff0c;其目标是让天线波束中心精确指向卫星&#xff0c;从而获得最大信号接收与发射效率。 卫星通信终端天线的对星技术是保障卫星通信链路稳定的…

重构下一代智能电池“神经中枢”:GCKontrol定义高性能BMS系统级设计标杆

概述BMS&#xff08;电池管理系统&#xff09;作为新能源汽车动力电池与整车的核心纽带&#xff0c;通过实时监控电压、电流、温度及SOC等参数&#xff0c;控制电池充放电过程&#xff0c;保障电池安全性与使用寿命。随着电动汽车智能化发展&#xff0c;对BMS的响应速度、精度和…

面试150 对称二叉树

思路 联想递归三部曲&#xff1a;传入参数、遍历方式、返回什么。本题联想到先序遍历的方式,需要遍历整颗二叉树,最后返回的是一个布尔值。然后我们需要传入的是左子树和左子树的节点,然后分别进行比较。 # Definition for a binary tree node. # class TreeNode: # def __…