当前位置: 首页 > news >正文

写作网站推荐seo页面如何优化

写作网站推荐,seo页面如何优化,网站仿制 个人,抖音怎么开通小程序推广课程3. 分批训练与数据规范、标准化 理论神经网络的梯度优化反向传播算法 批量训练网络输入的规范化BatchNorm 验证样本实践加载数据集网络构建训练神经网络 课程计划#xff1a; 1.理论#xff1a; 批量训练#xff1b; 输入数据的规范化#xff1b; 批量标准化#xff… 课程3. 分批训练与数据规范、标准化 理论神经网络的梯度优化反向传播算法 批量训练网络输入的规范化BatchNorm 验证样本实践加载数据集网络构建训练神经网络 课程计划 1.理论 批量训练 输入数据的规范化 批量标准化batchnorm ——验证样品 2.练习 在 PyTorch 上使用神经网络进行 MNIST 数字图像分类。 理论 神经网络的梯度优化 我们已经知道神经网络是使用基于梯度下降的反向传播算法进行训练的。其本质是通过计算损失 L L L对网络参数 ∂ L ∂ w i \frac{\partial L}{\partial w_i} ∂wi​∂L​的偏导数来持续改变神经网络参数的值。 我们来回忆一下神经网络训练算法的思路是什么样的 假设我们有一个神经网络 F F F一个由 n n n 个元素组成的数据集 { X i , Y i } i 0 n \{X_i, Y_i\}_{i0}^n {Xi​,Yi​}i0n​以及一个损失函数 l o s s loss loss。然后我们的任务就是找到这样的神经网络权重值使得数据集所有元素的损失函数 l o s s loss loss的平均值很小 L ∑ i 1 n l o s s ( y i , y ^ i ) n → m i n L \frac{∑^{n}_{i1} loss(y_i, \widehat{y}_i)}{n} \to min Ln∑i1n​loss(yi​,y ​i​)​→min 这里 y i y_i yi​是数据集中第i个元素的正确答案 y ^ i \widehat{y}_i y ​i​是神经网络对数据集中第 i i i个元素的答案。 梯度下降算法利用以下思想来帮助找到最佳权重 偏导数 ∂ L ∂ w i \frac{\partial L}{\partial w_i} ∂wi​∂L​ 的符号表示权重 w i w_i wi​ 应该向哪个方向移动以使损失值 L L L 变小偏导数 ∂ L ∂ w i \frac{\partial L}{\partial w_i} ∂wi​∂L​ 的模越大 w i w_i wi​ 的值距离最优值越远 神经网络的梯度优化算法如下所示 用随机值初始化所有网络权重 W i W_i Wi​和 b i b_i bi​。我们选择梯度下降步长 α \alpha α 的值直到满足停止标准为止执行以下操作 利用参数 W i W_i Wi​和 b i b_i bi​的当前值计算 L L L的值我们计算偏导数 ∂ L ∂ W i \frac{\partial L}{\partial W_i} ∂Wi​∂L​、 ∂ L ∂ b i \frac{\partial L}{\partial b_i} ∂bi​∂L​的值更新网络参数值 W i W i − α ∂ L ∂ W i , b i b i − α ∂ L ∂ b i W_i W_i - \alpha \frac{\partial L}{\partial W_i}, \ \ b_i b_i - \alpha \frac{\partial L}{\partial b_i} Wi​Wi​−α∂Wi​∂L​,  bi​bi​−α∂bi​∂L​ 停止标准可能有所不同。最合乎逻辑和最普遍的说法是当每次迭代或从一个时代到另一个时代的损失变化幅度变小时我们就停止。此外我们还监控过度训练如果开始过度训练我们就会停止算法。 反向传播算法 从之前的讲座中大家可以知道在标准梯度下降的基础上人们已经发明了大量的修改方法其中当今最流行、最有效的修改方法就是ADAMAdaptive Gradients with Momentum算法。对于每一种可能的梯度方法都会出现一个问题如何根据深度神经网络的参数有效地计算损失函数的梯度。问题是这样的为了对神经网络的所有权重进行自动微分需要计算最终函数的值计算次数与我们计算梯度的参数数量成线性比例。对于深度神经网络来说这个值可以达到数十亿、数千亿。有必要简化这一过程并学会在比使用标准数值方法计算导数更短的时间内计算模型所有参数的导数。为此有一个众所周知的算法叫做反向传播。 反向传播算法是一种将复杂函数的微分法则应用于神经网络层层逐次计算梯度的问题的方法。 为了方便起见我们引入以下符号和术语 我们将原始张量 X X X 在神经网络处理过程中的连续变换称为信号。对于每个完全连接的层经过线性变换处理但尚未输入到激活函数的信号值将被称为预激活并用 z z z 表示经过激活函数变换后该层的输出将被称为层 a a a的激活令 Q Q Q 表示要最小化的函数 L L L 表示层内线性变换的应用 层间信号转换由以下公式确定 z i 1 L i ( a i ) L i ( f i ( z i ) ) z_{i1} L_i(a_i) L_i(f_i(z_i)) zi1​Li​(ai​)Li​(fi​(zi​)) 其中 L i L_i Li​ 是定义第 i 层的线性变换即在基本情况下只是乘以某个矩阵 f i f_i fi​ 是第 i 层的激活函数。反向传播算法提出将损失函数Q关于第i层参数的导数展开如下 ∂ Q ∂ ω i ∂ Q ∂ z i 1 ∂ z i 1 ∂ ω i ∂ Q ∂ z i 1 ∂ z i 1 ∂ z i ∂ z i ∂ ω i \frac{∂ Q}{∂ ω_i} \frac{∂ Q}{∂ z_{i1}}\frac{∂ z_{i1}}{∂ ω_i} \frac{∂ Q}{∂ z_{i1}}\frac{∂ z_{i1}}{∂ z_i}\frac{∂ z_{i}}{∂ \omega_i} ∂ωi​∂Q​∂zi1​∂Q​∂ωi​∂zi1​​∂zi1​∂Q​∂zi​∂zi1​​∂ωi​∂zi​​ 该公式应这样理解此处的索引表示相应名称所指的层的编号。这里 ω i ω_i ωi​是第i层的任意参数也就是说这个公式对于定义第i个线性层的矩阵 W i W_i Wi​的任何元素都成立。 此外该公式中以下结论也成立 1对于最后一层计算关于参数和预激活的导数并不困难。它们的数量相当多并且不会花费太多时间。在标准分类和回归问题中最后一层只包含一个神经元。 2如果我们知道对第i1层预激活的导数那么根据最后一个公式我们不难计算出对第i层参数的导数。事实上 ∂ z i 1 ∂ z i \frac{∂ z_{i1}}{∂ z_i} ∂zi​∂zi1​​ 很容易表示因为 z i 1 W i 1 ⋅ f i ( z i ) z_{i1} W_{i1}⋅f_i(z_i) zi1​Wi1​⋅fi​(zi​)其中我们知道矩阵 W i W_i Wi​ 和函数 f i f_i fi​。我们还可以计算导数 ∂ z i ∂ ω i \frac{∂ z_{i}}{∂ \omega_i} ∂ωi​∂zi​​因为 ω i \omega_i ωi​ 是矩阵 W i W_i Wi​ 的一个分量且 z i W i ⋅ a i − 1 z_i W_i \cdot a_{i-1} zi​Wi​⋅ai−1​ 3因此我们可以从最后一层的导数开始一步步回到第一层重新计算所有的导数 批量训练 现在让我们想象一下我们有一个大型数据集。例如1,000,000 个元素。对于这样的数据集上述算法的每次迭代都会花费非常长的时间因为每次迭代都需要计算神经网络的输出值以及所有数据元素的损失 L L L 此外还可能出现第二个问题大型数据集可能不适合放入 GPU 内存。那么我们基本上就无法在算法中迈出一步。 解决方案是这样的让我们在每个步骤中针对部分数据集元素计算损失 L L L 和偏导数的值而不是一次性针对所有数据集元素计算损失 L L L 和偏导数的值。例如对于 100 个元素。那么算法将如下所示 神经网络的梯度优化算法如下所示 用随机值初始化所有网络权重 W i W_i Wi​和 b i b_i bi​。我们选择梯度下降步长 α \alpha α 的值直到满足停止标准为止执行以下操作 我们将数据分成批每批有 k k k个元素。对于每个 batch 我们执行以下操作 我们根据当前第 j j j 个批次的元素用参数 W i W_i Wi​ 和 b i b_i bi​ 的当前值计算 L j L^j Lj 的值我们计算偏导数 ∂ L j ∂ W i \frac{\partial L^j}{\partial W_i} ∂Wi​∂Lj​、 ∂ L j ∂ b i \frac{\partial L^j}{\partial b_i} ∂bi​∂Lj​的值更新网络参数值 W i W i − α ∂ L j ∂ W i , b i b i − α ∂ L j ∂ b i W_i W_i - \alpha \frac{\partial L^j}{\partial W_i}, \ \ b_i b_i - \alpha \frac{\partial L^j}{\partial b_i} Wi​Wi​−α∂Wi​∂Lj​,  bi​bi​−α∂bi​∂Lj​ 该算法称为小批量梯度下降或随机梯度下降SGD。 这种算法的每次迭代都比通常的梯度下降的每次迭代快得多在梯度下降中我们每次都会计算数据集所有元素的 L L L 值。但随机梯度下降所需的总迭代次数较高。 为了理解其含义让我们考虑批量大小等于一的极端情况。也就是说在梯度下降的每次迭代中我们仅根据数据集的一个元素来计算表达式 L L L 的值和偏导数。这意味着在算法的每一步我们都会改变网络权重以便网络开始针对当前元素 y i y_i yi​ 产生最佳答案。但是这种权重变化的方向并不一定与导致数据集所有元素的网络性能提高的方向完全一致。 事实证明每一步的随机梯度下降都会使参数值朝着略微偏离理想的方向移动。 具体如下 这里 D i D_i Di​是第 i i i个batch上的损失值最小的网络参数值向量。平均而言 D i D_i Di​比 C i C_i Ci​更接近 B B B。因此小批量的梯度下降所需的迭代次数将比批量大小为 1 时更少。 事实证明我们需要在算法一次迭代的执行速度和所需的迭代次数之间进行权衡。实际上批量大小通常被认为是 GPU 允许的最大值。 网络输入的规范化 对于神经网络在将输入数据输入网络之前对其进行规范化是很有用的。规范化是将所有输入特征的分布带到同一尺度的过程。 例如假设我们有一项任务是根据客户信息确定信用评分。让信息包括客户的年龄。此特征的值变化为[18, 80]即在相当大的范围内它的绝对值可能相当大。这使得梯度下降算法的效率降低需要更多的迭代来训练网络还会导致网络中梯度爆炸等其他问题。您可以通过“附加”部分中的链接了解为什么会发生这种情况。 最常见的规范化方法是标准化。这减少到了平均值 0 和方差 1。 假设我们有一个特征 F F F以及它在数据集中的值 { x i f } \{x_i^f\} {xif​}。那么每个元素的属性值变化如下 x i f − μ f σ f \frac{x_i^f-\mu_f}{\sigma_f} σf​xif​−μf​​ 其中 μ f \mu_f μf​是数据集中特征 F F F的平均值 σ f \sigma_f σf​是数据集中特征 F F F的标准差。经过这样的标准化之后数据集的特征的平均值将为0标准差将为1。 特征的规范化可以说明如下。假设数据集中有两个特征。我们将数据集的元素可视化为平面上的点。 这里的蓝点表示标准化之前的数据集元素红点表示标准化之后的数据集元素。 BatchNorm 现在我们来讨论网络的一个新的层——批量标准化。 这一层有助于使网络训练更稳定、更快。此外具有批量规范层的神经网络通常比没有批量规范的相同网络更好地学习任务。 让我们看一下具有多层的神经网络。请注意该神经网络的 2-3 层可以被视为一个单独的、较小的神经网络。该神经网络的输入数据是网络第一层的输出。 我们已经知道为了更好地训练神经网络输入数据需要规范化。事实证明规范化每个中间层的输出也有助于更好的网络训练。 BatchNorm 是执行此标准化的层。 但是还有第二个原因来规范中间层的输出。这是神经网络内部协变量转移的影响。 BatchNorm 最初是为了消除这种影响而设计的。 什么是内部协变量转移让我们看一下具有几层的神经网络。在训练过程中各层一起学习。并且网络在训练时每一层都必须适应前一层产生的值。但是在网络训练的时候网络每一层输出的数值的分布是会发生变化的。并且算法每次迭代时每个隐藏层都必须适应前一层输出的新分布。正因为如此网络学习得比较慢。同时在每次训练迭代中权重可能会发生相当大的变化这可能会引发其他问题例如梯度爆炸。 规范化神经网络层的输出将有助于解决这个问题。 那么我们如何实现层输出的规范化呢最简单的想法是在将每一层的输出进一步输入到网络之前对其进行严格的规范化就像我们规范化输入数据一样。假设也将所有层输出的平均值降低为 0方差降低为 1。 但是为什么不给神经网络更多的自由并让它自己决定如何最好地规范化每一层的输出呢 这就是 BatchNorm 背后的想法。 BatchNorm 是一个可训练层它使用可训练参数对网络输出进行规范化。 BatchNorm层应用在网络层之后其工作原理如下 我们按批次计算网络层输出的平均值 μ B \mu_B μB​和标准差 σ B \sigma_B σB​。也就是说我们有层 { x i } i 1 b \{x_i\}_{i1}^b {xi​}i1b​ 的 b b b 个输出其中 b b b 是批量大小。然后 μ B ∑ i 1 b x i b \mu_B \frac{\sum_{i1}^b x_i}{b} μB​b∑i1b​xi​​ σ B 2 ∑ i 1 b ( x i − μ B ) 2 b \sigma^2_B \frac{\sum_{i1}^b (x_i - \mu_B)^2}{b} σB2​b∑i1b​(xi​−μB​)2​ 规范化层输出 x i ^ x i − μ B σ B \widehat{x_i} \frac{x_i - \mu_B}{\sigma_B} xi​ ​σB​xi​−μB​​ 计算更新后的层输出为 y i γ x i ^ β y_i \gamma\widehat{x_i} \beta yi​γxi​ ​β 其中 γ \gamma γ和 β \beta β是训练参数。 所以这个想法是这样的我们对每个神经元的输出进行标准化使得其输出的平均值是 0方差是 1。然后我们将每个神经元的输出乘以可训练值 γ \gamma γ 并添加可训练值 β \beta β。也就是说我们改变神经元输出的平均值及其方差。但同时我们使得该层的所有神经元的平均输出值和方差相同。 每层的可学习平均值和方差使得神经网络能够为特定任务选择最方便的层值标准化。 在实践中BatchNorm 几乎用于所有神经网络尤其是深度神经网络。当我们讨论流行的网络架构时我们会再次看到这一点。 验证样本 为了在训练过程中跟踪网络的当前质量训练样本通常分为两部分训练和验证。训练部分用于训练网络验证部分用于在每 n 次训练迭代之后例如每个 epoch 之后检查网络的质量。 测试样品不能作为验证样品。因此测试样本存在过度拟合的风险。 验证样本的主要功能 在训练过程中监控模型的质量。这对于跟踪训练模型时可能出现的问题非常重要过度拟合、梯度爆炸或衰减、模型参数的不良分布或“滚动”到简单的答案。根据验证样本的结果通常会从训练期间保存的集合中选择最终模型。需要注意的是在大型神经网络的情况下使用验证样本时不能排除可能的随机性因素即使是训练不佳的模型有时也能在验证样本上显示出良好的结果。这类似于多重假设检验的效果需要进行校正如果我们测试同一模型的许多不同版本即使是随机的在某个时候我们也会找到一个在验证集上提供高质量的版本。这种影响可以被视为验证样本的一种过度训练。因此验证样本和测试样本必须彼此不同。 一些超参数的选择。对于训练许多模型来说以最佳方式选择超参数非常重要。但这无法在训练样本上完成因为无法排除模型的过度拟合即所选的超参数与优化参数的组合本身是好的而不是针对特定的训练样本。在测试样本上执行此操作也是不可能的因为我们可以对其进行重新训练并且它不再是测试样本。为了这些目的有必要使用验证样本。 实践 在本部分中我们将使用 PyTorch 上的全连接神经网络解决将图像分类为 10 个类的问题。 import numpy as np from tqdm.notebook import tqdm import matplotlib.pyplot as plt %matplotlib inline# PyTorch 库模块 import torch from torchvision import datasets, transforms加载数据集 MNIST数据集是标准数据集之一位于PyTorch框架的数据集模块中。下载并加载到内存中非常简单 train_data datasets.MNIST(root./mnist_data, trainTrue, downloadTrue, transformtransforms.ToTensor()) test_data datasets.MNIST(root./mnist_data, trainFalse, downloadTrue, transformtransforms.ToTensor())这里 root — 下载数据集的文件夹路径train — 如果为 True则下载样本的训练部分如果为 False — 则下载测试部分download — 如果数据集尚未在磁盘上则为 True。如果已经下载可以设置downloadFalsetransform — 加载时对数据集元素应用哪些转换transforms.ToTensor() 将所有图像转换为“张量”类型。 train_data接下来您需要向数据集的两个部分添加数据加载器。数据加载器是一种协调将数据集分成批次的结构。我们将在网络训练代码中使用它。 train_loader torch.utils.data.DataLoader(train_data, batch_size64, shuffleTrue) test_loader torch.utils.data.DataLoader(test_data, batch_size64, shuffleFalse)这里 batch_size — 批次大小shuffle — 如果您需要在每个时期之前将数据集分成批次之前进行打乱则为 True否则为 False。对于训练集shuffleTrue 应该始终为真 网络构建 我们将建立一个完全连接的神经网络来解决将图像分为 10 类的问题。要做到这一点您需要了解如何将图像输入到神经网络的输入。 事实上这很容易做到。每张黑白图片都是一个二维数字矩阵。在我们的数据集中图像的分辨率为 28x28因此 MNIST 的每个图像都表示为 28x28 的数字矩阵。 为了将图像输入神经网络我们将二维矩阵拉伸为一维向量。我们将矩阵的所有行连接成一个大小为 28*28 784 的长向量。结果是每张图片将由一个大小为 784 的向量表示。该向量可以被视为图片特征的向量。 那么在解决 MNIST 图像分类问题的神经网络中输入层应该正好有 784 个神经元。输出为 - 10因为我们的问题中有 10 个类。中间层的数量以及每个中间层的神经元的数量可以是任意的。 让我们建立一个神经网络 # 定义神经网络层的模块 import torch.nn as nn # 定义神经网络层激活的模块 import torch.nn.functional as Fclass SimpleNet(nn.Module):def __init__(self):super().__init__()self.flatten torch.nn.Flatten()self.fc_in nn.Linear(28*28, 256)self.fc_out nn.Linear(256, 10)def forward(self, x):# 前向传递网络# 将输入对象从图像转换为矢量x self.flatten(x)# 乘以第 1 层的权重矩阵并应用激活函数x F.relu(self.fc_in(x))# 乘以第 2 层权重矩阵并应用激活函数x self.fc_out(x)return xdevice torch.device(cuda if torch.cuda.is_available() else cpu) device输出device(type‘cuda’) model SimpleNet().to(device)训练神经网络 让我们声明损失函数和优化器 # 损失函数 loss_fn torch.nn.CrossEntropyLoss()# 优化器 learning_rate 1e-3 optimizer torch.optim.Adam(model.parameters(), lrlearning_rate)最后我们来编写模型训练函数 def train(model, loss_fn, optimizer, n_epoch6):model.train(True)# 网络训练周期for epoch in tqdm(range(n_epoch)):for i, batch in enumerate(tqdm(train_loader)):# 这就是我们获得当前一批图片和对它们的回应的方式X_batch, y_batch batch# 前向传递接收一批图像的网络响应logits model(X_batch.to(device))# 根据网络给出的答案和批次的正确答案计算损失loss loss_fn(logits, y_batch.to(device))# 每 50 次迭代我们将显示当前批次的损失if i % 50 0:print(loss.item())optimizer.zero_grad() # 我们重置优化器梯度的值loss.backward() # 反向传播梯度计算optimizer.step() # 更新网络权重return model我们训练模型 model train(model, loss_fn, optimizer, n_epoch2)太好了模型已经训练好了。让我们在测试样本上测试一下它的质量。为此我们编写了评估函数 from sklearn.metrics import accuracy_scoredef evaluate(model, dataloader, loss_fn):model.eval()y_pred_list []y_true_list []losses []# 让我们看一下数据加载器批次for i, batch in enumerate(tqdm(dataloader)):# 这就是我们得到当前批次的方法X_batch, y_batch batch# 关闭任何梯度的计算with torch.no_grad():# 我们收到该批次的网络响应logits model(X_batch.to(device))# 我们计算批次上的损失函数值loss loss_fn(logits, y_batch.to(device))loss loss.item()# 将当前批次的损失保存到数组中losses.append(loss)# 对于我们理解的批次中的每个元素# 网络将它分配到 0 到 9 中的哪个类别y_pred torch.argmax(logits, dim1)# 我们将当前批次的正确答案保存到数组中# 以及对当前批次的网络响应y_pred_list.extend(y_pred.cpu().numpy())y_true_list.extend(y_batch.numpy())# 我们计算网络响应和正确答案之间的准确率accuracy accuracy_score(y_pred_list, y_true_list)return accuracy, np.mean(losses)让我们检查一下模型对训练和测试样本的预测质量 evaluate(model, train_loader, loss_fn) evaluate(model, test_loader, loss_fn)我们将训练数据分为 train 和 val # 我们将把 80% 的图片纳入训练样本 train_size int(len(train_data) * 0.8) # 验证 - 剩余 20% val_size len(train_data) - train_sizetrain_data, val_data torch.utils.data.random_split(train_data, [train_size, val_size])train_data, val_data, test_data让我们为更新的数据集声明数据加载器 train_loader torch.utils.data.DataLoader(train_data, batch_size64, shuffleTrue) val_loader torch.utils.data.DataLoader(train_data, batch_size64, shuffleFalse) test_loader torch.utils.data.DataLoader(test_data, batch_size64, shuffleFalse)让我们添加一些网络训练代码在每个时期之后插入对训练和验证样本的损失和准确性的检查 def train(model, loss_fn, optimizer, n_epoch6):model.train(True)data {acc_train: [],loss_train: [],acc_val: [],loss_val: []}# 网络训练周期for epoch in tqdm(range(n_epoch)):for i, batch in enumerate(tqdm(train_loader)):# 这就是我们获得当前一批图片和对它们的回应的方式X_batch, y_batch batch# 前向传递接收一批图像的网络响应logits model(X_batch.to(device))# 根据网络给出的答案和批次的正确答案计算损失loss loss_fn(logits, y_batch.to(device))optimizer.zero_grad() # 我们重置优化器梯度的值loss.backward() # 反向传播梯度计算optimizer.step() # 更新网络权重# 时代终结模型验证print(On epoch end, epoch)acc_train_epoch, loss_train_epoch evaluate(model, train_loader, loss_fn)print(Train acc:, acc_train_epoch, Train loss:, loss_train_epoch)acc_val_epoch, loss_val_epoch evaluate(model, val_loader, loss_fn)print(Val acc:, acc_val_epoch, Val loss:, loss_val_epoch)data[acc_train].append(acc_train_epoch)data[loss_train].append(loss_train_epoch)data[acc_val].append(acc_val_epoch)data[loss_val].append(loss_val_epoch)return model, data让我们再次创建一个具有随机权重的模型为其声明一个损失函数和一个优化器 model SimpleNet().to(device)# 损失函数 loss_fn torch.nn.CrossEntropyLoss()# 优化器 learning_rate 1e-3 optimizer torch.optim.Adam(model.parameters(), lrlearning_rate)我们训练模型 model, data train(model, loss_fn, optimizer, n_epoch3)让我们直观地看一下各个时期损失和准确度的变化图 _, axes plt.subplots(nrows2, ncols2, figsize(10, 10))ox list(range(3))axes[0][0].plot(ox, data[acc_train]) axes[0][0].title.set_text(acc_train)axes[0][1].plot(ox, data[acc_val]) axes[0][1].title.set_text(acc_val)axes[1][0].plot(ox, data[loss_train]) axes[1][0].title.set_text(loss_train)axes[1][1].plot(ox, data[loss_val]) axes[1][1].title.set_text(loss_val)plt.show()
http://www.w-s-a.com/news/83593/

相关文章:

  • 分类网站一天做几条合适南安网络推广
  • 案例学 网页设计与网站建设百度竞价关键词出价技巧
  • 做公司网站要那些资料南雄网站建设
  • 自己做的网站发布到网上视频播放不了网页游戏奥奇传说
  • 网站效果用什么软件做品牌网站建设等高端服务
  • 四川省成华区建设局网站网站专业制作
  • 网站建设如何开票网站后台怎么做超链接
  • 教育网站设计方案建设网站技术公司电话号码
  • 建网站要定制还是第三方系统传奇网站模板psd
  • 免费搭建企业网站什么叫网站定位
  • 网站建设cms程序员培训班
  • 网站seo技术wordpress editor ios
  • 红酒网站设计成立公司需要哪些手续
  • 广州做网站哪个好网站建网站建设网站站网站
  • 如何快速提升网站pr短剧个人主页简介模板
  • 上海网站建设 永灿百度权重3的网站值多少
  • 公司展示网站模板模板工
  • 网站建设收费详情舟山公司做网站
  • 深圳宝安区住房和建设局网站html模板大全
  • 和田哪里有做网站的地方wordpress地址更改
  • 恒通建设集团有限公司网站企业网站百度指数多少算竞争大
  • 雅虎网站收录提交入口如何使用wordpress搭建网站
  • 微商城网站建设怎么样发稿是什么意思
  • dz建站与wordpress群晖做网站服务器速度快吗
  • 做手机网站的公司网站建设 app开发 图片
  • 网站开发技术背景介绍wordpress数据库重置密码
  • 开发建设网站的实施过程是一个logo设计品牌
  • 做360pc网站排名首页工程造价信息网官网首页
  • 产品销售网站模块如何设计大数据和网站开发
  • 现在帮别人做网站赚钱不济南做网站建设公司