当poi遇上embedding

12 篇文章 3 订阅
5 篇文章 3 订阅

最近看到一篇关于poi的论文,把poi各个类别通过邻接关系利用Word-embedding训练成了词向量,这样原本属于不同大类下的子类但是功能很相近的类别就在词向量空间里显得比较近,更符合实际情况。相比于之前的分开看各种poi类别比例,这样可以更好地表达出城市内的poi配置情况。

论文提要

Liu K, Yin L, Lu F, et al. Visualizing and exploring POI configurations of urban regions on POI-type semantic space[J]. Cities, 2020, 99: 102610.

主要技术路线如下:

图片来自论文

  • 选择深圳市地铁站700m范围内poi作为研究数据

图片来自论文

  • 参考Skip-gram模型(Word-embedding)的一种,把每个poi类别当做输入(one-hot编码处理),并给定一个阈值范围(500m),统计范围内的所有poi比例,作为输出

图片来自论文

  • 根据各类别的词向量进行分析

图片来自论文

他们还做了一个下面这样的交互页面,http://hpcc.siat.ac.cn/liuk/POI_configuration_en/index.html

图片来自论文


简单复现

ok,介绍就到这里,我们拿上海的poi数据简单复现一下

  • step1 筛选上海地铁站700m内poi数据
    这里是通过geopandas对每个地铁站建立缓冲区,然后利用sjoin与各个poi点做相交,判断是否在缓冲区内,这里注意做缓冲区需要先把地理坐标系这种转换为平面坐标系,做完缓冲区我们再换回去
#读取poi数据
data=pd.read_csv(r"E:\data\上海市_201812_WGS84_poi_type.csv")
data['geometry']=data.apply(lambda x: geometry.Point(x.ln,x.lat),axis=1)
data=geopandas.GeoDataFrame(data)
data.crs = pyproj.CRS.from_user_input('EPSG:4326')
#读取上海地铁站数据
urban=pd.read_csv("E:/data/shanghai_urban.csv")
urban['geometry']=urban.apply(lambda x: geometry.Point(x.lon,x.lat),axis=1)
urban=geopandas.GeoDataFrame(urban)
urban.crs = pyproj.CRS.from_user_input('EPSG:4326')
#设置缓冲区范围
distance=700
urban=urban.to_crs(crs="EPSG:2385")
urban['geometry']=urban.buffer(distance)
urban.set_geometry('geometry',inplace=True)
#设置完缓冲区后再换回来
urban=urban.to_crs(crs="EPSG:4326")
#判断是否与地铁接驳范围相交
result=geopandas.sjoin(data,urban,how="left", op='intersects')
result.to_csv('result.csv')
result.set_geometry('geometry',inplace=True)
##保存接驳距离内poi数据
urban_in=result[pd.notna(result['name_right'])]
urban_in.to_csv(r'E:\data\shanghai_poi_within_urban.csv')

这里统计下来,上海poi在轨道站700m范围内的占61.85%

  • step2 筛选每个poi点周围500m内的poi数据,统计比例

此时数据里有141类poi了,这里我们应该对每一个poi点都做500m的缓冲区,找到落在该缓冲区内的141个子类的比例

这一步的话相当于是做99万+的缓冲区实在搞不动,要么多做几次很费时间,要么做一次又没内存,反正只是为了试验一下,就把每一类抽了1%,最后得到9962条数据

data=pd.read_csv(r"E:\data\shanghai_poi_within_urban.csv")
type_list=data['type_id'].unique().tolist()
def sample_data(type_id):
    con=data['type_id']==type_id
    tempdata=data.loc[con,:].copy()
    outdata=tempdata.sample(frac=0.01,random_state=1)
    return outdata
result_list=[]
for i in range(0,len(type_list)):
    result_list.append(sample_data(type_list[i]))
result=pd.concat(result_list,axis=0)
result.to_csv(r'shanghai_poi_within_urban_sample.csv')

接着对经过抽样的数据中每一个poi点都做500m的缓冲区,这里做缓冲区同step 1,不再赘述

得到下图结果

结果
然后统计不同类别的数目

table=pd.pivot_table(data=data,index=['id'],values=['index_right'],columns=['type_id_right'],aggfunc='count')
table=table.reset_index()
table=table.fillna(value=0)

转换成比例

data=pd.read_excel(r'C:\users\fff507\Desktop\data_poi_processed.xlsx')
data_value=data.iloc[:,1:].values
df1=pd.DataFrame(data_value)
df2=df1.sum(axis=1)# 按行相加
new_data=df1.div(df2, axis='rows')
  • step3 利用skip-gram训练,得到各类别对应的词向量

skip-gram原理

把中心词的onehot编码当做输入,上下文里的词出现的概率做输出,以此来进行训练,其实真正想要的是中间的隐藏层权重,也就是我们想要的对应于每个词的词向量。

我们这个背景里,中心词类似于每一个poi,上下文类似于缓冲区内的poi
基本原理其实也很简单,核心就是两个矩阵,看一下下面我画的图,就是W1,W2的问题,他们也是我们最终想要的

小周亲手画的

小周亲手画的

那么输入就是某个poi的one-hot编码,输出就是对应于141类的概率
但其实我们想要的是中间隐藏层的权重,W1,W2

我直接按照上图原理搞了个最简单的

def weight_variable(shape,name_w):
    initial = tf.truncated_normal(shape, stddev=0.1,name=name_w)
    return tf.Variable(initial)


X = tf.placeholder(tf.float32, [None, input_size],name='x')
W1 = weight_variable([input_size,embedding_size],name_w='W1')
v_c= tf.matmul(X, W1)
W2= weight_variable([embedding_size,input_size],name_w='W2')
M=tf.matmul(v_c, W2)
Y = tf.placeholder(tf.float32, [None,output_size],name='y')
loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=M, labels=Y))
train_op = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)
correct_prediction = tf.equal(tf.argmax(M, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
saver = tf.train.Saver(tf.global_variables())

最后测试集准确率在75.78%,141类也不算很差吧

训练结果

获取W1矩阵,也即词向量矩阵(141*50)

这个我看了有人说W1和W2都可以本质是一样的,也有人说应该取W1,官方取得是W1,我们这里也取W1好了

from tensorflow.python import pywrap_tensorflow
#首先,使用tensorflow自带的python打包库读取模型
model_reader = pywrap_tensorflow.NewCheckpointReader(r"model_emb/model.ckpt")
#然后,使reader变换成类似于dict形式的数据
var_dict = model_reader.get_variable_to_shape_map()
W1=model_reader.get_tensor('W1')#141*50
  • step4 降维后做一些可视化分析
# 降维到二维
pca = PCA(n_components=2)
pca.fit(W)
# 输出特征值
print(pca.explained_variance_)
#输出特征向量
print(pca.components_)
# 降维后的数据
W_new = pca.transform(W)
result=pd.DataFrame(W_new)
result.to_excel('poi_2d_wight.xlsx',index=False)

poi2维分布

由于内存限制本文只是实验性的拿差不多1w(1%)试验,难免有偏差结果看起来有些应该在一起的没有在一起(比如公交站和地铁站),不过看这个论文里的结果挺好的

ok,我们挑几个地铁站来看看poi配置区别
那就挑黄渡理工,同济,交大,复旦吧

周边poi配置

周边poi配置

下面这个当图例

我是图例

我是图例

黄渡理工独树一帜,而同济和交大地铁站周边分布最为相似,都有较多的生活服务,科教文化,培训结构,复旦大学地铁站是18号线在建,所以相对偏少,但是在事务所那里复旦大学地铁站周围高于其他。
在这里插入图片描述

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fff2zrx

谢谢老板

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值