中国海洋大学26秋《软件工程原理与实践》实验2:深度学习基础
一、实验内容1、pytorch 基础练习首先根据教程创建好 Colab 环境每次使用时都要先挂载 Google Drive从而访问 Google Drive 中的文件。from google.colab import drive drive.mount(/content/drive/)1定义数据一般定义数据使用 torch.Tensortensor的意思是张量是数字各种形式的总称import torch # 可以是一个数 x torch.tensor(666) print(x)import torch # 可以是一维数组向量 x torch.tensor([1, 2, 3, 4, 5, 6]) print(x)import torch # 可以是二维数组矩阵 x torch.ones(2, 3) print(x)import torch # 可以是任意维度的数组张量 x torch.ones(2,3,4) print(x)Tensor支持各种各样类型的数据包括:torch.float32torch.float64 torch.float16 torch.uint8torch.int8torch.int16torch.int32torch.int64 。创建Tensor有多种方法包括:oneszeroseyearangelinspacerandrandn normaluniformrandperm下面主要通过代码展示。import torch # 创建一个空张量 x torch.empty(5,3) print(x)import torch #创建一个随机初始化的张量 x torch.rand(5,3) print(x)import torch #创建一个全0的张量里面的数据类型为long x torch.zeros(5,3,dtypetorch.long) print(x)import torch #基于现有的tensor创建一个新的tensor #从而可以利用原有的tensor的的typedevicesize之类的属性信息 x torch.zeros(5,3,dtypetorch.long) y x.new_ones(5,3) print(y) ​ #利用原来的tensor的大小但是重新定义了dtype z torch.randn_like(x,dtypetorch.float) print(z)2定义操作计算操作基本运算加减乘除求幂求余布尔运算大于小于最大最小线性运算矩阵乘法求模求行列式基本运算abs /sqrt /div /exp /fmod /pow 及一些三角函数 cos /sin /asin /atan2 /cosh及 ceil /round /floor /trunc 等布尔运算gt /lt /ge /le /eq /netopk, sort, max /min线性运算trace, diag, mm /bmmtdot/crossinversesvd 等下面为具体操作案例import torch #创建一个2*4的tensor m torch.Tensor([[2,5,3,7], [4,2,1,9]]) print(m.size(0),m.size(1),m.size(),sep - )size()用于获取张量的形状。m.size(0)表示第 0 维的大小m.size()返回完整的形状信息import torch ​ m torch.tensor([[2,5,3,7], [4,2,1,9]]) ​ # 获取张量中元素的总数量 print(m.numel()) # 获取第 0 行、第 2 列的元素 print(m[0][2]) # 获取第 1 行的全部元素 print(m[1, :]) # 获取第 0 列的全部元素 print(m[:, 0])import torch ​ #Create tensor of numbers from 1 to 5 #注意这里结果是1到4没有5 v torch.arange(1,5) print(v)import torch ​ v torch.arange(1,5,,dtypetorch.float32) m torch.Tensor([[2,5,3,7], [4,2,1,9]]) ​ # Scalar product # m 和 v 的类型一样才可以使用 否则会报错 m v# Calculated by 1*2 2*5 3*3 4*7 m[[0],:] v# Add a random tensor of size 2*4 to m m torch.rand(2,4)#转置由2*4变为4*2 print(m.t()) ​ #使用transpose也可以达到相同效果 print(m.transpose(0,1))import torch #returns a 1D tensor of steps equally spaced points between start3 end8 and steps20 #返回一个一维向量从3开始8结束共20个 torch.linspace(3,8,20)from matplotlib import pyplot as plt ​ # matlabplotlib只能显示numpy类型的数据下面展示了转换数据类型然后显示 # 注意randn是生成均值为0,方差为1的随机数 # 下面是生成1000个随机数并按照100个bin统计直方图 plt.hist(torch.randn(1000).numpy(),100)# 当数据非常多的时候正态分布会体现的非常明显 plt.hist(torch.randn(10**6).numpy(),100)import torch # 创建两个 1*4 的tensor a torch.Tensor([[1,2,3,4]]) b torch.Tensor([[5,6,7,8]]) ​ # 在0方向拼接即在Y方向上拼接会得到 2*4 的矩阵 print(torch.cat((a,b),0)) ​ # 在1方向拼接即在X方向上拼接会得到 1*8 的矩阵 print(torch.cat((a,b),1))torch.cat()用于沿指定维度拼接多个张量。并且参与拼接的张量除拼接维度外其余维度的大小必须一致。2、螺旋数据分类1运行代码下载绘图函数到本地!wget https://raw.githubusercontent.com/Atcold/NYU-DLSP21/refs/heads/master/res/plot_lib.py2引入基本的库然后初始化重要参数import random import torch from torch import nn, optim import math from IPython import display from plot_lib import plot_data, plot_model, set_default ​ # 因为colab是支持GPU的torch 将在 GPU 上运行 device torch.device(cuda:0 if torch.cuda.is_available() else cpu) print(device: , device) ​ # 初始化随机数种子。神经网络的参数都是随机初始化的 # 不同的初始化参数往往会导致不同的结果当得到比较好的结果时我们通常希望这个结果是可以复现的 # 因此在pytorch中通过设置随机数种子也可以达到这个目的 seed 12345 random.seed(seed) torch.manual_seed(seed) ​ N 1000 # 每类样本的数量 D 2 # 每个样本的特征维度 C 3 # 样本的类别 H 100 # 神经网络里隐层单元的数量3初始化 X 和 YX 可以理解为特征矩阵Y可以理解为样本标签。结合代码可以看到X的为一个 NxC 行 D 列的矩阵。C 类样本每类样本是 N个所以是 N*C 行。每个样本的特征维度是2所以是 2列。在 python 中调用 zeros 类似的函数第一个参数是 y方向的即矩阵的行第二个参数是 x方向的即矩阵的列大家得注意下不要搞反了。下面结合代码看看 3000个样本的特征是如何初始化的。X torch.zeros(N * C, D).to(device) Y torch.zeros(N * C, dtypetorch.long).to(device) for c in range(C): index 0 t torch.linspace(0, 1, N) # 在[01]间均匀的取10000个数赋给t # 下面的代码不用理解太多总之是根据公式计算出三类样本可以构成螺旋形 # torch.randn(N) 是得到 N 个均值为0方差为 1 的一组随机数注意要和 rand 区分开 inner_var torch.linspace( (2*math.pi/C)*c, (2*math.pi/C)*(2c), N) torch.randn(N) * 0.2 ​ # 每个样本的(x,y)坐标都保存在 X 里 # Y 里存储的是样本的类别分别为 [0, 1, 2] for ix in range(N * c, N * (c 1)): X[ix] t[index] * torch.FloatTensor((math.sin(inner_var[index]), math.cos(inner_var[index]))) Y[ix] c index 1 ​ print(Shapes:) print(X:, X.size()) print(Y:, Y.size())# visualise the data plot_data(X,Y)4构建线性模型分类learning_rate 1e-3 lambda_l2 1e-5 # nn包用来创建线性模型 # 每一个线性模型都包含weight和bias model nn.Sequential( nn.Linear(D, H), nn.Linear(H, C) ) #把模型放到GPU上 model.to(device) # nn包含多种不同的损失函数这里使用的是交叉(cross entropy loss)损失函数 criterion torch.nn.CrossEntropyLoss() ​ #这里使用optim包进行随机梯度下降(stochastic gradient descent)优化 optimizer torch.optim.SGD(model.parameters(), lrlearning_rate, weight_decaylambda_l2) ​ #开始训练 for t in range(1000): #把数据输入模型得到预测结果 y_pred model(X) #计算损失和准确率 loss criterion(y_pred,Y) score,predicted torch.max(y_pred,1) acc (Y predicted).sum().float() / len(Y) print([EPOCH]:%i, [LOSS]:%.6f, [ACCURACY]:%.3f % (t, loss.item(), acc)) display.clear_output(waitTrue) ​ # 反向传播前把梯度置0 optimizer.zero_grad() # 反向传播优化 loss.backward() # 更新全部参数 optimizer.step()使用 print(y_pred.shape) 可以看到模型的预测结果为[3000, 3]的矩阵。每个样本的预测结果为3个保存在 y_pred 的一行里。值最大的一个即为预测该样本属于的类别score, predicted torch.max(y_pred, 1) 是沿着第二个方向即X方向提取最大值。最大的那个值存在 score 中所在的位置即第几列的最大保存在 predicted 中。交叉熵损失函数用于衡量模型输出与真实类别之间的差异。随机梯度下降SGD优化器则根据反向传播计算得到的梯度更新模型参数。由于 PyTorch 在每次反向传播时会把梯度累加到上一次的梯度上不会自动清零。所以在每次反向传播前都要把梯度置0即optimizer.zero_grad()这样可以保证每次更新都只用当前批次的梯度。下面代码把第10行的情况输出供解释说明。print(y_pred.shape) print(y_pred[10,:]) print(score[10]) print(predicted[10])# Plot trained model print(model) plot_model(X,Y,model)上面使用 print(model) 把模型输出可以看到有两层第一层输入为 2因为特征维度为主2输出为 100第二层输入为 100 上一层的输出输出为 3类别数该模型包含两层线性变换但由于两层之间没有加入非线性激活函数因此两个线性变换的组合仍然等价于一个线性变换。而且从上面图示可以看出线性模型的准确率最高只能达到 50% 左右对于这样复杂的一个数据分布线性模型难以实现准确分类。5构建两层神经网络分类learning_rate 1e-3 lambda_l2 1e-5 # 这里可以看到和上面模型不同的是在两层之间加入了一个 ReLU 激活函数 model nn.Sequential( nn.Linear(D, H), nn.ReLU(), nn.Linear(H, C) ) model.to(device) ​ # 下面的代码和之前是完全一样的这里不过多叙述 criterion torch.nn.CrossEntropyLoss() optimizer torch.optim.Adam(model.parameters(), lrlearning_rate, weight_decaylambda_l2) # built-in L2# 训练模型和之前的代码是完全一样的 for t in range(1000): y_pred model(X) loss criterion(y_pred, Y) score, predicted torch.max(y_pred, 1) acc ((Y predicted).sum().float() / len(Y)) print([EPOCH]: %i, [LOSS]: %.6f, [ACCURACY]: %.3f % (t, loss.item(), acc)) display.clear_output(waitTrue) # zero the gradients before running the backward pass. optimizer.zero_grad() # Backward pass to compute the gradient loss.backward() # Update params optimizer.step()# Plot trained modelprint(model) plot_model(X, Y, model)加入 ReLU 激活函数以后分类的准确率得到了显著提高。说明面对具有复杂非线性结构的数据仅使用线性变换往往难以获得理想的分类效果。通过在隐藏层中加入非线性激活函数模型的表达能力得到增强更容易学习螺旋形数据对应的复杂决策边界。二、问题总结与体会思考题1、AlexNet有哪些特点为什么可以比 LeNet 取得更好的性能特点网络结构更深、规模更大相比 LeNetAlexNet 拥有更多的卷积层和全连接层能够提取更复杂的图像特征。使用 ReLU 激活函数相较于 Sigmoid 等传统激活函数ReLU 能够缓解梯度消失问题加快训练速度。使用 Dropout在训练过程中随机屏蔽部分神经元降低神经元之间的过度依赖缓解过拟合。使用重叠最大池化池化窗口大于步长有助于提取显著特征。利用 GPU 加速训练能够处理更大规模的网络和数据。使用数据增强通过随机裁剪、翻转等方式扩充训练数据提高模型的泛化能力。AlexNet 比 LeNet 性能更好的主要原因是它具有更强的特征提取能力采用了 ReLU、Dropout 和数据增强等技术并借助 GPU 提高了训练效率因此能够更有效地处理复杂的大规模图像分类任务。2、激活函数有哪些作⽤激活函数的主要作用是为神经网络引入非线性能力。如果网络中只有线性变换那么无论叠加多少层整体仍然可以表示为一个线性变换难以学习复杂的数据关系。激活函数不仅影响网络的表达能力也会影响梯度传播和训练效率。3、梯度消失现象是什么梯度消失是指在神经网络反向传播过程中梯度随着层数增加而逐渐变小甚至接近于 0的现象。在反向传播中梯度需要经过多层求导结果的连乘。如果激活函数的导数较小多个较小的数相乘后就可能使梯度非常微弱导致靠近输入端的网络层参数更新缓慢难以有效学习特征。4、神经网络是更宽好还是更深好神经网络的宽度指每层神经元的数量深度指网络的层数。更宽和更深各有优势不能简单地认为其中一种一定更好。更宽的网络单层可以容纳更多神经元增强特征表示能力但参数量和计算开销可能增加。更深的网络能够逐层组合特征从简单特征逐步学习更抽象、复杂的特征通常具有较强的特征表达能力但训练难度也可能更高。网络过深或过宽都可能增加计算成本和过拟合风险。因此应根据任务复杂度、训练数据量、计算资源和模型效果选择合适的深度与宽度而不是一味增加层数或神经元数量。5、为什么要使⽤Softmax?Softmax 常用于多分类神经网络的输出层主要作用是将模型输出的原始得分Logits转换为一个概率分布。转换为概率分布每个类别的输出都在 0 到 1 之间且所有类别的概率之和为 1。便于进行多分类预测通常选择概率最大的类别作为预测结果。配合交叉熵损失函数训练模型衡量预测结果与真实标签之间的差异引导模型调整参数。6、SGD 和 Adam 哪个更有效SGD 和 Adam 都是常见的梯度优化算法各有优缺点没有一种算法在所有任务中都一定更有效。比较方面SGDAdam基本原理根据梯度更新参数结合梯度的一阶矩和二阶矩估计自适应调整学习率学习率通常需要仔细调整每个参数具有自适应的更新步长收敛速度可能较慢对学习率较敏感通常前期收敛较快计算与存储开销相对较小需要额外存储梯度的统计量泛化表现在部分任务中可能获得更好的泛化效果训练初期通常较方便但最终泛化效果依赖任务和设置如果希望训练过程更方便、较快地取得初步结果Adam 通常是不错的选择。如果追求特定任务上的泛化性能并且能够调整学习率和训练策略SGD 也可能取得更好的结果。收获和体会通过本次实验我学习了 PyTorch 中张量的创建、索引、拼接、转置和矩阵乘法等基本操作也熟悉了神经网络从数据构建、模型定义、损失计算到反向传播训练的完整流程对神经网络的实际运行过程有了更具体的体会。在螺旋数据分类实验中线性模型的准确率只有 50% 左右而加入 ReLU 激活函数后分类效果显著提升。通过对比可以发现线性模型虽然结构简单但由于层与层之间没有非线性激活函数最终仍然等价于一个线性变换因此面对螺旋形这种复杂数据分布时准确率只能停留在较低水平。而在加入 ReLU 激活函数后模型的分类准确率明显提高决策边界也能够更好地适应数据的非线性结构。这让我深刻体会到激活函数在神经网络中的关键作用它不仅增强了模型的表达能力也使神经网络能够拟合更加复杂的函数关系。此外通过思考题我对 AlexNet、激活函数、梯度消失、网络宽度与深度、Softmax 以及 SGD 与 Adam 的区别有了更系统的认识。总的来说这次实验让我对神经网络的结构设计、优化方法及训练细节都有了更清晰的认识为后续更深入的深度学习课程与项目打下了坚实基础。

相关新闻

WAMR 入门指南:WebAssembly 运行时基础、架构组成与安全机制全解析

WAMR 入门指南:WebAssembly 运行时基础、架构组成与安全机制全解析

语言运行时嵌入式物联网 【免费下载链接】wasm-micro-runtime WebAssembly Micro Runtime (WAMR) 项目地址: https://gitcode.com/gh_mirrors/wa/wasm-micro-runtime 点击查看 免费下载 WebAssembly Micro Runtime(WAMR)是一个轻量级、可高度…

2026/10/11 12:00:28 阅读更多 →
GDAL 开发实践指南:从变更流程、命名规范与内存安全到 Git 提交流程和源码布局

GDAL 开发实践指南:从变更流程、命名规范与内存安全到 Git 提交流程和源码布局

GIS遥感数据工程 【免费下载链接】gdal GDAL is an open source MIT licensed translator library for raster and vector geospatial data formats. 项目地址: https://gitcode.com/gh_mirrors/gd/gdal 点击查看 免费下载 本文以 doc/source/development/dev_prac…

2026/10/11 12:00:13 阅读更多 →
Weblate 的 Flat XML 文件格式:从组件配置到自定义标签结构解析

Weblate 的 Flat XML 文件格式:从组件配置到自定义标签结构解析

后端开发工具 【免费下载链接】weblate Web based localization tool with tight version control integration. 项目地址: https://gitcode.com/gh_mirrors/we/weblate 点击查看 免费下载 本篇技术指南以 Weblate 官方文档 docs/formats/flatxml.rst 为骨架&#…

2026/10/11 12:53:42 阅读更多 →

最新新闻

基于SSM+Vue的流浪动物领养助养系统毕业设计全流程解析

基于SSM+Vue的流浪动物领养助养系统毕业设计全流程解析

去年秋招失败后的那段时间,我每天从学校回出租屋都要绕路经过一家流浪动物救助站。救助站的负责人是个四十多岁的大姐,她给我看了三本厚得像字典的纸质登记册,里面密密麻麻写着编号、转账记录、领养人电话。她说他们最缺的不是爱心&#xff0…

2026/10/12 15:03:44 阅读更多 →
微信官方 Bot API 开放后,ClawBot 插件如何用 TaoToken 统一 Key 接入 AI 能力

微信官方 Bot API 开放后,ClawBot 插件如何用 TaoToken 统一 Key 接入 AI 能力

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 15:03:44 阅读更多 →
OpenClaw 正在重塑我的数字生活:从 SaaS 退订到 Mac Mini 本地推理的 TaoToken 实践

OpenClaw 正在重塑我的数字生活:从 SaaS 退订到 Mac Mini 本地推理的 TaoToken 实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 15:03:44 阅读更多 →
HyperFrames 爆火但别神化:确定性渲染救不了没创意,HTML 视频框架的边界到底在哪

HyperFrames 爆火但别神化:确定性渲染救不了没创意,HTML 视频框架的边界到底在哪

HyperFrames 爆火但别神化:确定性渲染救不了没创意,HTML 视频框架的边界到底在哪 【免费下载链接】hyperframes Write HTML. Render video. Built for agents. 项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes HyperFrames 火了。…

2026/10/12 15:03:44 阅读更多 →
Azkaban solo-server 0.1.0-SNAPSHOT 部署与工作流调度实战

Azkaban solo-server 0.1.0-SNAPSHOT 部署与工作流调度实战

简介:本资源为Azkaban单服务器版(Solo Server)0.1.0-SNAPSHOT的已编译tar.gz包,面向需要快速搭建工作流调度环境的小型团队、个人开发者及大数据初学者。Azkaban由LinkedIn开源,用于简化Hadoop作业调度,提供…

2026/10/12 15:03:44 阅读更多 →
编译原理实验一词法分析器:从状态图到Token识别的全解析

编译原理实验一词法分析器:从状态图到Token识别的全解析

简介:北邮编译原理课程词法分析器实验的完整源码包,面向正在学习编译原理的本科生,以编译器前端的关键环节为切入点,帮助理解扫描器如何将源代码字符流拆分为记号,并识别关键字、标识符、常量、运算符等词素。包内共4个…

2026/10/12 15:02:42 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →