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

网站建设seo视频微信推广软件哪个好

网站建设seo视频,微信推广软件哪个好,网站做优化必须要ftp吗,淮安做网站seo文章目录1 、使用内置的训练和评估循环API概述:第一个端到端示例loss、metrics和optimizerKeras API 中内置的optimizers、losses和metrics:自定义 losses自定义metricsfit()方法中的参数使用tf.data Datasets训练和评估fit() 使用样本权重和类权重将数据…

文章目录

  • 1 、使用内置的训练和评估循环
    • API概述:第一个端到端示例
    • loss、metrics和optimizer
      • Keras API 中内置的optimizers、losses和metrics:
      • 自定义 losses
      • 自定义metrics
    • fit()方法中的参数
    • 使用tf.data Datasets训练和评估
    • fit() 使用样本权重和类权重
    • 将数据传递到多输入、多输出模型
    • 使用callbacks
    • Checkpointing 模型
    • 使用学习率表
    • 训练期间loss和metrics的可视化
  • 2:从头开始编写自己的训练和评估循环
    • 使用GradientTape:端到端的示例
  • 参考资料

 
TensorFlow 2.0中一般有两种情况下的训练、评估和预测(推断)模型:

  1. 使用内置APIs进行训练和验证(例如model.fit(), model.evaluate(), model.predict())。
  2. 使用紧急执行和GradientTape对象从头开始编写自定义循环。

一般来说,无论是使用内置循环还是编写自己的循环,模型训练和评估在各种Keras模型中的工作方式都是相同的——Sequential模型、使用函数API构建的模型以及通过模型子类化从头开始编写的模型。

 

1 、使用内置的训练和评估循环

将数据传递到模型的内置训练循环时,应该使用Numpy数组(如果数据很小并且适合内存),或者使用 tf.data Dataset 对象。

接下来,将使用MNIST数据集作为Numpy数组,以演示如何使用optimizers, losses, 和metrics。
 

API概述:第一个端到端示例

这里,使用函数API构建模型:

import tensorflow as tf
import numpy as np
from tensorflow import keras
from tensorflow.keras import layersinputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, name='predictions')(x)model = keras.Model(inputs=inputs, outputs=outputs)

典型的端到端工作流是这样的,包括训练、对原始训练数据生成的数据集的验证,以及对测试数据的最终评估:

1)加载数据集:

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()# Preprocess the data (these are Numpy arrays)
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255y_train = y_train.astype('float32')
y_test = y_test.astype('float32')# Reserve 10,000 samples for validation
x_val = x_train[-10000:]
y_val = y_train[-10000:]
x_train = x_train[:-10000]
y_train = y_train[:-10000]

2)指定训练配置(optimizer, loss, metrics)

model.compile(optimizer=keras.optimizers.RMSprop(),  # Optimizer# Loss function to minimizeloss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),# List of metrics to monitormetrics=['sparse_categorical_accuracy'])

3)通过将数据分为大小为“batch_size”的“batches”来训练模型,并在给定数量的“epochs”中重复遍历整个数据集

print('# Fit model on training data')
history = model.fit(x_train, y_train,batch_size=64,epochs=3,# We pass some validation for# monitoring validation loss and metrics# at the end of each epochvalidation_data=(x_val, y_val))print('\nhistory dict:', history.history)

返回的“history”对象保存训练期间loss值和metric值。

4)最后,使用测试集数据进行评估和预测:

# Evaluate the model on the test data using `evaluate`
print('\n# Evaluate on test data')
results = model.evaluate(x_test, y_test, batch_size=128)
print('test loss, test acc:', results)# Generate predictions (probabilities -- the output of the last layer)
# on new data using `predict`
print('\n# Generate predictions for 3 samples')
predictions = model.predict(x_test[:3])
print('predictions shape:', predictions.shape)

 

loss、metrics和optimizer

要使用fit训练模型,需要指定loss函数、optimizer,还可以选择指定一些要监视的metrics。

将这些作为参数传递给模型的compile()方法:

model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=[keras.metrics.sparse_categorical_accuracy])

也可以通过字符串标识符的方式:

model.compile(optimizer='rmsprop',loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['sparse_categorical_accuracy'])

其中,metrics参数是一个列表——模型可以有任意数量的metrics。
 

Keras API 中内置的optimizers、losses和metrics:

Optimizers:

SGD() (with or without momentum)
RMSprop()
Adam()
etc.

Losses:

MeanSquaredError()
KLDivergence()
CosineSimilarity()
etc.

Metrics:

AUC()
Precision()
Recall()
etc.

 

自定义 losses

有两种方法可以自定义losses。

方法一:创建一个函数,该函数的输入为 y_true 和 y_pred 。该函数计算实际数据和预测之间的平均绝对误差:

def basic_loss_function(y_true, y_pred):return tf.math.reduce_mean(tf.abs(y_true - y_pred))model.compile(optimizer=keras.optimizers.Adam(),loss=basic_loss_function)model.fit(x_train, y_train, batch_size=64, epochs=3)

如果需要一个loss函数,它需要除 y_true 和 y_pred 之外的参数,您可以子类化 tf.keras.losses.Loss类并实现以下两种方法:

	__init__(self):接受在调用loss函数期间要传递的参数call(self, y_true, y_pred):使用目标(y_true)和模型预测(y_pred)计算模型的损失

在计算损失时,可以在call()期间使用传递到__init__()的参数。

方法二:实现计算BinaryCrossEntropy损失的WeightedCrossEntropy损失函数,其中某个类或整个函数的损失可以由标量修改。

class WeightedBinaryCrossEntropy(keras.losses.Loss):"""Args:pos_weight: Scalar to affect the positive labels of the loss function.weight: Scalar to affect the entirety of the loss function.from_logits: Whether to compute loss from logits or the probability.reduction: Type of tf.keras.losses.Reduction to apply to loss.name: Name of the loss function."""def __init__(self, pos_weight, weight, from_logits=False,reduction=keras.losses.Reduction.AUTO,name='weighted_binary_crossentropy'):super().__init__(reduction=reduction, name=name)self.pos_weight = pos_weightself.weight = weightself.from_logits = from_logitsdef call(self, y_true, y_pred):ce = tf.losses.binary_crossentropy(y_true, y_pred, from_logits=self.from_logits)[:,None]ce = self.weight * (ce*(1-y_true) + self.pos_weight*ce*(y_true))return ceone_hot_y_train = tf.one_hot(y_train.astype(np.int32), depth=10)model.compile(optimizer=keras.optimizers.Adam(),loss=WeightedBinaryCrossEntropy(pos_weight=0.5, weight = 2, from_logits=True)
)
model.fit(x_train, one_hot_y_train, batch_size=64, epochs=5)

 

自定义metrics

可以通过子类化Metric类来轻松创建自定义metrics,并且需要实现4个方法:

	__init__(self):创建状态变量。update_state(self, y_true, y_pred, sample_weight=None):使用目标y_true和模型预测y_pred更新状态变量。result(self):使用状态变量来计算最终结果。reset_states(self):重新初始化度量的状态。

状态更新和结果计算是分开的,因为在某些情况下,结果计算大,并且只能定期进行。

下面是一个简单的示例,演示如何实现CategoricalTruePositives metric,计算正确分类为属于给定类的样本数:

class CategoricalTruePositives(keras.metrics.Metric):def __init__(self, name='categorical_true_positives', **kwargs):super(CategoricalTruePositives, self).__init__(name=name, **kwargs)self.true_positives = self.add_weight(name='tp', initializer='zeros')def update_state(self, y_true, y_pred, sample_weight=None):y_pred = tf.reshape(tf.argmax(y_pred, axis=1), shape=(-1, 1))values = tf.cast(y_true, 'int32') == tf.cast(y_pred, 'int32')values = tf.cast(values, 'float32')if sample_weight is not None:sample_weight = tf.cast(sample_weight, 'float32')values = tf.multiply(values, sample_weight)self.true_positives.assign_add(tf.reduce_sum(values))def result(self):return self.true_positivesdef reset_states(self):# The state of the metric will be reset at the start of each epoch.self.true_positives.assign(0.)model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=1e-3),loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=[CategoricalTruePositives()])
model.fit(x_train, y_train,batch_size=64,epochs=3)

 

fit()方法中的参数

第一个端到段示例,使用validation_data参数将Numpy数组的元组(x_val,y_val)传递给模型,以在每个epoch结束时评估验证损失和验证度量。

还有另一个选项:参数validation_split允许自动保留部分训练数据进行验证。参数值表示要保留用于验证的数据部分,因此应将其设置为大于0且小于1的数字。例如,validation_split=0.2表示“使用20%的数据进行验证”,validation_split=0.6表示“使用60%的数据进行验证”。

model.fit(x_train, y_train, batch_size=64, validation_split=0.2, epochs=1, steps_per_epoch=1)

 

使用tf.data Datasets训练和评估

tf.data API是TensorFlow 2.0中的一组实用程序,用于以快速和可扩展的方式加载和预处理数据。

可以将数据集实例直接传递给fit()、evaluate()和predict()方法:

# First, let's create a training Dataset instance.
# For the sake of our example, we'll use the same MNIST data as before.
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)# Now we get a test dataset.
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_dataset = test_dataset.batch(64)# Since the dataset already takes care of batching,
# we don't pass a `batch_size` argument.
model.fit(train_dataset, epochs=3)# You can also evaluate or predict on a dataset.
print('\n# Evaluate')
result = model.evaluate(test_dataset)
dict(zip(model.metrics_names, result))

如果只想对数据集中特定数量的批运行训练,可以传递steps_per_epoch参数,该参数指定模型在转到下一个epoch之前应使用此数据集运行多少训练步。这样,数据集不会在每个epoch结束时重置,而是继续使用下一批。数据集最终将用完数据(除非它是无限循环的数据集)。

# Only use the 100 batches per epoch (that's 64 * 100 samples)
model.fit(train_dataset, steps_per_epoch=100, epochs=3)

使用验证数据集
可以在fit中将数据集实例作为validation_data参数传递:

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)model.fit(train_dataset, epochs=3, validation_data=val_dataset)

如果只想对此数据集的特定批处理运行验证,可以传递validation_steps参数,该参数指定在中断验证并转到下一个epoch之前,模型应使用验证数据集运行多少个验证步骤:

# Prepare the training dataset
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)# Prepare the validation dataset
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))
val_dataset = val_dataset.batch(64)model.fit(train_dataset, epochs=3,# Only run validation using the first 10 batches of the dataset# using the `validation_steps` argumentvalidation_data=val_dataset, validation_steps=10)

 

fit() 使用样本权重和类权重

除了输入数据和目标数据外,在使用 fit 时,还可以将样本权重或类权重传递给模型:

从Numpy数据训练时:使用 sample_weight 和 class_weight 参数
从Datasets训练时:Datasets返回一个元组(input_batch、target_batch、sample_weight_batch)

“样本权重”数组是一个数字数组,指定在计算总损失时,批中每个样本应具有的权重。它通常用于不平衡分类问题(其思想是给很少出现的类赋予更多的权重)。当使用的权重为1和0时,数组可以用作损失函数的掩码(完全放弃某些样本对总损失的贡献)。

“类权重”字典是同一概念的一个更具体的实例:它将类索引映射到应用于属于该类的样本的样本权重。

下面是一个Numpy示例,使用类权重或样本权重来重视 class #5(MNIST数据集中的数字“5”)的正确分类。

class_weight = {0: 1., 1: 1., 2: 1., 3: 1., 4: 1.,# Set weight "2" for class "5",# making this class 2x more important5: 2.,6: 1., 7: 1., 8: 1., 9: 1.}
print('Fit with class weight')
model.fit(x_train, y_train,class_weight=class_weight,batch_size=64,epochs=4)
# Here's the same example using `sample_weight` instead:
sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.
print('\nFit with sample weight')model = get_compiled_model()
model.fit(x_train, y_train,sample_weight=sample_weight,batch_size=64,epochs=4)

下面是Dataset示例:

sample_weight = np.ones(shape=(len(y_train),))
sample_weight[y_train == 5] = 2.# Create a Dataset that includes sample weights
# (3rd element in the return tuple).
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train, sample_weight))# Shuffle and slice the dataset.
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)model = get_compiled_model()
model.fit(train_dataset, epochs=3)

 

将数据传递到多输入、多输出模型

多输入、多输出模型示例:图像输入的shape(32,32,3)(即(height,width,channels))和时间序列输入的shape(None,10)(即(timesteps,features))。模型将从这两个输入组合计算出2个输出:“分数”(shape(1,))和五个类别(shape(5,))的概率分布。

from tensorflow import keras
from tensorflow.keras import layersimage_input = keras.Input(shape=(32, 32, 3), name='img_input')
timeseries_input = keras.Input(shape=(None, 10), name='ts_input')x1 = layers.Conv2D(3, 3)(image_input)
x1 = layers.GlobalMaxPooling2D()(x1)x2 = layers.Conv1D(3, 3)(timeseries_input)
x2 = layers.GlobalMaxPooling1D()(x2)x = layers.concatenate([x1, x2])score_output = layers.Dense(1, name='score_output')(x)
class_output = layers.Dense(5, name='class_output')(x)model = keras.Model(inputs=[image_input, timeseries_input],outputs=[score_output, class_output])keras.utils.plot_model(model, 'multi_input_and_output_model.png', show_shapes=True)model.compile(optimizer=keras.optimizers.RMSprop(1e-3),loss=[keras.losses.MeanSquaredError(),keras.losses.CategoricalCrossentropy(from_logits=True)],metrics=[[keras.metrics.MeanAbsolutePercentageError(),keras.metrics.MeanAbsoluteError()],[keras.metrics.CategoricalAccuracy()]])

在这里插入图片描述由于已经给输出层命名,可以通过dict指定每个输出损失和度量:

model.compile(optimizer=keras.optimizers.RMSprop(1e-3),loss={'score_output': keras.losses.MeanSquaredError(),'class_output': keras.losses.CategoricalCrossentropy(from_logits=True)},metrics={'score_output': [keras.metrics.MeanAbsolutePercentageError(),keras.metrics.MeanAbsoluteError()],'class_output': [keras.metrics.CategoricalAccuracy()]})

使用loss-weights参数,可以为不同的output-specific losses赋予不同的权重,如下所示:

model.compile(optimizer=keras.optimizers.RMSprop(1e-3),loss={'score_output': keras.losses.MeanSquaredError(),'class_output': keras.losses.CategoricalCrossentropy(from_logits=True)},metrics={'score_output': [keras.metrics.MeanAbsolutePercentageError(),keras.metrics.MeanAbsoluteError()],'class_output': [keras.metrics.CategoricalAccuracy()]},loss_weights={'score_output': 2., 'class_output': 1.})

如果这些输出用于预测,不用于训练,也可以选择不计算某些输出的损失:

# List loss version
model.compile(optimizer=keras.optimizers.RMSprop(1e-3),loss=[None, keras.losses.CategoricalCrossentropy(from_logits=True)])# Or dict loss version
model.compile(optimizer=keras.optimizers.RMSprop(1e-3),loss={'class_output':keras.losses.CategoricalCrossentropy(from_logits=True)})

在fit中将数据传递给多输入多输出模型的方式与在compile中指定loss函数的方式类似:可以传递Numpy数组的列表(1:1映射到接收loss函数的输出)或dict将输出名称映射到Numpy训练数据数组。

model.compile(optimizer=keras.optimizers.RMSprop(1e-3),loss=[keras.losses.MeanSquaredError(),keras.losses.CategoricalCrossentropy(from_logits=True)])# Generate dummy Numpy data
img_data = np.random.random_sample(size=(100, 32, 32, 3))
ts_data = np.random.random_sample(size=(100, 20, 10))
score_targets = np.random.random_sample(size=(100, 1))
class_targets = np.random.random_sample(size=(100, 5))# Fit on lists
model.fit([img_data, ts_data], [score_targets, class_targets],batch_size=32,epochs=3)# Alternatively, fit on dicts
model.fit({'img_input': img_data, 'ts_input': ts_data},{'score_output': score_targets, 'class_output': class_targets},batch_size=32,epochs=3)

Dataset的情况:

train_dataset = tf.data.Dataset.from_tensor_slices(({'img_input': img_data, 'ts_input': ts_data},{'score_output': score_targets, 'class_output': class_targets}))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)model.fit(train_dataset, epochs=3)

 

使用callbacks

Keras 中的 Callbacks 是在训练过程中的不同点调用的对象(在epoch开始时、批处理结束时、epoch结束时等),可用于实现以下行为:

	在训练期间的不同点进行验证定期检查模型或当模型超过某个精度阈值时训练趋于平稳时改变模型的学习率当训练似乎趋于平稳时,对顶层进行微调在训练结束或超过某个性能阈值时发送电子邮件或即时消息通知

回调可以作为列表在fit中调用:

callbacks = [keras.callbacks.EarlyStopping(# Stop training when `val_loss` is no longer improvingmonitor='val_loss',# "no longer improving" being defined as "no better than 1e-2 less"min_delta=1e-2,# "no longer improving" being further defined as "for at least 2 epochs"patience=2,verbose=1)
]
model.fit(x_train, y_train,epochs=20,batch_size=64,callbacks=callbacks,validation_split=0.2)

一些内置的callbacks:

  1. ModelCheckpoint:定期保存模型。
  2. EarlyStopping:当训练不再改进验证指标时,停止训练。
  3. TensorBoard:定期编写可以在TensorBoard中可视化的模型日志。
  4. CSVLogger:将损失和度量数据流到CSV文件。

自定义callback:

可以通过扩展基类keras.callbacks.Callback创建自定义callback。callback可以通过类属性self.model访问其关联的模型。

下面是一个简单的示例,保存了训练期间每批损失值的列表:

class LossHistory(keras.callbacks.Callback):def on_train_begin(self, logs):self.losses = []def on_batch_end(self, batch, logs):self.losses.append(logs.get('loss'))

 

Checkpointing 模型

在相对较大的数据集上训练模型时,必须经常保存模型的检查点。

实现这一点的最简单方法是使用ModelCheckpoint callback:

callbacks = [keras.callbacks.ModelCheckpoint(filepath='mymodel_{epoch}',# Path where to save the model# The two parameters below mean that we will overwrite# the current checkpoint if and only if# the `val_loss` score has improved.save_best_only=True,monitor='val_loss',verbose=1)
]
model.fit(x_train, y_train,epochs=3,batch_size=64,callbacks=callbacks,validation_split=0.2)

 

使用学习率表

在训练深度学习模型时,一个常见的模式是随着训练的进行逐渐减少学习。这通常被称为“学习率衰减”。

学习衰退时间表可以是静态的(预先固定的,作为当前epoch或当前批处理索引的函数),也可以是动态的(响应模型的当前行为,特别是验证损失)。

方法一:通过在优化器中将schedule对象作为learning_rate参数传递,可以轻松使用静态学习速率衰减表:

initial_learning_rate = 0.1
lr_schedule = keras.optimizers.schedules.ExponentialDecay(initial_learning_rate,decay_steps=100000,decay_rate=0.96,staircase=True)optimizer = keras.optimizers.RMSprop(learning_rate=lr_schedule)

有几种内置的表可用:ExponentialDecay, PiecewiseConstantDecay, PolynomialDecay, 和InverseTimeDecay。

方法二:利用callbacks实现动态学习率表

 

训练期间loss和metrics的可视化

在训练期间,监视模型的最佳方法是使用TensorBoard,这是一个基于浏览器的应用程序,可以在本地运行:

  1. 训练和评估时实时绘制loss和metrics
  2. (可选)层激活直方图的可视化
  3. (可选)Embedding层学习的嵌入空间的三维可视化

如果使用pip安装了TensorFlow,则应该能够从命令行启动TensorBoard:

tensorboard --logdir=/full_path_to_your_logs

使用TensorBoard callback:
在Keras模型和fit方法中使用TensorBoard的最简单方法是TensorBoard callback。

在最简单的情况下,只要指定callback要写入日志的位置,就可以:

tensorboard_cbk = keras.callbacks.TensorBoard(log_dir='/full_path_to_your_logs')
model.fit(dataset, epochs=10, callbacks=[tensorboard_cbk])

TensorBoard callback有许多有用的选项:

keras.callbacks.TensorBoard(log_dir='/full_path_to_your_logs',histogram_freq=0,  # How often to log histogram visualizationsembeddings_freq=0,  # How often to log embedding visualizationsupdate_freq='epoch')  # How often to write logs (default: once per epoch)

 

2:从头开始编写自己的训练和评估循环

使用GradientTape:端到端的示例

在GradientTape作用域内调用模型可以检索层的可训练权重相对于损失值的梯度。使用优化器实例,可以使用这些渐变来更新这些变量(可以使用model.trainable_weights检索).

# Get the model.
inputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, name='predictions')(x)
model = keras.Model(inputs=inputs, outputs=outputs)# Instantiate an optimizer.
optimizer = keras.optimizers.SGD(learning_rate=1e-3)
# Instantiate a loss function.
loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=True)# Prepare the training dataset.
batch_size = 64
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(batch_size)epochs = 3
for epoch in range(epochs):print('Start of epoch %d' % (epoch,))# Iterate over the batches of the dataset.for step, (x_batch_train, y_batch_train) in enumerate(train_dataset):# Open a GradientTape to record the operations run# during the forward pass, which enables autodifferentiation.with tf.GradientTape() as tape:# Run the forward pass of the layer.# The operations that the layer applies# to its inputs are going to be recorded# on the GradientTape.logits = model(x_batch_train, training=True)  # Logits for this minibatch# Compute the loss value for this minibatch.loss_value = loss_fn(y_batch_train, logits)# Use the gradient tape to automatically retrieve# the gradients of the trainable variables with respect to the loss.grads = tape.gradient(loss_value, model.trainable_weights)# Run one step of gradient descent by updating# the value of the variables to minimize the loss.optimizer.apply_gradients(zip(grads, model.trainable_weights))# Log every 200 batches.if step % 200 == 0:print('Training loss (for one batch) at step %s: %s' % (step, float(loss_value)))print('Seen so far: %s samples' % ((step + 1) * 64))

 

参考资料

https://tensorflow.google.cn/guide/keras/custom_layers_and_models?hl=zh_cn

http://www.lbrq.cn/news/2403505.html

相关文章:

  • 网站仿站工具seo具体优化流程
  • 网站开发人员工作内容提高关键词排名的软文案例
  • 多新闻怎么做扁平网站百度软件安装
  • wordpress计费查询山东seo
  • 昆明网站设计代写文章兼职
  • 做网站什么职业百度搜索数据统计
  • 网站设计管理方向seo优化推广工程师
  • 哪里有网站建设服务全国疫情高中低风险区一览表
  • 南宁小程序建设seo排名培训学校
  • 北京市住房和城乡建设委官方网站2022年明星百度指数排行
  • 高端品牌名字大全深圳百度seo整站
  • 昌网站建设网站检测工具
  • 网站建设的基本流程包括营销网站优化推广
  • 网站搭建软件国际大新闻最新消息
  • 舞钢市做网站开发的公司seo咨询
  • 上海网站工作室如何查询网站收录情况
  • 塘沽做网站近三天发生的重要新闻
  • 郑州做网站价格山东搜索引擎优化
  • app网站制作软件免费b站网站推广
  • 用dw制作一个网站百度推广代理赚钱
  • 菠菜网站的代理怎么做网站推广广告
  • 网络公关在哪些方面能发挥作用seo关键词是什么
  • 网站组件google推广方式和手段有哪些
  • 新疆生产建设兵团水利局网站看啥网一个没有人工干预的网
  • 学习做网站只学过cseo推广人员
  • 瑶海区网站建设seo技术教学视频
  • 湘潭公司网站建设网盟推广
  • 陕西网站建设推广深圳seo推广公司
  • 晋城做网站公司怎样做推广更有效
  • 迅睿cms和帝国哪个好福州网seo
  • Qwen3-8B 与 ChatGPT-4o Mini 的 TTFT 性能对比与底层原理详解
  • Node.js 中基于请求 ID 实现简单队列(即时阻止策略/排队等待策略)
  • 支付宝支付
  • 马走日题解
  • 从零手写红黑树(C++实现详解)
  • Kotlin泛型约束