携程基于LSTM的广告库存预估算法

2023-05-18 18:32:00 携程技术

作者简介


(相关资料图)

Paul,携程高级研发经理,关注广告投放技术架构、大数据、人工智能等领域;

Xunling,携程资深后端开发工程师,关注广告服务、性能优化,对AI技术有浓厚兴趣。

一、背景

近年来,随着互联网的发展,在线广告营销成为一种非常重要的商业模式。出于广告流量商业化售卖和日常业务投放精细化运营的目的,需要对广告流量进行更精准的预估,从而更精细的进行广告库存管理。

因此,携程广告纵横平台实践了LSTM(Long Short-Term Memory,长短时记忆网络)模型结合Embedding的广告库存预估深度学习算法,在节省训练资源的同时,构建更具泛化性的模型,支持根据不同地域分布、人口学属性标签等进行库存变动预估,并能体现出节假日特征对库存波动的影响,从而对广告库存进行更为精确的预估。

二、问题和挑战

广告库存预估实现有诸多挑战:

现实中对广告库存的影响因素非常多,比如节假日、周末、自然灾害等等;广告库存样本周期以天为单位,训练样本很少;需要支持不同维度交叉进行广告预估,例如同时选择地域、年龄、性别、会员等级等定向交叉,预估未来N天的库存情况;广告库存日新月异,随时间推移,不断有新的库存样本生成,模型更新频率要求较高。

这些因素让广告库存预估工作从资源和效率等角度都带来压力。

三、算法简述

RNN(Recurrent Neural Network,循环神经网络)是一种特殊的神经网络,被广泛应用于序列数据的建模和预测,如自然语言处理、语音识别、时间序列预测等领域。RNN对时间序列的数据有着强大的提取能力,也被称作记忆能力。相对于传统的前馈神经网络,RNN具有循环连接,可以将前一时刻的输出作为当前时刻的输入,从而使得网络可以处理任意长度的序列数据,捕捉序列数据中的长期依赖关系。

图 3-1

LSTM(Long Short-Term Memory,长短时记忆网络)是一种特殊的 RNN,它通过引入门控机制和记忆单元等结构来增强 RNN 的记忆能力和表达能力。

LSTM 的基本结构包括一个循环单元和三个门控单元:输入门、遗忘门和输出门。循环单元接受当前时刻的输入和前一时刻的输出作为输入,并输出当前时刻的输出和传递到下一时刻的状态。输入门控制当前时刻的输入对状态的影响,遗忘门控制前一时刻的状态对当前状态的影响,输出门控制当前状态对输出的影响。记忆单元则用于存储和传递长期的信息。基于此,使得LSTM具有长期的记忆能力,并且具有防止梯度消失的特点,故我们选择LSTM作为库存预估模型的训练基础。

图 3-2

Embedding是一种特征处理方式,它可以将我们的某个特征数据向量化,可以将离散的整数序列映射为连续的实向量,它通常用于自然语言处理中的词嵌入(Word Embedding)任务,用于将每个单词映射为一个实向量,从而使得单词之间的语义关系可以在向量空间中进行计算。

在本文中,我们是使用它进行实体嵌入(Entity Embedding) 任务,也就是将我们的特征实体进行向量化,通过大量的数据训练,得到实体向量之前的细微关系,从而帮助模型更清晰的识别不同实体对广告库存的影响,进而提高模型的泛化能力。

四、数据处理4.1 特征定义

基础特征为下图所示:

图 4-1

由于节假日的特殊性,我们又将其细分为以下维度,保证模型抓住节前和节后购票效应。

图 4-2

4.2 归一化

在深度学习中,对数据进行归一化主要目的是将数据缩放到一个合适的范围内,便于神经网络的训练和优化。对数据进行归一化可以改善梯度下降、加速收敛、提高模型的泛化能力。

我们选择Z-score标准化方法对数据进行处理,Z-score 标准化(也称为标准差标准化)是一种常见的数据归一化方法,其基本思想是将原始数据转换为标准正态分布,即均值为 0,标准差为 1。公式如下图所示,是一个实测值与平均数的差再除以标准差的过程。

4.3 数据聚类

我们在第二章节问题和挑战中聊到过,广告库存预估需要对多个维度支持预估功能,不同维度交叉组合后,库存量千差万别,导致我们的样本数据中标签值min和max差距非常大。

如图4-3所示,本图Y轴表示某组合维度标签值的库存数据量级,库存数据量较小的组合维度占有很大一部分,而库存数据量较大的组合维度相对较少,仅凭数据归一化手段,数据压缩的效果非常不明显,如果强行一起训练会互相影响,导致模型难以拟合,训练中的损失函数如图4-4所示,训练时模型无法正常拟合,损失值不能够正常下降,训练出的模型效果可想而知,无法支持正常的预估功能。

图 4-3

图 4-4

所以,我们以库存样本的标签值为依据,使用K-means算法对不同维度的库存进行数据聚类,将近似类别的维度放在一起进行训练,提高模型的拟合速度和泛化能力。

我们选择“肘部法则”来确认本数据集的最佳分类数,也就是K-means的簇数K的具体值。随着K的增加,聚类效果不断提高,但是当K到达某个值的时候,聚类效果的提高变得越来越慢,此时再增加K已经不能明显提高聚类效果,因此这个点就是最佳的K值。具体过程如下:

对数据集进行K-Means聚类,分别尝试不同的簇数K。对于每个簇数K,计算该簇数下的SSE(Sum of Squared Errors),即每个数据点到其所属簇中心的距离的平方和,保存SSE 到数组。使用numpy库中的diff函数计算相邻两点的差异并除以最大值,得到变化率。然后,我们使用numpy库中的argmax函数找到最大斜率的位置,加上n即为肘部点的位置。n的取值要考虑自身数据集,一般来说,K的值至少要为2,不然没有分类意义,而且argmax计算出来的是数组的索引位置,小于真实位置1个点位,综合考虑,我们将n设置为2。
# 计算不同聚类个数下的聚类误差    n = 2    sse = []    for k in range(1, 10):        kmeans = KMeans(n_clusters=k, random_state=0).fit(data)        sse.append(kmeans.inertia_)    # 自动寻找肘部点    diff = np.diff(sse)    diff_r = diff[1:] / diff[:-1]    nice_k = np.argmin(diff_r) + n
#绘制SSE随簇数变化的曲线(如图4-5),观察曲线的形状。    plt.plot(range(1, 10), sse, "bx-")    plt.xlabel("Number of Clusters")    plt.ylabel("SSE")    plt.title("Elbow Method for Optimal k")    plt.show()

图 4-5

经过K值选择后,我们将样本数据集进行聚类得到如下图4-6所示结果,Y轴为某组合维度的标签值,X轴为某组合维度出现在样本数据集数组中的索引位置。其中最右侧最高的点,明显是没有任何维度交叉的全部广告库存,其他位置都是经过维度交叉后的库存,最终我们将其分成了3份进行训练。

图 4-6

经过聚类处理后,模型训练时损失函数输出的损失值如下图所示,出现了正常的损失值下降的过程,并逐渐趋于稳定。

图 4-7

五、网络结构定义与训练5.1 网络结构定义

1)网络模型结构图

图 5-1

2)网络模型定义

我们将各维度组装特征数据和标签数据的数据经过Embedding 实体嵌入,输入到LSTM学习并提取历史库存的时间序列特性,最终经过激活函数和全连接层输出与标签值进行损失值计算,不断拟合,直到损失值接近稳定或到达最大训练批次。

import torchfrom torch import nnclass LSTM(nn.Module):    def __init__(self, emb_dims, out_dim, hidden_dim, mid_layers):        super(LSTM, self).__init__()        self.emb_layers = nn.ModuleList([nn.Embedding(x, y) for x, y in emb_dims])        self.rnn = nn.LSTM([sum(x) for x in zip(*emb_dims)][1] + 1, hidden_dim, mid_layers, batch_first=False)        self.reg = nn.Sequential(            nn.Linear(hidden_dim, hidden_dim),            nn.Tanh(),            nn.Linear(hidden_dim, out_dim),        )    def forward(self, cat_data):        var_x = []        for cat in cat_data:            x = self.emb_layer(cat)            var_x.append(x)        stack = torch.stack(var_x)        y = self.rnn(stack)        return y
5.2 训练

1)组织数据

我们获取任意维度历史N天数据作为训练集,如下图所示,我们设定滑动窗口时间为七天,定义广告请求数为标签数据。使用DataLoader组织数据,shuffle设为True保证样本是随机获取的,仅需保证滑动窗口内部有序即可,这样训练可以提高模型的泛化能力。

loader = Data.DataLoader(dataset=set, batch_size=size, shuffle=True, num_workers=numWorkers)

需要注意的是,LSTM要求的入参顺序为(seq_length, batch_size, input_size)即:序列长度、批次量数、特征维度,然而DataLoade组织出的数据第一个维度是batch_size,因此设置batch_first = true,即可解决问题,继续正常的使用LSTM模型训练数据。但是这会拉低训练效率,原因是NVIDIA cuDNN 的RNN API 设置的batch_size参数就是在第二个位置,这样设置的原因如下:

举个例子1,假设输入序列的长度seq_length等于3,batch_size等于2,假设一个batch的数据是[[“A”, “B”, “C”], [“D”, “E”, “F”]],如图5-2所示。由于RNN是序列模型,只有T1时刻计算完成,才能进入T2时刻,而"batch"就体现在每个时刻Ti的计算过程中,图1中T1时刻将[“A”, “D”]作为当前时刻的batch数据,T2时刻将[“B”, “E”]作为当前时刻的batch数据,可想而知,“A"与"D"在内存中相邻比"A"与"B"相邻更合理,这样取数据时才更高效。

而不论Tensor的维度是多少,在内存中都以一维数组的形式存储,batch first意味着Tensor在内存中存储时,先存储第一个sequence,再存储第二个… 而如果是seq_length first,模型的输入在内存中,先存储所有sequence的第一个元素,然后是第二个元素… 两种区别如图5-3所示,seq_length first意味着不同sequence中同一个时刻对应的输入元素(比如"A”, “D” )在内存中是毗邻的,这样可以快速读取数据。

图 5-2

图 5-3

因此,使用batch_first = true并不是好的选择,可以选择permute函数解决此问题:

batch_x = batch_x.permute((1, 0, 2))

使用此方法改变数组的shape,以适应原始LSTM模型的入参要求,在不影响训练速度的原则下解决参数顺序问题。

2)训练步骤

输入: 任意维度前七天组成的窗口数据,包括所有的特征数据 + 标签数据

输出: 第八天的标签数据

第N步

图 5-4

第N+1步:

图 5-5

3)离线与在线增量训练

第二章节问题和挑战中提到,由于广告样本数据每天都在产生,而且影响其因素非常多,所以历史模型仅凭历史库存学到的时间序列特性预估出的未来库存,除了可以带有假期周末等时间特征的正向影响外,很难紧跟近期的库存数量级。

所以,这要求我们要高频次的更新广告库存预估模型,但这也加大了维护成本,如果仅采用离线训练的方式,每次都拉取全量历史库存样本数据训练出新的优质模型,无疑是不可取的,所以我们选择一次离线训练+N次在线增量训练的方式解决此问题。

a.离线训练

首先使用Spark Sql组织广告库存Hive表中现存所有的历史数据导入CSV文件,使用GPU训练此样本数据,由于是各维度交叉训练,一般在这个阶段数据量在亿级别,如果资源有限,离线训练可以拆分广告位分别进行。经过多次训练选择优质的离线模型文件,作为基础预估模型,可以用于短期的库存预估工作。此时我们需要将优质模型以字节的形式存储至Redis,便于后面的预估服务和在线训练脚本使用。

此时需要注意的是,我们需要将模型和优化器打包为一个字典,以二进制的方式读取模型文件并保存在Redis中。

#保存模型:#net:模型#optimizer:优化器 state = {"net": net.state_dict(), "optimizer": optimizer.state_dict()}torch.save(state, netPath)         #存储至Redis:def saveModel(modelName, netPath):    with open(modelPath, "rb") as f:        pth_model = f.read()    result = redis.set(modelName, pth_model)

b.在线训练:经过离线训练后,我们得到了一个优质的预估模型,此时我们需要开发两个脚本:

① PySpark 拉取hive表中昨天的库存样本存储在GPU机器实时文件目录。

② 读取实时文件目录,获取近八个文件,前七个作为一个滑动窗口数据,第八个作为标签值组成单次训练样本,在Redis中获取并加载预存的模型和优化器,进行一次在线训练,再将其覆盖保存至redis中。

# 在Redis中加载模型def readModel(modelName, path):    pthByte = redis.get(modelName)    with open(path, "wb") as f:        f.write(pthByte)    return torch.load(path, map_locatinotallow=lambda storage, loc: storage)  # 加载模型和优化器状态,用于训练 # 读取字典model = readModel(modelName, path)# 加载模型net = LSTM(emb_dims, out_dim, mid_dim, mid_layers).to(device)net.load_state_dict(model["net"])# 加载优化器optimizer = torch.optim.Adam(net.parameters(), lr=1e-2)optimizer.load_state_dict(model["optimizer"])

最终,我们将以上两个脚本配置在携程大数据定时任务,设置每天0点后执行,即可实现不断的在线训练,保证模型在优质状态的基础上,使用最新的库存数据对模型进行微调修正,使用Redis保存模型可以快速存取模型文件流,保证在线训练结束后,预估服务可以立刻反应,获取到新的模型用于预估工作,无需对预估服务做任何改动。根据以上方案可以不断维持模型提供精准的预估能力。

4)早停机制

训练过程中,为防止过拟合,也为提高效率,当loss 不再明显变化时终止训练,输出模型,每次训练不断记录并更新loss最小值,当loss 连续N次小于x时,视为可触发早停机制。

class EarlyStopping:             def __call__(self, val_loss):        score = val_loss        if self.best_score is None:            self.best_score = score        elif score > self.best_score:            if score <= x:                self.counter += 1            if self.counter >= self.patience:                self.early_stop = True        else:            self.best_score = score            self.counter = 0

下图为早停效果图,设置的训练批次为150批, 此模型训练至115批截至,可以观察到loss已经非常低, 已经没有下降空间,符合早停预期。

图 5-6

5)指标验证

经过模型的构建和训练后,我们需要对模型做出评估,以决定模型是否可以推到线上使用,因为基础数据量较小,所以本次模型未设置验证集,训练集和测试集 9 :1。评估指标采用WMAPE(加权偏差率):

TorchMetrics类库对80 多个PyTorch 指标做了实现.

这里我们直接调用api : WeightedMeanAbsolutePercentageError

import torchmetricserror = torchmetrics.WeightedMeanAbsolutePercentageError()# 调用模型得到预估值predict = net(valid_x)# 计算偏差error = error(predict, valid_y)error_list.append(error.item())

指标验证可以更科学的观察到模型对所有维度的测试集的预估能力, 可以更科学的验证模型是否符合我们的预期,指导我们进行调参,控制唯一变量并观察指标变化。某广告位置调参验证示例如下, 比较不同批次训练模型后指标比较, 明显表现出200批次的模型指标更好。

Group Model 1: 150批次 测试集ERROR: 0.09729844331741333 200批次 测试集ERROR: 0.08846557699143887

Group Model 2: 150批次 测试集ERROR: 0.10297603532671928 200批次 测试集ERROR: 0.09801376238465309

Group Model 3: 150批次 测试集ERROR: 0.0748182088136673 200批次 测试集ERROR: 0.07573202252388

6)内存释放

在大数据量的深度神经网络训练过程中,内存是我们的一大瓶颈,在组织数据过程中,python的List由于不能确定其存储内容的数据类型,不支持快速切割结构,我们经常需要将List转换为数组再做处理,此时需要copy一份数据,那么List就成了闲置内存,这种类似的闲置内存我们可以操作主动释放,以快速释放无用内存,让我们的机器可以在有限的内存空间中支持更大数据量的训练。

不同的数据类型的释放方式如下(假设变量名称为 X ):

# 1、Listdel X[:]# 2、数组X = []# 3、字典X.clear()# 4、Tensor(此方式需要调用gc.collect()触发GC才可以真正清除内存)del X# 5、清理CUDA显存import torchtorch.cuda.empty_cache()

下图5-7为训练过程中主动释放内存操作后,得到的内存释放监控反馈。

图 5-7

5.3 预估验证

1)历史预估

整体模型训练完成,需要对模型做预估测试,我们选择2022年的10月作为测试样本,10月1日国庆节有特殊的节假日特性,可以考量模型预估能力。以携程启动页广告位为例,图 5-8 分别展示了全量库存、某特征定向和两种会员等级定向不同维度的预估效果,都成功表达出10月1日的节假日上涨特性,与实际值的走势相似,证明我们训练出的模型具有预估未来广告库存的能力。

图 5-8

2)未来预估

以下是对未来库存的预估效果示例,从未来预估示例中,可以直观看出在4月26-29左右有流量的高峰,经过5月1日后高峰下跌,回归正常值,符五一的节假日效应。

图5-9 定向交叉为:某年龄段、某地

图 5-9

图5-10 定向交叉为:某年龄段、某类会员

图 5-10

图5-11 定向交叉为:某地、某类会员

图 5-11

六、模型部署6.1 python 服务部署

使用python flask组件开发部署restful接口,支持预估服务。

from flask import Flaskfrom flask import request, jsonify@app.route("/model/ad/forecast", methods=["post"])def forecast():    # 在clickhouse中实时获取前七天的标签值,传入接口    prepareData = request.json.get("prepareData")    return forecast(prepareData)

从Redis中读取对应维度的模型文件流,加载到内存生成模型对象,将前7天的标签值和对应其他特征组织好输入模型得到预估结果。

# 在Redis中加载模型def readModel(modelName, path):    pthByte = redis.get(modelName)    with open(path, "wb") as f:        f.write(pthByte)    return torch.load(path, map_locatinotallow=lambda storage, loc: storage)
七、总结

通过使用LSTM算法结合Embedding特征处理方式训练得到优质的广告库存预估模型,能够捕捉库存时间样本数据中的长期依赖关系,表达节假日、周末等特殊时间点对库存变化的影响,更具泛化能力,支持地域、年龄、会员等级、性别等定向交叉预估,对比早期使用全量库存乘以定向比例的预估库存方式,此方式更能体现出不同维度之间的相互影响关系,更贴近事实,预估准确度高。

使用离线与在线增量训练相结合的训练方式,使模型更具活力,每天在优选出的广告库存模型基础上进行微调,可以不断维持模型提供精准的预估能力。后续我们会继续优化和探索更优秀的模型和特征处理方式,优化方向考虑在Embedding层 与 LSTM 层之间增加CNN 卷积层,提高模型的特征提取能力,进而提高广告库存模型的泛化能力、预估精准度。

八、参考文献Pytorch lstm中batch_first 参数理解使用

标签:

相关文章

携程基于LSTM的广告库存预估算法

作者简介Paul,携程高级研发经理,关注广告投放技术架构、大数据、人工智能等领域;Xunling,携程资深后端

2023-05-18

邓州地图高清版政区图_邓州地图 当前热点

邓州地图高清版政区图,邓州地图这个很多人还不知道,现在让我们一起来看看吧!1、你可以选择百度地图打开寻

2023-05-18

天天热点!美媒称债务违约若发生 美国将被推入衰退

当地时间17日,美国两党仍未就债务上限问题达成协议,社会舆论持续发酵。当天,《财富》杂志刊登了一篇对前

2023-05-18

vivo xplay5旗舰版_vivo Xplay5

1、vivoXplay5是vivo于2016年3月1日在北京发布的手机。2、vivoXplay5屏幕采用5 43英寸

2023-05-18

孟州市大定街道:“夜经济”点燃发展“新引擎”_每日速读

大河报·豫视频记者李岩通讯员候微夜幕降临,位于孟州市大定街道韩愈大街东段的夜市灯火通明,人潮涌动...

2023-05-18

女士太阳镜十大品牌_太阳镜十大品牌 动态

1、选择太阳镜的时候一定要确认太阳镜是否具备防紫外线的功能,最简单的方法就是看价格,太便宜的太阳镜一

2023-05-18

自动写代码?Google Colab叫板github copilot

自动写代码?GoogleColab叫板githubcopilot,github,谷歌,代码,微软,javascript

2023-05-18

全国一般公共预算支出同比增长6.8% 重点领域支出得到保障

全国一般公共预算支出同比增长6 8%重点领域支出得到保障

2023-05-18

环球速递!“嗨·樊城”系列促消费活动正式启动

5月17日晚,“嗨·樊城”2023年度系列促消费活动启动仪式在湖北省襄阳市樊城区泛悦商场外广场举行。一系...

2023-05-18

微资讯!涉嫌严重违法!山东2地纪委监委通报

大众日报东营市据利津县纪委监委消息:利津县人力资源和社会保障局原四级调研员王德亮涉嫌严重违纪违法,目

2023-05-18

焦点资讯:伤心2009歌词王杰(伤心2009歌词)

伤心2009歌词王杰,伤心2009歌词很多人还不知道,现在让我们一起来看看吧!1 我要走了。也许我们在一起是错

2023-05-18

劳动者在同一用人单位连续工作满多少年后_劳动者在同一用人单位连续工作满-全球看热讯

1、劳动合同法规定,用人单位自用工之日起超过一个月不满一年未与劳动者订立书面劳动合同的,应当向劳动者

2023-05-18

拍身份证可以化妆吗(拍身份证可以涂口红吗) 每日热点

1、照身份证可以化妆,但不得影响真实面貌。2、身份证证件照的要求是免冠(不戴帽子)正面照片,照片上正常

2023-05-18

每日速看!小麦价格上调,5月18日小麦价格行情

今日,小麦市场价格上调。新季小麦面企开收,质量要求比较高,基本属于有价无市状态。距离新麦上市还有几天

2023-05-18

当地时间5月17日,哥伦比亚安蒂奥基亚省一金矿遭炸弹袭击,造成2人死亡,包括4名警察在内的14人受伤|天天热消息

当地时间5月17日,哥伦比亚安蒂奥基亚省一金矿遭炸弹袭击,造成2人死亡,包括4名警察在内的14人受伤。遭袭

2023-05-18

呼吸道合胞病毒是什么?与流感和新冠如何区分?来看儿科专家的解答|今日快看

新华社北京5月17日电(记者侠克)近日,不少家长反映孩子感染呼吸道合胞病毒,出现发热、咳嗽等症状,部分

2023-05-18

这些仿冒新闻单位、新闻主播,被集中清理!

国家网信办近期开展“清朗·规范重点流量环节网络传播秩序”专项行动,紧盯短视频平台、热搜热榜等重点...

2023-05-18

全球首个!5G异网漫游是什么,如何使用?_滚动

办理了中国移动的手机卡,能使用中国电信、联通的信号吗?乍一听异想天开,但以后真的要实现了。

2023-05-18

天天实时:百洋医药:5月17日融券卖出金额37.48万元,占当日流出金额的1.84%

同花顺数据中心显示,百洋医药5月17日获融资买入300 67万元,占当日买入金额的13 78%,当前融资余额8892 72

2023-05-18

卵巢早衰吃什么中药_卵巢早衰吃中药能完全恢复吗

1、舒气功能可以缓解失眠、多梦、烦躁、多汗等类似更年期的症状。2、不能使患者恢复正常排卵。3、女性难以

2023-05-18

刀山火海歌词_动了情的痞子歌词 天天要闻

1、动了心的痞子歌词:曾经的我一直都放荡不羁野的像风傲的像光如今的我为你画地为牢动了情的痞子真的连刀

2023-05-18

每日简讯:瑶圩乡_关于瑶圩乡介绍

瑶圩乡,关于瑶圩乡介绍这个很多人还不知道,我们一起来看看!瑶圩乡,隶属江西省抚州市东乡区,位于东乡区

2023-05-18

一名美国“志愿者”在乌东被击毙!瓦格纳创始人发声!德国、英国称不会援乌战斗机,波兰:无法给乌F-16 当前快讯

据央视新闻,当地时间5月17日,英国国防大臣华莱士在访问柏林期间表示,英国不会向乌克兰提供战斗机。德国

2023-05-18

今日热门!5月17日基金净值:富国兴利增强债券最新净值1.4496,涨0.1%

5月17日,富国兴利增强债券最新单位净值为1 4496元,累计净值为1 4496元,较前一交易日上涨0 1%。历史数据

2023-05-18

中国-中亚峰会|走,到长安去! 天天观速讯

西域骑手纵马疾驰他要去哪里?唐代的“流行天团”为何载歌载舞?帅气逼人的兵马俑向你投来爱的wink!“...

2023-05-17

全球看热讯:定制mRNA疫苗治疗“癌王”前景可期

据《自然》发表的一项研究报道,一种定制化的mRNA疫苗引起了可观的免疫响应,当与其他治疗方法一起使用时,

2023-05-17

95平新中式风两居室时尚前卫,薄荷绿沙发背景墙很清爽

95㎡新中式风两居室,整个设计方案的过程跟完美的配合,房子从面积上看不大,但是整体的色彩搭配的还是比较

2023-05-17

​专注内容换来业绩“狂飙”,但爱奇艺还不能松口气-环球讯息

​专注内容换来业绩“狂飙”,但爱奇艺还不能松口气,5月16日,爱奇艺发布截至2023年3月31日未经审计的第...

2023-05-17

盘江股份副总经理杨凤翔和梁玉柱辞职 2022年公司净利21.94亿 天天最新

盘江股份副总经理杨凤翔和梁玉柱辞职2022年公司净利21 94亿2023 5 1720:23:29挖贝网白杨树挖贝网5月17日,

2023-05-17

关于奥比岛的文案

想必现在有很多小伙伴对于关于奥比岛家族方面的知识都比较想要了解,那么今天小好小编就为大家收集了一些关

2023-05-17

最新发布
精彩图文
精彩推送

Copyright @  2015-2018 东方it网版权所有  备案号:沪ICP备2020036824号-8   联系邮箱:562 66 29@qq.com