## 背景
在深度学习的世界中,Vision Transformer (ViT) 模型因其在图像分类任务中的卓越表现而受到广泛关注。然而,ViT 模型通常使用 Python 编写,尤其是基于 PyTorch 框架的实现。对于 PHP 开发者来说,利用 PHP 来实现 ViT 模型可能看似不切实际,但借助`phpy`扩展,我们可以轻松地在 PHP 中调用 Python 的生态系统,从而实现这一目标。
## ViT模型特点
ViT模型主要应用于图像分类领域。因此,其模型结构相较于传统的Transformer有以下几个特点:
* 数据集的原图像被划分为多个Patch后,通过Patch Embedding将二维Patch(不考虑channel)转换为一维向量,再加上类别向量与位置向量作为模型输入。
* 模型主体的Block结构是基于Transformer的Encoder结构,但是调整了Normalization的位置,其中,最主要的结构依然是Multi-head Attention结构。
* 模型在Blocks堆叠后接全连接层,接受类别向量的输出作为输入并用于分类。通常情况下,我们将最后的全连接层称为Head,Transformer Encoder部分为backbone。
ViT模型利用Transformer模型在处理上下文语义信息的优势,将图像转换为一种`变种词向量`然后进行处理,而这种转换的意义在于,多个Patch之间本身具有空间联系,这类似于一种“空间语义”,从而获得了比较好的处理效果。
## 什么是phpy?
`phpy`是一个 PHP 扩展,允许 PHP 调用 Python 模块。这意味着我们可以在 PHP 中使用 Python 的强大功能和库,而不需要切换编程语言。这对于需要在 PHP 项目中使用深度学习模型的开发者来说,具有重要意义。
## 代码实现
安装依赖包
```
pip install torch
```
安装日志
```ts
Collecting torch
Downloading torch-2.4.0-cp39-cp39-manylinux1_x86_64.whl (797.2 MB)
|████████████████████████████████| 797.2 MB 55 kB/s
Collecting nvidia-cufft-cu12==11.0.2.54
Downloading nvidia_cufft_cu12-11.0.2.54-py3-none-manylinux1_x86_64.whl (121.6 MB)
|████████████████████████████████| 121.6 MB 4.2 MB/s
Collecting filelock
Downloading filelock-3.15.4-py3-none-any.whl (16 kB)
Collecting jinja2
Downloading jinja2-3.1.4-py3-none-any.whl (133 kB)
|████████████████████████████████| 133 kB 6.7 MB/s
Collecting nvidia-cuda-cupti-cu12==12.1.105
Downloading nvidia_cuda_cupti_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (14.1 MB)
|████████████████████████████████| 14.1 MB 922 kB/s
Collecting nvidia-nvtx-cu12==12.1.105
Downloading nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (99 kB)
|████████████████████████████████| 99 kB 1.1 MB/s
Collecting nvidia-cudnn-cu12==9.1.0.70
Downloading nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl (664.8 MB)
|████████████████████████████████| 664.8 MB 6.0 kB/s
Collecting typing-extensions>=4.8.0
Downloading typing_extensions-4.12.2-py3-none-any.whl (37 kB)
Collecting fsspec
Downloading fsspec-2024.6.1-py3-none-any.whl (177 kB)
|████████████████████████████████| 177 kB 4.6 MB/s
Collecting nvidia-cusolver-cu12==11.4.5.107
Downloading nvidia_cusolver_cu12-11.4.5.107-py3-none-manylinux1_x86_64.whl (124.2 MB)
|████████████████████████████████| 124.2 MB 1.5 MB/s
Collecting nvidia-cusparse-cu12==12.1.0.106
Downloading nvidia_cusparse_cu12-12.1.0.106-py3-none-manylinux1_x86_64.whl (196.0 MB)
|████████████████████████████████| 196.0 MB 3.7 MB/s
Collecting nvidia-cublas-cu12==12.1.3.1
Downloading nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl (410.6 MB)
|████████████████████████████████| 410.6 MB 3.0 kB/s
Collecting networkx
Downloading networkx-3.2.1-py3-none-any.whl (1.6 MB)
|████████████████████████████████| 1.6 MB 841 kB/s
Collecting triton==3.0.0
Downloading triton-3.0.0-1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (209.4 MB)
|████████████████████████████████| 209.4 MB 157 kB/s
Collecting sympy
Downloading sympy-1.13.2-py3-none-any.whl (6.2 MB)
|████████████████████████████████| 6.2 MB 1.1 MB/s
Collecting nvidia-curand-cu12==10.3.2.106
Downloading nvidia_curand_cu12-10.3.2.106-py3-none-manylinux1_x86_64.whl (56.5 MB)
|████████████████████████████████| 56.5 MB 279 kB/s
Collecting nvidia-nccl-cu12==2.20.5
Downloading nvidia_nccl_cu12-2.20.5-py3-none-manylinux2014_x86_64.whl (176.2 MB)
|████████████████████████████████| 176.2 MB 45 kB/s
Collecting nvidia-cuda-nvrtc-cu12==12.1.105
Downloading nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (23.7 MB)
|████████████████████████████████| 23.7 MB 1.8 MB/s
Collecting nvidia-cuda-runtime-cu12==12.1.105
Downloading nvidia_cuda_runtime_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (823 kB)
|████████████████████████████████| 823 kB 2.8 MB/s
Collecting nvidia-nvjitlink-cu12
Downloading nvidia_nvjitlink_cu12-12.6.68-py3-none-manylinux2014_x86_64.whl (19.7 MB)
|████████████████████████████████| 19.7 MB 711 kB/s
Collecting MarkupSafe>=2.0
Downloading MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (25 kB)
Collecting mpmath<1.4,>=1.1.0
Downloading mpmath-1.3.0-py3-none-any.whl (536 kB)
|████████████████████████████████| 536 kB 2.4 MB/s
Installing collected packages: nvidia-nvjitlink-cu12, nvidia-cusparse-cu12, nvidia-cublas-cu12, mpmath, MarkupSafe, filelock, typing-extensions, triton, sympy, nvidia-nvtx-cu12, nvidia-nccl-cu12, nvidia-cusolver-cu12, nvidia-curand-cu12, nvidia-cufft-cu12, nvidia-cudnn-cu12, nvidia-cuda-runtime-cu12, nvidia-cuda-nvrtc-cu12, nvidia-cuda-cupti-cu12, networkx, jinja2, fsspec, torch
Successfully installed MarkupSafe-2.1.5 filelock-3.15.4 fsspec-2024.6.1 jinja2-3.1.4 mpmath-1.3.0 networkx-3.2.1 nvidia-cublas-cu12-12.1.3.1 nvidia-cuda-cupti-cu12-12.1.105 nvidia-cuda-nvrtc-cu12-12.1.105 nvidia-cuda-runtime-cu12-12.1.105 nvidia-cudnn-cu12-9.1.0.70 nvidia-cufft-cu12-11.0.2.54 nvidia-curand-cu12-10.3.2.106 nvidia-cusolver-cu12-11.4.5.107 nvidia-cusparse-cu12-12.1.0.106 nvidia-nccl-cu12-2.20.5 nvidia-nvjitlink-cu12-12.6.68 nvidia-nvtx-cu12-12.1.105 sympy-1.13.2 torch-2.4.0 triton-3.0.0 typing-extensions-4.12.2
```
### PHP代码实现
让我们首先来看一下如何在 PHP 中实现 ViT 模型。以下是一个完整的 PHP 实现,利用了`phpy`扩展来调用 PyTorch:
```php
<?php
declare(strict_types=1);
/**
* Vit类定义了Vision Transformer(ViT)的结构
*/
class Vit
{
// 定义模型的各类属性,包括嵌入大小、patch大小、patch数量,以及各种层和token
private mixed $emb_size;
private int $patch_size;
private int $patch_count;
private $conv;
private $patch_emb;
private $cls_token;
private $pos_emb;
private $tranformer_enc;
private $cls_linear;
private $torch; // 存储导入的torch模块
private $nn; // 存储导入的nn模块
/**
* 构造函数初始化模型参数和层结构
* @param int $emb_size 嵌入的大小,默认为16
*/
public function __construct($emb_size = 16)
{
$this->torch = PyCore::import('torch');
$this->nn = PyCore::import('torch.nn');
$this->emb_size = $emb_size;
$this->patch_size = 4;
$this->patch_count = intdiv(28, $this->patch_size); // 计算patch的数量
$this->conv = $this->nn->Conv2d(
in_channels: 1,
out_channels: pow($this->patch_size, 2),
kernel_size: $this->patch_size,
padding: 0,
stride: $this->patch_size,
);
$this->patch_emb = $this->nn->Linear(pow($this->patch_size, 2), $this->emb_size);
$this->cls_token = $this->torch->randn([1, 1, $this->emb_size]);
$this->pos_emb = $this->torch->randn([1, pow($this->patch_count, 2) + 1, $this->emb_size]);
$encoder_layer = $this->nn->TransformerEncoderLayer($this->emb_size, 2,
dim_feedforward: 2 * $this->emb_size,
dropout: 0.1,
activation: 'relu',
layer_norm_eps: 1e-5,
batch_first: true
);
$this->tranformer_enc = $this->nn->TransformerEncoder($encoder_layer, 3);
$this->cls_linear = $this->nn->Linear($this->emb_size, 10);
}
/**
* 定义模型的前向传播过程
* @param mixed $x 输入的数据
* @return mixed 模型的输出
*/
public function forward($x)
{
$operator = \PyCore::import('operator');
$x = $this->conv->forward($x);
$batch_size = $x->size(0);
$out_channels = $x->size(1);
$height = $x->size(2);
$width = $x->size(3);
$x = $x->view($batch_size, $out_channels, $height * $width);
$x = $x->permute([0, 2, 1]);
$x = $this->patch_emb->forward($x);
$cls_token = $this->cls_token->expand([$x->size(0), 1, $x->size(2)]);
$x = $this->torch->cat([$cls_token, $x], 1);
$x = $operator->__add__($x, $this->pos_emb);
$x = $this->tranformer_enc->forward($x);
return $this->cls_linear->forward($x->select(1, 0));
}
}
// 导入torch库,用于后续的深度学习操作
$torch = PyCore::import('torch');
// 初始化ViT模型实例,ViT是一种Vision Transformer模型
$vit = new ViT();
// 生成一个随机输入张量,形状为(5, 1, 28, 28),通常用于模拟一批图像数据
$x = $torch->rand(5, 1, 28, 28);
// 通过ViT模型的forward方法对输入$x进行前向传播,得到输出$y
$y = $vit->forward($x);
// 打印前向传播的结果
PyCore::print($y);
```
执行代码打印结果
```
# php ViT.php
tensor([[ 1.4124e-01, -2.2445e-01, -4.8343e-02, 1.0453e+00, 2.6407e-01,
-1.0721e+00, -4.5355e-01, 9.3695e-01, 2.0814e-01, -6.9242e-01],
[ 1.3197e-01, -1.7860e-01, -3.5619e-02, 1.0052e+00, 3.5701e-01,
-1.0619e+00, -5.5952e-01, 8.9957e-01, 2.2079e-01, -7.3373e-01],
[ 7.5269e-04, -1.9265e-01, -2.2268e-02, 9.1797e-01, 4.4237e-01,
-9.6516e-01, -5.3235e-01, 1.0040e+00, 1.9907e-01, -8.6913e-01],
[ 4.2739e-02, -1.3659e-01, -1.5089e-01, 9.2313e-01, 2.9609e-01,
-1.0178e+00, -3.7121e-01, 9.5373e-01, 1.0967e-01, -7.0122e-01],
[-1.1353e-01, -4.2927e-02, -5.9407e-02, 1.1204e+00, 1.0559e-01,
-1.1278e+00, -2.8934e-01, 1.0370e+00, 2.5948e-01, -8.9551e-01]],
grad_fn=<AddmmBackward0>)
```
在上面的代码中,`phpy`的`PyCore::import()`方法使我们能够在 PHP 中导入和使用 PyTorch 模块,例如`torch`和`torch.nn`。这一点使得 PHP 可以直接调用 Python 代码,从而实现复杂的深度学习模型。
例如:在构建 ViT 模型的过程中,我们在 PHP 中使用了 Python 的`torch.nn.Conv2d`和`torch.nn.Linear`等模块,这些模块在深度学习模型的构建中起到了至关重要的作用。
### Python代码实现
对比`vit.py`中的 Python 代码,PHP 版本的代码结构和逻辑几乎完全相同。这归功于`phpy`让我们能够在 PHP 中直接使用 Python 的语法和模块,实现了代码的高度一致性和可移植性。
```python
from torch import nn
import torch
class ViT(nn.Module):
def __init__(self, emb_size=16):
super().__init__()
self.patch_size = 4
self.patch_count = 28 // self.patch_size
self.conv = nn.Conv2d(in_channels=1, out_channels=self.patch_size ** 2, kernel_size=self.patch_size, padding=0,
stride=self.patch_size)
self.patch_emb = nn.Linear(in_features=self.patch_size ** 2, out_features=emb_size)
self.cls_token = nn.Parameter(torch.rand(1, 1, emb_size))
self.pos_emb = nn.Parameter(torch.rand(1, self.patch_count ** 2 + 1, emb_size))
self.tranformer_enc = nn.TransformerEncoder(
nn.TransformerEncoderLayer(d_model=emb_size, nhead=2, batch_first=True), num_layers=3)
self.cls_linear = nn.Linear(in_features=emb_size, out_features=10)
def forward(self, x):
x = self.conv(x)
x = x.view(x.size(0), x.size(1), self.patch_count ** 2)
x = x.permute(0, 2, 1)
x = self.patch_emb(x)
cls_token = self.cls_token.expand(x.size(0), 1, x.size(2))
x = torch.cat((cls_token, x), dim=1)
x = self.pos_emb + x
y = self.tranformer_enc(x)
return self.cls_linear(y[:, 0, :])
if __name__ == '__main__':
vit = ViT()
x = torch.rand(5, 1, 28, 28)
y = vit(x)
print(y.shape)
```
## phpy的应用场景与意义
在实际开发中,PHP 常用于 Web 开发,但缺乏原生的深度学习支持。这使得在 PHP 项目中实现复杂的机器学习模型成为一项挑战。然而,借助`phpy`,我们可以直接调用 Python 的深度学习框架(如 PyTorch 和 TensorFlow),从而将复杂的 AI 算法无缝集成到 PHP 应用中。
这不仅扩展了 PHP 的应用范围,也为 PHP 开发者提供了更多的可能性。例如,在构建需要实时预测或复杂计算的 Web 应用时,PHP 开发者可以直接利用 Python 的丰富生态系统,而不必重新实现这些算法。
## 结语
通过`phpy`,我们可以轻松地在 PHP 中实现 Python 的深度学习模型,如 ViT。这不仅展示了 PHP 的灵活性,也为 PHP 开发者打开了通往深度学习领域的大门。在未来,随着 AI 技术的不断发展,PHP 与 Python 的结合将为开发者带来更多创新的机会。
- 设计模式系列
- 工厂方法模式
- 序言
- Windows程序注册为服务的工具WinSW
- 基础
- 安装
- 开发规范
- 目录结构
- 配置
- 快速入门
- 架构
- 请求流程
- 架构总览
- URL访问
- 容器和依赖注入
- 中间件
- 事件
- 代码层结构
- 四个层次
- 路由
- 控制器
- 请求
- 响应
- 数据库
- MySQL实时同步数据到ES解决方案
- 阿里云DTS数据MySQL同步至Elasticsearch实战
- PHP中的MySQL连接池
- PHP异步非阻塞MySQL客户端连接池
- 模型
- 视图
- 注解
- @SpringBootApplication(exclude={DataSourceAutoConfiguration.calss})
- @EnableFeignClients(basePackages = "com.wotu.feign")
- @EnableAspectJAutoProxy
- @EnableDiscoveryClient
- 错误和日志
- 异常处理
- 日志处理
- 调试
- 验证
- 验证器
- 验证规则
- 扩展库
- 附录
- Spring框架知识体系详解
- Maven
- Maven和Composer
- 构建Maven项目
- 实操课程
- 01.初识SpringBoot
- 第1章 Java Web发展史与学习Java的方法
- 第2章 环境与常见问题踩坑
- 第3章 springboot的路由与控制器
- 02.Java编程思想深度理论知识
- 第1章 Java编程思想总体
- 第2章 英雄联盟的小案例理解Java中最为抽象的概念
- 第3章 彻底理解IOC、DI与DIP
- 03.Spring与SpringBoot理论篇
- 第1章 Spring与SpringBoot导学
- 第2章 Spring IOC的核心机制:实例化与注入
- 第3章 SpringBoot基本配置原理
- 04.SprinBoot的条件注解与配置
- 第1章 conditonal 条件注解
- 第2章 SpringBoot自动装配解析
- 05.Java异常深度剖析
- 第1章 Java异常分类剖析与自定义异常
- 第2章 自动配置Url前缀
- 06.参数校验机制与LomBok工具集的使用
- 第1章 LomBok工具集的使用
- 第2章 参数校验机制以及自定义校验
- 07.项目分层设计与JPA技术
- 第1章 项目分层原则与层与层的松耦合原则
- 第2章 数据库设计、实体关系与查询方案探讨
- 第3章 JPA的关联关系与规则查询
- 08.ORM的概念与思维
- 第1章 ORM的概念与思维
- 第2章 Banner等相关业务
- 第3章 再谈数据库设计技巧与VO层对象的技巧
- 09.JPA的多种查询规则
- 第1章 DozerBeanMapper的使用
- 第2章 详解SKU的规格设计
- 第3章 通用泛型Converter
- 10.令牌与权限
- 第1章 通用泛型类与java泛型的思考
- 常见问题
- 微服务
- demo
- PHP中Self、Static和parent的区别
- Swoole-Cli
- 为什么要使用现代化PHP框架?
- 公众号
- 一键部署微信公众号Markdown编辑器(支持适配和主题设计)
- Autodesigner 2.0发布
- Luya 一个现代化PHP开发框架
- PHPZip - 创建、读取和管理 ZIP 文件的简单库
- 吊打Golang的PHP界天花板webman压测对比
- 简洁而强大的 YAML 解析库
- 推荐一个革命性的PHP测试框架:Kahlan
- ServBay下一代Web开发环境
- 基于Websocket和Canvas实现多人协作实时共享白板
- Apipost预执行脚本如何调用外部PHP语言
- 认证和授权的安全令牌 Bearer Token
- Laradock PHP 的 Docker 完整本地开发环境
- 高效接口防抖策略,确保数据安全,避免重复提交的终极解决方案!
- TIOBE 6月榜单:PHP稳步前行,编程语言生态的微妙变化
- Aho-Corasick字符串匹配算法的实现
- Redis键空间通知 Keyspace Notification 事件订阅
- ServBay如何启用并运行Webman项目
- 使用mpdf实现导出pdf文件功能
- Medoo 轻量级PHP数据库框架
- 在PHP中编写和运行单元测试
- 9 PHP运行时基准性能测试
- QR码生成器在PHP中的源代码
- 使用Gogs极易搭建的自助Git服务
- Gitea
- webman如何记录SQL到日志?
- Sentry PHP: 实时监测并处理PHP应用程序中的错误
- Swoole v6 Alpha 版本已发布
- Proxypin
- Rust实现的Redis内存数据库发布
- PHP 8.4.0 Alpha 1 测试版本发布
- 121
- Golang + Vue 开发的开源轻量 Linux 服务器运维管理面板
- 内网穿透 FRP VS Tailscale
- 新一代开源代码托管平台Gitea
- 微服务系列
- Nacos云原生配置中心介绍与使用
- 轻量级的开源高性能事件库libevent
- 国密算法
- 国密算法(商用密码)
- GmSSL 支持国密SM2/SM3/SM4/SM9/SSL 密码工具箱
- GmSSL PHP 使用
- 数据库
- SQLite数据库的Web管理工具
- 阿里巴巴MySQL数据库强制规范
- PHP
- PHP安全测试秘密武器 PHPGGC
- 使用declare(strict_types=1)来获得更健壮的PHP代码
- PHP中的魔术常量
- OSS 直传阿里腾讯示例
- PHP源码编译安装APCu扩展实现数据缓存
- BI性能DuckDB数据管理系统
- 为什么别人可以是架构师!而我却不是?
- 密码还在用 MD5 加盐?不如试试 password_hash
- Elasticsearch 在电商领域的应用与实践
- Cron 定时任务入门
- 如何动态设置定时任务!而不是写死在Linux Crontab
- Elasticsearch的四种查询方式,你知道多少?
- Meilisearch vs Elasticsearch
- OpenSearch vs Elasticsearch
- Emlog 轻量级开源博客及建站系统
- 现代化PHP原生协程引擎 PRipple
- 使用Zephir编写C扩展将PHP源代码编译加密
- 如何将PHP源代码编译加密,同时保证代码能正常的运行
- 为什么选择Zephir给PHP编写动态扩展库?
- 使用 PHP + XlsWriter实现百万级数据导入导出
- Rust编写PHP扩展
- 阿里云盘开放平台对接进行文件同步
- 如何构建自己的PHP静态可执行文件
- IM后端架构
- RESTful设计方法和规范
- PHP编译器BPC 7.3 发布,成功编译ThinkPHP8
- 高性能的配置管理扩展 Yaconf
- PHP实现雪花算法库 Snowflake
- PHP官方现代化核心加密库Sodium
- pie
- 现代化、精简、非阻塞PHP标准库PSL
- PHP泛型和集合
- 手把手教你正确使用 Composer包管理
- JWT双令牌认证实现无感Token自动续期
- 最先进PHP大模型深度学习库TransformersPHP
- PHP如何启用 FFI 扩展
- PHP超集语言PXP
- 低延迟双向实时事件通信 Socket.IO
- PHP OOP中的继承和多态
- 强大的现代PHP高级调试工具Kint
- PHP基金会
- 基于webman+vue3高质量中后台框架SaiAdmin
- 开源免费的定时任务管理系统:Gocron
- 简单强大OCR工具EasyOCR在PHP中使用
- PHP代码抽象语法树工具PHP AST Viewer
- MySQL数据库管理工具PHPMyAdmin
- Rust编写的一款高性能多人代码编辑器Zed
- 超高性能PHP框架Workerman v5.0.0-beta.8 发布
- 高并发系列
- 入门介绍及安装
- Lua脚本开发 Hello World
- 执行流程与阶段详解
- Nginx Lua API 接口开发
- Lua模块开发
- OpenResty 高性能的正式原因
- 记一次查找 lua-resty-mysql 库 insert_id 的 bug
- 包管理工具OPM和LuaRocks使用
- 异步非阻塞HTTP客户端库 lua-resty-http
- Nginx 内置绑定变量
- Redis协程网络库 lua-resty-redis
- 动态HTML渲染库 lua-testy-template
- 单独的
- StackBlitz在线开发环境
- AI
- 基础概念
- 12312
- 基础镜像的坑
- 利用phpy实现 PHP 编写 Vision Transformer (ViT) 模型
- 语义化版本 2.0.0