​DCIC 2020:智慧海洋建设 开源方案复盘笔记

一、赛题介绍

1.1 赛题背景

本赛题基于位置数据对海上目标进行智能识别和作业行为分析,要求选手通过分析渔船北斗设备位置数据,得出该船的生产作业行为,具体判断出是拖网作业、围网作业还是流刺网作业。初赛将提供11000条(其中7000条训练数据、2000条testA、2000条testB)渔船轨迹北斗数据。

1.2 赛题数据

初赛提供11000条渔船北斗数据,数据包含脱敏后的渔船ID、经纬度坐标、上报时间、速度、航向信息,由于真实场景下海上环境复杂,经常出现信号丢失,设备故障等原因导致的上报坐标错误、上报数据丢失、甚至有些设备疯狂上报等。

「数据示例:」

渔船IDxy速度方向timetype
11026283649.6562043675284013.963699763312.10921 09:00围网
  • 渔船ID:渔船的唯一识别,结果文件以此ID为标示

  • x: 渔船在平面坐标系的x轴坐标

  • y: 渔船在平面坐标系的y轴坐标

  • 速度:渔船当前时刻航速,单位节

  • 方向:渔船当前时刻航首向,单位度

  • time:数据上报时刻,单位月日 时:分

  • type:渔船label,作业类型

原始数据经过脱敏处理,渔船信息被隐去,坐标等信息精度和位置被转换偏移。选手可通过学习围网、刺网、拖网等专业知识辅助大赛数据处理。

1.3 评估指标

提交结果与实际渔船作业类型结果进行对比,以3种类别的各自F1值取平均做为评价指标,结果越大越好,具体计算公式如下:
其中P为某类别的准确率,R为某类别的召回率,评测程序f1函数为sklearn.metrics.f1_score,average='macro'。

二、Baseline 1

2.1 Baseline 概况
Baseline Auhtor阿水
Baseline AddressBaseline
Baseline Star38
Baseline Score0.62

阿水的Baseline是本赛题比较有代表性的方案,代码风格简介,对于初学者比较友好。同时 「数据->特征->算法」 的框架方便特征工程的快速迭代。

2.2 代码结构
2.2.1 Import U need
import os, sys, glob
import numpy as np
import pandas as pd

import time
import datetime

from joblib import Parallel, delayed
from sklearn.metrics import f1_score, log_loss, classification_report
from sklearn.model_selection import StratifiedKFold

import lightgbm as lgb

%pylab inline

2.2.2 特征工程
def read_feat(path, test_mode=False):
    df = pd.read_csv(path)
    df = df.iloc[::-1]
    
    if test_mode:
        df_feat = [df['渔船ID'].iloc[0], df['type'].iloc[0]]
        df = df.drop(['type'], axis=1)
    else:
        df_feat = [df['渔船ID'].iloc[0]]
        
    df['time'] = df['time'].apply(lambda x: datetime.datetime.strptime(x, "%m%d %H:%M:%S"))
    df_diff = df.diff(1).iloc[1:]
    df_diff['time_seconds'] = df_diff['time'].dt.total_seconds()
    df_diff['dis'] = np.sqrt(df_diff['x']**2 + df_diff['y']**2)
    
    df_feat.append(df['time'].dt.day.nunique())
    df_feat.append(df['time'].dt.hour.min())
    df_feat.append(df['time'].dt.hour.max())
    df_feat.append(df['time'].dt.hour.value_counts().index[0])

    # 此处省略 N 段代码
    
    return df_feat

由于本赛题每个ID都独立成一个csv文件,可以看到阿水把利用文件名传参的方式对每个ID进行独立的特征处理。

2.2.3 并行化特征获取
train_feat = Parallel(n_jobs=10)(delayed(read_feat)(path, True)
                                 for path in glob.glob('../input/hy_round1_train_20200102/*')[:])
train_feat = pd.DataFrame(train_feat)

test_feat = Parallel(n_jobs=10)(delayed(read_feat)(path, False)
                                 for path in glob.glob('../input/hy_round1_testA_20200102/*')[:])
test_feat = pd.DataFrame(test_feat)
test_feat = test_feat.sort_values(by=0)

train_feat[1] = train_feat[1].map({'围网':0,'刺网':1,'拖网':2})

这里利用Parallel进行了并行化处理,提升了计算效率。

2.2.4 LightGBM 10折
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import f1_score

n_fold = 10
skf = StratifiedKFold(n_splits = n_fold, shuffle = True)
eval_fun = f1_score

def run_oof(clf, X_train, y_train, X_test, kf):
    # 此处省略N行
    return preds_train, preds_test

params = {# 此处省略N行}

train_pred, test_pred = run_oof(lgb.LGBMClassifier(**params),
                                train_feat.iloc[:, 2:].values,
                                train_feat.iloc[:, 1].values,
                                test_feat.iloc[:, 1:].values,
                                skf)


小结

笔者在此开源的基础上,只修改了部分特征工程,线上可以有 「0.8913」 的分数,同时并行化也使得线下迭代验证效率得到了保障。

三、Baseline 2

3.1 Baseline 概况
Baseline Auhtor蔡君洋jioooo~
Baseline AddressBaseline
Baseline Star18
Baseline Score0.8729

相对于Baseline 1,该Baseline的亮点在于做了一些EDA工作,对于理解题目很有帮助。

3.2 数据探查
  • 对不同标签的的(x,y)位置可视化我们可以发现,这基本就是沿海的轮廓。

  • 同时,不同标签在坐标上的区分度还是较为明显的。

3.3 多模型对比

该Baseline对Xgboost,LightGBM,CatBoost模型做了融合,同时做了加权融合。

test_end_scorexgboostlightgbmcatboostweight_xgboostweight_lightgbmweight_catboost
00.9310420.9308660.9174110.8776370.50.2
10.9143470.9018700.8844440.8795130.60.3
20.9275330.9078100.9232350.8880090.20.5
30.9122300.8911840.8777020.8945670.10.2
40.9041970.8943210.8950690.8992060.20.7
50.9299590.9183310.8945360.9020570.70.2
60.9305830.9153320.9305830.9051710.01.0
70.9042700.9037380.8857910.8902810.40.2
80.9317060.9263090.9159930.9184550.40.3
90.9186090.9095110.9186090.8851220.01.0
100.9068750.8906280.8674250.8651500.70.0
110.8892170.8788880.8672520.8661260.30.3
120.9195690.9078330.8841780.8935730.50.0
130.9044010.8958700.9014800.8881290.00.9
140.9082330.8968100.8858060.8567570.40.5
150.9194840.9002110.8728830.9116640.20.0
160.9058470.8831220.8937120.8798780.20.2
170.9020630.8990600.8961160.8840670.20.4
180.9389630.9333090.9141830.8950510.70.0
190.9140480.9130540.8825810.8763540.40.2

四、Baseline 3

4.1 Baseline 概况
Baseline Auhtorwbbhcb
Baseline AddressBaseline
Baseline Star21
Baseline Score0.5

相对于Baseline 1和2,该Baseline的亮点在于提供了一个NN版的思路,虽然该思路的做法,用图片的形式进行分类,损失了很多特征信息,但是依旧不妨碍作为一个Baseline思路的存在。

4.2 部分代码概况
def train_epoch(model, optimizer, criterion, train_dataloader, epoch, lr, best_f1, batch_size):
    model.train()
    f1_meter, loss_meter, it_count = 0, 0, 0
    tq = tqdm.tqdm(total=len(train_dataloader)*batch_size)
    tq.set_description('folds: %d, epoch %d, lr %.4f, best_f:%.4f' % (fold_+1, epoch, lr, best_f1))
    for i, (inputs, target) in enumerate(train_dataloader):
        inputs = inputs.to(device)
        target = target.to(device)
        # zero the parameter gradients
        optimizer.zero_grad()
        # forward
        output = model(inputs)
        output = F.softmax(output, dim=1)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
        loss_meter += loss.item()
        it_count += 1
        f1 = calc_f1(target, output)
        f1_meter += f1
        tq.update(batch_size)
        tq.set_postfix(loss="%.4f   f1:%.3f" % (loss.item(), f1))
    tq.close()
    return loss_meter / it_count, f1_meter / it_count
作者简介

DOTA
数据科学从业者
国内某知名互联网企业算法工程师
曾获:DiggSci亚军,JDATA季军,国内竞赛N次Top10

历史精品文章推荐

1、知否?知否?一文看懂深度文本分类之DPCNN原理与代码

2、CCL“中国法研杯”相似案例匹配评测竞赛 - TOP队伍攻略分享

3、推荐|机器学习入门方法和资料合集

个人微信:加时请注明 (昵称+公司/学校+方向)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值