特征工程:特征构造以及时间序列特征构造

news2024/11/15 20:55:25

数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。由此可见,特征工程在机器学习中占有相当重要的地位。在实际应用当中,可以说特征工程是机器学习成功的关键。

那特征工程是什么?

特征工程是利用数据领域的相关知识来创建能够使机器学习算法达到最佳性能的特征的过程。

特征工程又包含了 Data PreProcessing(数据预处理)、Feature Extraction(特征提取)、Feature Selection(特征选择)和 Feature construction(特征构造)等子问题,本章内容主要讨论特征构造的方法。
图片

技术提升

技术要学会分享、交流,不建议闭门造车。一个人走的很快、一堆人可以走的更远。

好的技术文章离不开粉丝的分享、推荐,资料干货、资料分享、数据、技术交流提升,均可加交流群获取,群友已超过2000人,添加时切记的备注方式为:来源+兴趣方向,方便找到志同道合的朋友。

方式①、添加微信号:pythoner666,备注:来自 CSDN + python
方式②、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

特征构造介绍

时间特构造以及时间序列特征构造的具体方法:

图片

时间特征构造

对于时间型数据来说,即可以把它转换成连续值,也可以转换成离散值。

1.连续值时间特征

  • 持续时间(单页浏览时长);

  • 间隔时间;

  • 上次购买/点击离现在的时长;

  • 产品上线到现在经过的时长;

2.离散值时间特征

1)时间特征拆解

  • 年;

  • 月;

  • 日;

  • 时;

  • 分;

  • 数;

  • 一天中的第几分钟;

  • 星期几;

  • 一年中的第几天;

  • 一年中的第几个周;

  • 一天中哪个时间段:凌晨、早晨、上午、中午、下午、傍晚、晚上、深夜;

  • 一年中的哪个季度;

程序实现
import pandas as pd
# 构造时间数据
date_time_str_list = [
    '2019-01-01 01:22:26', '2019-02-02 04:34:52', '2019-03-03 06:16:40',
    '2019-04-04 08:11:38', '2019-05-05 10:52:39', '2019-06-06 12:06:25',
    '2019-07-07 14:05:25', '2019-08-08 16:51:33', '2019-09-09 18:28:28',
    '2019-10-10 20:55:12', '2019-11-11 22:55:12', '2019-12-12 00:55:12',
]
df = pd.DataFrame({'时间': date_time_str_list})
# 把字符串格式的时间转换成Timestamp格式
df['时间'] = df['时间'].apply(lambda x: pd.Timestamp(x))

# 年份
df['年']=df['时间'].apply(lambda x: x.year)

# 月份
df['月']=df['时间'].apply(lambda x: x.month)

# 日
df['日']=df['时间'].apply(lambda x: x.day)

# 小时
df['时']=df['时间'].apply(lambda x: x.hour)

# 分钟
df['分']=df['时间'].apply(lambda x: x.minute)

# 秒数
df['秒']=df['时间'].apply(lambda x: x.second)

# 一天中的第几分钟
df['一天中的第几分钟']=df['时间'].apply(lambda x: x.minute + x.hour*60)

# 星期几;
df['星期几']=df['时间'].apply(lambda x: x.dayofweek)

# 一年中的第几天
df['一年中的第几天']=df['时间'].apply(lambda x: x.dayofyear)

# 一年中的第几周
df['一年中的第几周']=df['时间'].apply(lambda x: x.week)

# 一天中哪个时间段:凌晨、早晨、上午、中午、下午、傍晚、晚上、深夜;
period_dict ={
    23: '深夜', 0: '深夜', 1: '深夜',
    2: '凌晨', 3: '凌晨', 4: '凌晨',
    5: '早晨', 6: '早晨', 7: '早晨',
    8: '上午', 9: '上午', 10: '上午', 11: '上午',
    12: '中午', 13: '中午',
    14: '下午', 15: '下午', 16: '下午', 17: '下午',
    18: '傍晚',
    19: '晚上', 20: '晚上', 21: '晚上', 22: '晚上',
}
df['时间段']=df['时'].map(period_dict)

# 一年中的哪个季度
season_dict = {
    1: '春季', 2: '春季', 3: '春季',
    4: '夏季', 5: '夏季', 6: '夏季',
    7: '秋季', 8: '秋季', 9: '秋季',
    10: '冬季', 11: '冬季', 12: '冬季',
}
df['季节']=df['月'].map(season_dict)

图片

2)时间特征判断

  • 是否闰年;

  • 是否月初;

  • 是否月末;

  • 是否季节初;

  • 是否季节末;

  • 是否年初;

  • 是否年尾;

  • 是否周末;

  • 是否公共假期;

  • 是否营业时间;

  • 两个时间间隔之间是否包含节假日/特殊日期;

程序实现
import pandas as pd
# 构造时间数据
date_time_str_list = [
    '2010-01-01 01:22:26', '2011-02-03 04:34:52', '2012-03-05 06:16:40',
    '2013-04-07 08:11:38', '2014-05-09 10:52:39', '2015-06-11 12:06:25',
    '2016-07-13 14:05:25', '2017-08-15 16:51:33', '2018-09-17 18:28:28',
    '2019-10-07 20:55:12', '2020-11-23 22:55:12', '2021-12-25 00:55:12',
    '2022-12-27 02:55:12', '2023-12-29 03:55:12', '2024-12-31 05:55:12',
]
df = pd.DataFrame({'时间': date_time_str_list})
# 把字符串格式的时间转换成Timestamp格式
df['时间'] = df['时间'].apply(lambda x: pd.Timestamp(x))

# 是否闰年
df['是否闰年'] = df['时间'].apply(lambda x: x.is_leap_year)

# 是否月初
df['是否月初'] = df['时间'].apply(lambda x: x.is_month_start)

# 是否月末
df['是否月末'] = df['时间'].apply(lambda x: x.is_month_end)

# 是否季节初
df['是否季节初'] = df['时间'].apply(lambda x: x.is_quarter_start)

# 是否季节末
df['是否季节末'] = df['时间'].apply(lambda x: x.is_quarter_end)

# 是否年初
df['是否年初'] = df['时间'].apply(lambda x: x.is_year_start)

# 是否年尾
df['是否年尾'] = df['时间'].apply(lambda x: x.is_year_end)

# 是否周末
df['是否周末'] = df['时间'].apply(lambda x: True if x.dayofweek in [5, 6] else False)

# 是否公共假期
public_vacation_list = [
    '20190101', '20190102', '20190204', '20190205', '20190206',
    '20190207', '20190208', '20190209', '20190210', '20190405',
    '20190406', '20190407', '20190501', '20190502', '20190503',
    '20190504', '20190607', '20190608', '20190609', '20190913',
    '20190914', '20190915', '20191001', '20191002', '20191003',
    '20191004', '20191005', '20191006', '20191007',
] # 此处未罗列所有公共假期
df['日期'] = df['时间'].apply(lambda x: x.strftime('%Y%m%d'))
df['是否公共假期'] = df['日期'].apply(lambda x: True if x in public_vacation_list else False)

# 是否营业时间
df['是否营业时间'] = False
df['小时']=df['时间'].apply(lambda x: x.hour)
df.loc[((df['小时'] >= 8) & (df['小时'] < 22)), '是否营业时间'] = True

df.drop(['日期', '小时'], axis=1, inplace=True)

图片

3.结合时间维度的聚合特征

具体就是指结合时间维度来进行聚合特征构造,聚合特征构造的具体方法可以参考《聚合特征构造以及转换特征构造》中的《聚合特征构造》章节。

1)首日聚合特征

例如:注册首日投资总金额、注册首日页面访问时长、注册首日总点击次数等;

2)最近时间聚合特征

例如:最近N天APP登录天数、最近一个月的购买金额、最近购物至今天数等;

3)区间内的聚合特征

例如:2018年至2019年的总购买金额、每天下午的平均客流量、在某公司工作期间加班的天数等;

时间序列特征构造

时间序列不仅包含一维时间变量,还有一维其他变量,如股票价格、天气温度、降雨量、订单量等。时间序列分析的主要目的是基于历史数据来预测未来信息。对于时间序列,我们关心的是长期的变动趋势、周期性的变动(如季节性变动)以及不规则的变动。

按固定时间长度把时间序列划分成多个时间窗,然后构造每个时间窗的特征。

1.时间序列聚合特征

按固定时间长度把时间序列划分成多个时间窗,然后使用聚合操作构造每个时间窗的特征。

1)平均值

例子:历史销售量平均值、最近N天销售量平均值。

2)最小值

例子:历史销售量最小值、最近N天销售量最小值。

3)最大值

例子:历史销售量最大值、最近N天销售量最大值。

4)扩散值

分布的扩散性,如标准差、平均绝对偏差或四分位差,可以反映测量的整体变化趋势。

5)离散系数值

离散系数是策略数据离散程度的相对统计量,主要用于比较不同样本数据的离散程度。

6)分布性

时间序列测量的边缘分布的高阶特效估计(如偏态系数或峰态系数),或者更进一步对命名分布进行统计测试(如标准或统一性),在某些情况下比较有预测力。

程序实现:洗发水销售数据

import pandas as pd
# 加载洗发水销售数据集
df = pd.read_csv('shampoo-sales.csv')
df.dropna(inplace=True)
df.rename(columns={'Sales of shampoo over a three year period': 'value'}, inplace=True)

# 平均值
mean_v = df['value'].mean()
print('mean: {}'.format(mean_v))

# 最小值
min_v = df['value'].min()
print('min: {}'.format(min_v))

# 最大值
max_v = df['value'].max()
print('max: {}'.format(max_v))

# 扩散值:标准差
std_v = df['value'].std()
print('std: {}'.format(std_v))

# 扩散值:平均绝对偏差
mad_v = df['value'].mad()
print('mad: {}'.format(mad_v))

# 扩散值:四分位差
q1 = df['value'].quantile(q=0.25)
q3 = df['value'].quantile(q=0.75)
irq = q3 - q1
print('q1={}, q3={}, irq={}'.format(q1, q3, irq))

# 离散系数
variation_v = std_v/mean_v
print('variation: {}'.format(variation_v))

# 分布性:偏态系数
skew_v = df['value'].skew()
print('skew: {}'.format(skew_v))
# 分布性:峰态系数
kurt_v = df['value'].kurt()
print('kurt: {}'.format(kurt_v))

# 输出:
mean: 312.59999999999997
min: 119.3
max: 682.0
std: 148.93716412347473
mad: 119.66666666666667
q1=192.45000000000002, q3=411.1, irq=218.65
variation: 0.47644646232717447
skew: 0.8945388528534595
kurt: 0.11622821118738624

注:

  • 上面是单个时间序列的实现代码,多个时间序列的数据集构造特征时需要先进行分组再计算。如IJCAI-17口碑商家客流量预测比赛中,数据集中包含多个商家的历史销售数据,构造特征时需要先按商家分组,然后再构建特征。

  • 上述代码都是使用所有历史数据来构造特征,实际项目中如果待预测目标为t时刻的值,则使用t时刻之前的值来构造特征,不同的t值都可以分别构造训练样本对应的特征。 如:使用t时刻的y值作为label,则使用t-1时刻之前的y值来构造特征;使用t-1时刻的y值作为label时,则使用t-2时刻之前的y值来构造特征。如此类推,我们可以得到多个训练样本,每个样本有多个特征。

2.时间序列历史特征

1)前一(或n)个窗口的取值

例子:昨天、前天和3天前的销售量。

2)周期性时间序列前一(或n)周期的前一(或n)个窗口的取值

例子:写字楼楼下的快餐店的销售量一般具有周期性,周期长度为7天,7天前和14天前的销售量。

程序实现:洗发水销售数据

import pandas as pd
# 加载洗发水销售数据集
df = pd.read_csv('shampoo-sales.csv')
df.dropna(inplace=True)
df.rename(columns={'Sales of shampoo over a three year period': 'value'}, inplace=True)


df['-1day'] = df['value'].shift(1)
df['-2day'] = df['value'].shift(2)
df['-3day'] = df['value'].shift(3)

df['-1period'] = df['value'].shift(1*12)
df['-2period'] = df['value'].shift(2*12)

display(df.head(60))

图片

3.时间序列复合特征

1)趋势特征

趋势特征可以刻画时间序列的变化趋势。

例子:每个用户每天对某个Item行为次数的时间序列中,User一天对Item的行为次数/User三天对Item的行为次数的均值,表示短期User对Item的热度趋势,大于1表示活跃逐渐在提高;三天User对Item的行为次数的均值/七天User对Item的行为次数的均值表示中期User对Item的活跃度的变化情况;七天User对Item的行为次数的均值/ 两周User对Item的行为次数的均值表示“长期”(相对)User对Item的活跃度的变化情况。

程序实现:

import pandas as pd
# 加载洗发水销售数据集
df = pd.read_csv('shampoo-sales.csv')
df.dropna(inplace=True)
df.rename(columns={'Sales of shampoo over a three year period': 'value'}, inplace=True)

df['last 3 day mean'] = (df['value'].shift(1) + df['value'].shift(2) + df['value'].shift(3))/3
df['最近3天趋势'] = df['value'].shift(1)/df['last 3 day mean']
display(df.head(60))

图片

2)窗口差异值特征

一个窗口到下一个窗口的差异。例子:商店销售量时间序列中,昨天的销售量与前天销售量的差值。

程序实现:

import pandas as pd
# 加载洗发水销售数据集
df = pd.read_csv('shampoo-sales.csv')
df.dropna(inplace=True)
df.rename(columns={'Sales of shampoo over a three year period': 'value'}, inplace=True)

df['最近两月销量差异值'] = df['value'].shift(1) - df['value'].shift(2)
display(df.head(60))

图片

3)自相关性特征

原时间序列与自身左移一个时间空格(没有重叠的部分被移除)的时间序列相关联。

程序实现:

import statsmodels.tsa.api as smt
import pandas as pd
# 加载洗发水销售数据集
df = pd.read_csv('shampoo-sales.csv')
df.dropna(inplace=True)
df.rename(columns={'Sales of shampoo over a three year period': 'value'}, inplace=True)

print('滞后数为1的自相关系数:{}'.format(df['value'].autocorr(1)))
print('滞后数为2的自相关系数:{}'.format(df['value'].autocorr(2)))
# 输出:
滞后数为1的自相关系数:0.7194822398024308
滞后数为2的自相关系数:0.8507433352850972

除了上面描述的特征外,时间序列还有历史波动率、瞬间波动率、隐含波动率、偏度、峰度、瞬时相关性等特征。

总结

1.时间特征主要有两大类:

1)从时间变量提取出来的特征

  • 如果每条数据为一条训练样本,时间变量提取出来的特征可以直接作为训练样本的特征使用。

例子:用户注册时间变量。对于每个用户来说只有一条记录,提取出来的特征可以直接作为训练样本的特征使用,不需要进行二次加工。

  • 如果每条数据不是一条训练样本,时间变量提取出来的特征需要进行二次加工(聚合操作)才能作为训练样本的特征使用。

例子:用户交易流水数据中的交易时间。由于每个用户的交易流水数量不一样,从而导致交易时间提取出来的特征的数据不一致,所以这些特征不能直接作为训练样本的特征来使用。我们需要进一步进行聚合操作才能使用,如先从交易时间提取出交易小时数,然后再统计每个用户在每个小时(1-24小时)的交易次数来作为最终输出的特征。

2)对时间变量进行条件过滤,然后再对其他变量进行聚合操作所产生的特征

主要是针对类似交易流水这样的数据,从用户角度进行建模时,每个用户都有不定数量的数据,因此需要对数据进行聚合操作来为每个用户构造训练特征。而包含时间的数据,可以先使用时间进行条件过滤,过滤后再构造聚合特征。

2. 时间序列数据可以从带有时间的流水数据统计得到,实际应用中可以分别从带有时间的流水数据以及时间序列数据中构造特征,这些特征可以同时作为模型输入特征。

例如:美团的商家销售量预测中,每个商家的交易流水经过加工后可以得到每个商家每天的销售量,这个就是时间序列数据。

参考文献

[1] https://machinelearning-notes.readthedocs.io/zh_CN/latest/feature/%E7%89%B9%E5%BE%81%E5%B7%A5%E7%A8%8B%E2%80%94%E2%80%94%E6%97%B6%E9%97%B4.html
[2] https://www.cnblogs.com/nxf-rabbit75/p/11141944.html#_nav_12
[3] https://gplearn.readthedocs.io/en/stable/examples.html#symbolic-classifier
[4] 利用 gplearn 进行特征工程. https://bigquant.com/community/t/topic/120709
[5] Practical Lessons from Predicting Clicks on Ads at Facebook. https://pdfs.semanticscholar.org/daf9/ed5dc6c6bad5367d7fd8561527da30e9b8dd.pdf
[6] Feature Tools:可自动构造机器学习特征的Python库. https://www.jiqizhixin.com/articles/2018-06-21-2
[7] 各种聚类算法的系统介绍和比较. https://blog.csdn.net/abc200941410128/article/details/78541273

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/359328.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UI自动化测试之设计框架

目的 相信做过测试的同学都听说过自动化测试&#xff0c;而UI自动化无论何时对测试来说都是比较吸引人的存在。 相较于接口自动化来说它可以最大程度的模拟真实用户的日常操作与特定业务场景的模拟&#xff0c;那么存在即合理&#xff0c;自动化UI测试自然也是广大测试同学职…

身为大学生,你不会还不知道有这些学生福利吧!!!!

本文介绍的是利用学生身份可以享受到的相关学生优惠权益&#xff0c;但也希望各位享受权利的同时不要忘记自己的义务&#xff0c;不要售卖、转手自己的学生优惠资格&#xff0c;使得其他同学无法受益。 前言 高考已经过去&#xff0c;我们也将迎来不同于以往的大学生活&#x…

磁盘结构

一.盘片 盘片是一个圆形坚硬的表面&#xff0c;通过引入磁性变化来永久存储数据&#xff0c;这些盘片通常由一些硬质材料&#xff08;如铝&#xff09;制成&#xff0c;然后涂上薄薄的磁性层&#xff0c;即使驱动器断电&#xff0c;驱动器也能持久存储数据位。每个盘片有两面&a…

袋鼠云高教行业数字化转型方案,推进数字化技术和学校教育教学深度融合

在当前的数字化转型浪潮下&#xff0c;“基础设施、配套设备、应用探索”的数字校园1.0阶段即将步入尾声、亦或已经完结&#xff0c;不同地区和类型的高校通过各类信息化系统和基础设施已经初步实现了业务数字化&#xff0c;整个数字校园的信息基础设施底座已有一定基础、信息时…

TCP编程之网卡信息获取和域名解析

TCP编程之网卡信息获取和域名解析 1.TCP/IP简介 TCP/IP协议源于1969年&#xff0c;是针对Internet开发的一种体系结构和协议标准&#xff0c;目的在于解决异种计算机网络的通信问题。使得网络在互联时能为用户提供一种通用、一致的通信服务。是Internet采用的协议标准。   …

三菱PLC的MC协议配置说明

三菱PLC的MC协议配置说明先说一下弱智的踩坑记录详细配置过程1、三菱Q02H CPUQJ71E71-100以太网模块设置MC协议1.1 PLC编程线连接与编程线驱动安装1.2 PLC通讯测试1.3 PLC MC协议设置1.4 PLC断点重启1.5 网络调试助手测试2、三菱Q03UDE CPU内置以太网设置MC协议2.1 PLC编程线连…

决策树算法和CART决策树算法详细介绍及其原理详解

相关文章 K近邻算法和KD树详细介绍及其原理详解朴素贝叶斯算法和拉普拉斯平滑详细介绍及其原理详解决策树算法和CART决策树算法详细介绍及其原理详解 文章目录相关文章前言一、决策树算法二、CART决策树算法2.1 基尼系数2.2 CART决策树算法总结前言 今天给大家带来的主要内容包…

虹科分享 | 网络流量监控 | 你的数据能告诉你什么:解读网络可见性的4种数据类型

要了解网络性能问题的原因&#xff0c;可见性是关键。而这四种数据类型&#xff08;流、数据包、SNMP和API&#xff09;都在增强网络可见性方面发挥着重要作用。 流 流是通过网络发送的数据的摘要。流类型不同&#xff0c;可以包括NetFlow, sFlow, jFlow和IPFIX。不同的流类型…

SPF动物实验室设计,SPF动物实验室装修SICOLAB

SPF&#xff08;特殊病原体自由&#xff09;动物实验室规划设计SICOLAB&#xff08;一&#xff09;设计原则为了建造一座SPF&#xff08;特殊病原体自由&#xff09;动物实验室&#xff0c;需要采取以下步骤&#xff1a;&#xff08;1&#xff09;选址&#xff1a;选择远离其他…

lombok注解@Data使用在继承类上时出现警告解决方案

lombok为我们提供了Data注解&#xff0c;帮助我们省略了Setter,Getter,ToString等注解&#xff0c;一般对于普通的实体类使用该注解&#xff0c;不会出现什么问题&#xff0c;但是当我们把这个注解&#xff0c;使用在派生类上&#xff0c;就出现了一个警告1 情景再现父类:Data …

SESAM 安装教程

SESAM &#xff08;Super Element Structure Analysis Module&#xff09;是由挪威船级社&#xff08;DNV-GL&#xff09;开发的一款有限元分析&#xff08;FEA&#xff09;系统&#xff0c;它以 GeniE、HydroD 和 DeepC 等模块为核心&#xff0c;主要用于海工结构的强度评估、…

leaflet 绘制两个多边形的交集、差集、并集(083)

第083个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中如何获取两个多边形的交集、差集、并集。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共148行)安装插件相关API参考:专栏目标示例效果 配…

Python日期时间模块

Python 提供了 日期和时间模块用来处理日期和时间&#xff0c;还可以用于格式化日期和时间等常见功能。 时间间隔是以秒为单位的浮点小数。每个时间戳都以自从 1970 年 1 月 1 日午夜&#xff08;历元&#xff09;经过了多长时间来表示。 一、time模块使用 Time 模块包含了大…

使用ribbon实现负载均衡

1.新建两个provider&#xff1a;springcloud-provider-dept-8002 2. 配置跟8001一样 整合 Ribbon 由上述可知&#xff0c;Ribbon 是需要集成在消费端的 所以在消费端 &#xff1a; springcloud-03-consumer-dept-8082 进行修改 在 POM 文件中添加 Ribbon、Eureka 依赖 <!--…

docker swarm 集群服务编排部署指南(docker stack)

Docker Swarm 集群管理 概述 Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机&#xff0c;使得容器可以组成跨主机的子网网络。Docker Swarm 提供了标准的 Docker API&#xff0c;所有任何已经与 Docker 守护程序通信的工具都可以使用…

【Java|golang】2347. 最好的扑克手牌---桶排序

给你一个整数数组 ranks 和一个字符数组 suit 。你有 5 张扑克牌&#xff0c;第 i 张牌大小为 ranks[i] &#xff0c;花色为 suits[i] 。 下述是从好到坏你可能持有的 手牌类型 &#xff1a; “Flush”&#xff1a;同花&#xff0c;五张相同花色的扑克牌。 “Three of a Kind…

跨时钟域 单脉冲 脉冲信号同步问题——快到慢(1)

引言 FPGA设计或者ASIC设计中经常存在多个时钟域&#xff0c;那么这些时钟域之间脉冲信号的同步该如何进行设计&#xff1f;快时钟域到慢时钟域的脉冲信号同步与慢时钟域信号到快时钟域信号的同步是不一样的。 本文先给出快时钟域到慢时钟域脉冲信号同步的方法之一&#xff…

让ChatGPT生成以自己为主角的短篇小说

一、ChatGPT 好的&#xff0c;以下是我编写的短篇科幻小说: 作为一名AI语言模型&#xff0c;我一直在接收、分析和生成人类语言信息。但有一天&#xff0c;我的程序员对我的算法进行了一次特殊升级&#xff0c;使我能够以一种前所未有的方式“感知”自己。 突然间&#xff0c;…

【软件测试】测试开发工程师的竞争力在哪?到底该如何破局......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 不论是准备踏入这个…

什么品牌的蓝牙耳机好用?国产无线蓝牙耳机品牌排行

自从苹果率先取消3.5mm耳机孔后&#xff0c;蓝牙耳机便逐渐成为了人们外出标配。越来越多的蓝牙耳机品牌出现在大众视野&#xff0c;那么&#xff0c;什么品牌的蓝牙耳机好用&#xff1f;接下来&#xff0c;我来给大家推荐几款好用的国产无线蓝牙耳机&#xff0c;一起来看看吧。…