2020DCIC智慧海洋建设算法赛学习01-赛题北京及地理数据分析常用工具


本系列的博客旨在学习2020DCIC智能算法赛-智慧海洋建设的优秀方案,对地理数据分析问题积累一些思路和经验。
作为这一系列博客的开篇,这篇博客主要内容包括对赛题的解析和对项目中会用到的一些常用的地理数据分析工具的简要介绍。

1 赛题背景

1.1 问题陈述

智慧海洋建设比赛是一个时序数据的分类问题,任务就是要通过给出的渔船轨迹的北斗数据判断渔船的生产作业行为。渔船的生产作业行为包括三类:拖网作业、围网作业和流刺网作业。

(1) 拖网作业

拖网作业是依靠渔船的动力拖动渔具将所经之处的鱼虾捕捞入网的一种捕捞方式,它的作业方式如下图所示:
在这里插入图片描述

(2) 围网作业

围网作业时渔船沿圆形的轨迹拖动网具在垂直方向上张开一个近似圆形的围壁,将围壁中的鱼群捕捞入网,它的作业方式如下图所示:在这里插入图片描述

(3) 流刺网作业

流刺网作业时渔船拖动长方形网片直线拉开一张大网,等待鱼群被网缠住,它的作业方式如下图所示:
在这里插入图片描述
根据各种生产作业方式的特点可以发现,不同作业方式的渔船轨迹是有区别的:拖网作业将所到之处的鱼群纳入网中,它的轨迹通常是较为随意没有特定规律的;围网作业渔船要拉成一张围壁,它的轨迹通常是一个闭合的曲线;流刺网作业要张开一张网面,它的轨迹通常是直线。因此,赛题的核心任务就是分析和处理渔船的位置时序。
比赛给出的训练数据格式如下图所示:
在这里插入图片描述

  • x:渔船在平面坐标系中的x轴坐标
  • y:渔船在平面坐标系中的y轴坐标
  • 速度:渔船当前的航行速度,单位节
  • 方向:渔船当前的船首方向,单位度
  • time:当前数据的上报时刻
  • type:渔船的生产作业类型

1.2 评价指标

评价指标如下:
S c o r e = F 1 拖 网 + F 1 围 网 + F 1 流 刺 网 3 Score = \frac{F1_{拖网}+F1_{围网}+F1_{流刺网}}{3} Score=3F1+F1+F1
也就是说,评价指标是三种类型的F1得分的均值,其中F1得分计算公式如下:
F 1 = 2 × P r e c i s i o n × R e c a l l P r e c i s i o n + R e c a l l F1 = \frac{2\times{Precision}\times{Recall}}{Precision+Recall} F1=Precision+Recall2×Precision×Recall
其中Precision是准确率,Recall是召回率。

2 地理数据分析常用工具

2.1 常用库

在分析地理数据的时候,常用的库如下:

  • shapely:shapely库支持Point、LineString、LineRings、Polygon等几何对象以及它们之间的空间操作,使用方法可以参考它的官方文档
  • geopandas:geopandas库对pandas库进行扩展,在融合pandas数据类型的基础上提供了操作地理空间数据的高级接口,允许对几何类型进行空间操作,同时它依赖于matplotlib进行绘图,可以很方便地对地理数据进行可视化分析,可参考官方文档
    在这里插入图片描述
  • Folium:Folium库可以生成动态交互的地图,能够在世界地图的基础上生成热力图、路径图等,并且可以随意拖动和缩放地图,方便进行地理数据的可视化,使用方法可参考官方文档
    在这里插入图片描述
  • Kepler.gl:Kepler.gl库也是一个图形化的可视化工具,它相较于Folium使用更加遍历,可以直接读取csv、json、geojson格式的数据,生成数据的可视化图像,这个库特点在于可以无需编程,直接在界面上调节绘制出的可视化图像。
    在这里插入图片描述

2.2 douglas-peucker算法

轨迹数据量通常是非常庞大的,在Kepler.gl中进行分析时处理速度慢且容易出现卡顿,可以采用douglas-peucker算法进行数据压缩。
douglas-peucker算法实际是一种数据采样算法,思路并不复杂。假设有一条曲线AB,设定一个阈值T,采用douglas-peucker算法对曲线AB进行采样的步骤如下:

  1. 连接曲线两端点A和B得到直线AB作为曲线AB的弦。
  2. 计算曲线上各点到弦AB的距离,得到距离最大的点C,其到弦AB的距离为d。
  3. 若d不超过阈值T,则可以认为弦AB就是曲线AB的近似,处理完毕。
  4. 若d大于阈值T,则以C为分割点,将曲线AB分为曲线AC和曲线CB,分别对这两段曲线执行步骤1~3。
  5. 将所有分割点连接起来,得到的折线就是对曲线AB的近似。
    在这里插入图片描述
    douglas-peucker算法可以直接通过shapely库的simplify方法实现,例如对一条折线进行压缩:
# 导入库
from shapely import geometry as geo

# 由坐标点创建一个折线类型
line1 = geo.LineString([(0, 0), (1, -0.2), (2, 0.3), (3, -0.5), (5, 0.2), (7, 0)])
# 对折线line1进行数据压缩,其中simplify方法的第一个参数0.4就是设定的阈值
line1_simplify = line1.simplify(0.4, preserve_topology=False)  # preserve_topology设为True时采用更慢的算法,设为False时采用更快的算法

# 绘制压缩后的折线
print(line1)
print(line1_simplify)
line1_simplify

输出结果如下图所示:
在这里插入图片描述

2.3 异常值处理

由于海上的环境复杂,经常出现信号丢失或设备故障导致上报坐标错误、上报数据丢失、有些设备疯狂上报等问题,因此数据中会存在大量异常值,通常采用3-sigma算法来判断异常值,注意使用该算法的数据需服从正态分布。
在这里插入图片描述
从上图中可以看到,对于一个正态分布的数据,99.73%的数据都集中在 [ μ − 3 σ , μ + 3 σ ] [\mu-3\sigma, \mu+3\sigma] [μ3σ,μ+3σ]这一区间内,不在这一区间的可能性不超过0.3%,因此不在这一区间的数据即看作异常值。
实现代码如下:

# n=3时即为3-sigma算法
def sigma_data(data_y, n):
    ymean = np.mean(data_y)  # 数据的均值
    ystd = np.std(data_y)  # 数据的标准差
    threshold1 = ymean - n * ystd  # 区间左端点mu-3*sigma
    threshold2 = ymean + n * ystd  # 区间右端点mu+3*sigma
    judge = []
    for data in data_y:
    	# 小于左端点或大于右端点的数据判断为异常值
        if (data < threshold1) | (data > threshold2):
            judge.append(True)
        else:
            judge.append(False)
    return judge

2.4 GeoHash算法

GeoHash算法用于对地理位置进行编码,例如对经纬度坐标(116.29513,40.04920)进行编码,GeoHash算法的步骤可分为三步:

(1) 将坐标转换为二进制

分别根据经纬度获得坐标的二进制表示。
经度的取值范围是[-180, 180],将其而分为[-180, 0]和[0, 180],坐标在右区间,记为1。再将右区间二分,将坐标所在的区间不断二分,直到达到所设定的精度。此时得到经度的二进制表示11010 01010 11001。
同理得到纬度的二进制表示10111 00011 11010。

(2) 将经纬度的二进制表示合并

二进制的偶数位放经度,奇数位放纬度,得到合并的二进制表示11100 11101 00100 01101 11110 00110。

(3) 根据Base32表进行编码

将二进制每五位转换为十进制表示,得到28 29 4 13 30 6,根据如下的Base32编码表将十进制数转换为对应的base32码。
在这里插入图片描述
于是最终得到的编码为wy4ey6。
GeoHash算法的实现代码如下:

def geohash_encode(latitude, longitude, precision=12):
	# 纬度和经度的取值区间
    lat_interval, lon_interval = (-90.0, 90.0), (-180.0, 180.0)
    # base32码
    base32 = '0123456789bcdefghjkmnpqrstuvwxyz'
    geohash = []
    bits = [16, 8, 4, 2, 1]
    # 当前二进制位
    bit = 0
    # 累计坐标二进制表示
    ch = 0
    # 判断奇偶位
    even = True
    while len(geohash) < precision:
    	# 若是偶数位,则记录经度的二进制表示
        if even:
        	# 计算区间二分的中点
            mid = (lon_interval[0] + lon_interval[1]) / 2
            # 若在右侧区间,则记录为1,并重新设置经度区间
            if longitude > mid:
                ch |= bits[bit]
                lon_interval = (mid, lon_interval[1])
            else:
                lon_interval = (lon_interval[0], mid)
        # 若是奇数位,则记录纬度的二进制表示
        else:
        	# 计算区间二分的中点
            mid = (lat_interval[0] + lat_interval[1]) / 2
            # 若在右侧区间,则记录为1,并重新设置纬度区间
            if latitude > mid:
                ch |= bits[bit]
                lat_interval = (mid, lat_interval[1])
            else:
                lat_interval = (lat_interval[0], mid)
        # 翻转奇偶位判断标志
        even = not even
        if bit < 4:
            bit += 1
        # 若达到五位,则将其转换为base32码
        else:
            geohash += base32[ch]
            bit = 0
            ch = 0
    return ''.join(geohash)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值