智慧海洋建设TOP方案借鉴学习与整理

本文分析了智慧海洋建设中渔船作业方式,包括拖网、围网和刺网,以及渔船的Anchored-off、Turning、Straight-sailing三种状态。通过数据预处理、统计特征提取,如距离海岸线的近似值、轨迹位移特征和时间差统计,结合Geohash编码、Word2Vec和Node2Vec等方法表征轨迹信息。模型策略采用LightGBM,利用五折验证进行训练。


本文主要是学习了天池的智慧海洋建设比赛的一些TOP方案,并对思路进行整理,本文以TOP1的方案为主,其他方案作为补充。

参考的文章如下:

  1. 2020DCIC智能算法赛-智慧海洋建设TOP1方案
  2. DCIC 2020数字中国创新大赛数字政府赛道:智慧海洋建设Rank 3解决方案
  3. 智慧海洋复赛0.89937方案代码开源
  4. 智慧海洋建设算法赛道B榜top5 方案及源码
  5. 42个特征+xgboost top7方案-完整notebook

非常感谢前排大佬开源的方案

数据探索与预处理

渔船作业方式的定义

拖网:拖曳渔具在海底或海水中前进,对鱼类进行捕捞的作业方式。

围网:使用网具包围鱼群进行捕捞的作业方式

刺网:将长带形的网列敷设于水域中,使鱼刺入网目或被网衣缠络后加以捕捞

渔船作业过程中的三种状态

Anchored-off:船舶休息的点

Turning:船舶转弯的点

Straight-sailing:船舶航行的点

预处理

轨迹数据预处理方面, 将平面坐标转换为经纬度坐标。首先采用了经验阈值均值滤波去除了每条轨迹速度的异常值、坐标的离群点, 并用多项式插值函数对离群点进行了插值,基于局部速度对异常坐标点进行插值。

特征工程

统计特征

1,分箱特征,距离海岸线的近似值。

对v求分箱特征,等分为200份,求每一份的统计值
对x求分箱特征,1000份和10000份,求每一份的次数统计值,和每一个分箱对应不同id数目
对y求分箱特征,1000份和10000份,求每一份的次数统计值,和每一个分箱对应不同id数目
求x,y分箱后的组合特征做为分组,求对应的次数统计值,和对应的id的不同数目
根据x分组,求y距离最小y的距离 # 可以理解为距离海岸线距离
根据y分组,求x距离最小x的距离 # 可以理解为距离海岸线距离

2,对渔船的经纬度序列做均值、方差、分位数、众数等统计,可以简单地刻画渔船的活动范围

mode_df = data.groupby(['渔船ID', 'lat', 'lon'])['time'].agg({'mode_cnt':'count'}).reset_index()
mode_df['rank'] = mode_df.groupby('渔船ID')['mode_cnt'].rank(method='first', ascending=False)
for i in range(1, 4):
    tmp_df = mode_df[mode_df['rank']==i]
    del tmp_df['rank']
    tmp_df.columns = ['渔船ID', 'rank{}_mode_lat'.format(i), 'rank{}_mode_lon'.format(i), 'rank{}_mode_cnt'.format(i)]
    data_ = data_.merge(tmp_df, on=['渔船ID'], how='left')

3,间隔空间位移特征

根据id分组,对x求,上一个x,下一个x,间隔2个x的距离
根据id分组,对y求,上一个y,下一个y,间隔2个y的距离
根据上述距离,求上一时刻,下一时刻,间隔2个时刻的面积,相对值

4,行程特征

总行程距离
每一步行程的占比
将'dist_move_prev_bin_sen', 'v_bin_sen'转化为onehot稀疏特征

5,其他:

分别计算每个ship中速度大于0小于等于2、大于2小于等于6、大于6小于等于10的比例和平均值,三种区间代表三种运动状态,

以每个区间中的平均速度代表该船在该运动状态下的速度描述(根据速度的分布图选择的对速度的分箱方式)。以速度大于4的连续运动片段作为工作状态,计算每个ship中的工作状态片段并计算每个片段的位移作为作业间隔,统计每个ship中的作业间隔的中位数特征。

利用原数据’time’特征,提取其‘分钟’特征,计算其最大值。

时间差的平均值。时间差的分位数。时间差的中位数。

计算每个ship中角度的平均值。设计了拐角特征,并统计每艘船的三种拐角形式的数量,均值作为特征。

数据处理:skew较大的特征使用log函数将其正态化;与速度相关的特征保留其两位有效数字。

表征渔船的轨迹

POI信息

将每条轨迹投射到网格坐标系下,这样轨迹序列变为了网格id的符号序列; 随后我们基于被boat_id不同的渔船访问次数, 不同boat_id的渔船在该网格停留的平均时长和网格总的被访问的次数三个判据,筛选出了一系列的POI网格。

基于轨迹序列绝对和相对位置的复合向量编码

经纬度常规的统计特征对渔船轨迹信息的表征能力其实是有限的,这里我们设计了一种轨迹序列的编码方式(该方法可拓展至其他类型的轨迹序列数据),进一步刻画了轨迹的动态信息和渔船经过的每个点之间的联系

1,Geohash7编码:Geohash其实是将地图拆分成了一个个矩形网格,当经纬度落入到某个网格内时,则使用网格的编码代替经纬度,这相当于是一种聚类方式。这里我们不直接使用经纬度(细粒度)的好处就是可以提高特征的泛化能力。除此之外,我们还采用了全集下采样两种提取方式来提取Geohash7编码后的轨迹序列。下采样的好处是缓解渔船位置信息频繁上报而产生的噪音。

在这里插入图片描述

2,梯度编码:轨迹序列的梯度是指的后一个位置相对于前一个位置的变化,目的是为了获取相对位置信息

在这里插入图片描述

3,基于Word2Vec和Node2Vec的DNN编码:主要思想是将渔船的轨迹序列当成文本,每个地点(Geohash编码)则是一个 “词语”,使用Word2Vec进行向量表征;把渔船经过的地点构造成 “点”,而不同地点之间的关系构造成 “边”,使用Node2Vec进行向量表征。

def w2v_feat(df, group_id, feat, length):
    print('start word2vec ...')
    data_frame = df.groupby(group_id)[feat].agg(list).reset_index()
    model = Word2Vec(data_frame[feat].values, size=length, window=5, min_count=1, sg=1, hs=1,
                     workers=1, iter=10, seed=1, hashfxn=hashfxn)
    # data_frame[feat] 存放每个渔船的[xz5k92v, xz5k99f, ...,xz5kdjj]对应的【二维表】,维度:(n , 30)
    # n 是渔船的所有轨迹记录[xz5k92v, xz5k99f, ...,xz5kdjj]的个数
    # 30是每个轨迹数据,如xz5k92v,通过Word2Vec得到是30维向量
    # 即每一行都存放了一个轨迹记录的30维向量
    data_frame[feat] = data_frame[feat].apply(lambda x: pd.DataFrame([model[c] for c in x]))
    # 遍历30维向量的每个分量
    for m in range(length):
        # 计算n行30维向量 的 每个分量 的均值,也就是计算第m列均值,作为该渔船的一个Word2Vec特征。
        data_frame['w2v_{}_mean'.format(m)] = data_frame[feat].apply(lambda x: x[m].mean())
    del data_frame[feat]
    return data_frame

4,TFIDF&CountVec编码:

此类编码方式也是借鉴了文本的常用处理方法,提取渔船轨迹序列中Geohash的频次信息。

def tfidf(input_values, output_num, output_prefix, seed=1024):
    tfidf_enc = TfidfVectorizer()
    tfidf_vec = tfidf_enc.fit_transform(input_values)
    svd_tmp = TruncatedSVD(n_components=output_num, n_iter=20, random_state=seed)
    svd_tmp = svd_tmp.fit_transform(tfidf_vec)
    svd_tmp = pd.DataFrame(svd_tmp)
    svd_tmp.columns = ['{}_tfidf_{}'.format(output_prefix, i) for i in range(output_num)]
    return svd_tmp

表征渔船不同状态下的信息

Anchored-off状态特征

认为当渔船的速度为0时,渔船处于停靠或是收网的状态。统计该状态下渔船所处的位置,可以让模型捕捉到不同作业方式下渔船停靠点或收网点的规律。

for col in ['lat', 'lon']:
    print(col)
    group_df = data[data['速度']==0].groupby(['渔船ID'])[col].agg(
                     {'锚点_'+col+'_mean': 'mean',
                      '锚点_'+col+'_max': 'max',
                      '锚点_'+col+'_min': 'min',
                      '锚点_'+col+'_nuniq': 'nunique',
                      '锚点_'+col+'_q1': lambda x: np.quantile(x, 0.10),
                      '锚点_'+col+'_q2': lambda x: np.quantile(x, 0.20),
                      '锚点_'+col+'_q3': lambda x: np.quantile(x, 0.30),
                      '锚点_'+col+'_q4': lambda x: np.quantile(x, 0.40),
                      '锚点_'+col+'_q5': lambda x: np.quantile(x, 0.50),
                      '锚点_'+col+'_q6': lambda x: np.quantile(x, 0.60),
                      '锚点_'+col+'_q7': lambda x: np.quantile(x, 0.70),
                      '锚点_'+col+'_q8': lambda x: np.quantile(x, 0.80),
                      '锚点_'+col+'_q9': lambda x: np.quantile(x, 0.90)}
                     ).reset_index()
    features = features.merge(group_df, on=['渔船ID'], how='left')

Turning状态特征

将数值型的方向特征进行离散化处理后,统计渔船作业过程中不同方向的频次及比例。

data['方向'] = data['方向'].apply(lambda x:(int(round(x/30)))*30)
degree_df = data.pivot_table(index='渔船ID',columns='方向',values='lat', dropna=False, aggfunc='count').fillna(0)
degree_df.columns = [str(f)+'_方向_count' for f in degree_df.columns]
degree_df.reset_index(inplace=True)

Straight-sailing状态特征

渔船的历史数据中存在大量的速度为0的记录,会对速度进行均值、方差等统计产生较大的影响。我们单独取速度大于0时的样本,再对速度构造统计特征,一方面去除速度为0的影响、另一方面刻画了渔船航行时的状态。

group_df = data[data['速度']>0].groupby(['渔船ID'])['速度'].agg({
    '速度_mean_new': 'mean',
    '速度_q10_new': lambda x: np.quantile(x, 0.10),
    '速度_q20_new': lambda x: np.quantile(x, 0.20),
    '速度_q30_new': lambda x: np.quantile(x, 0.30),
    '速度_q40_new': lambda x: np.quantile(x, 0.40),
    '速度_q50_new': lambda x: np.quantile(x, 0.50),
    '速度_q60_new': lambda x: np.quantile(x, 0.60),
    '速度_q70_new': lambda x: np.quantile(x, 0.70),
    '速度_q80_new': lambda x: np.quantile(x, 0.80),
    '速度_q90_new': lambda x: np.quantile(x, 0.90),
}).reset_index()

动态信息特征

每个渔船id的速度、经纬度看做是一个序列信息

利用速度、经纬度的分位数统计量,将浮点特征分桶转成一个类型特征

使用不同的ngram提取TF-IDF 特征(ngram=1, 2, 3)

最终,利用NLP的TF-IDF提取关键高维的ngram信息,有效获取速度和经纬度动态变化的信息

模型策略

五折验证,使用的lightgbm参数如下:

params = {
        'learning_rate': 0.05,
        'boosting_type': 'gbdt',
        'objective': 'multiclass',
        'metric': 'None',
        'num_leaves': 63,
        'feature_fraction': 0.8,
        'bagging_fraction': 0.8,
        'bagging_freq': 5,
        'seed': 1,
        'bagging_seed': 1,
        'feature_fraction_seed': 7,
        'min_data_in_leaf': 20,
        'num_class': n_class,
        'nthread': 8,
        'verbose': -1,
    }

再次感谢前排大佬开源的方案

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值