image frame

To the MOUNTAIN

Learn & Life

【python+geopy包】地理信息检索

1. 注册百度AK

百度地图AK.png

2.开始编码

from geopy.geocoders import Nominatim,BaiduV3

geolocator = Nominatim(user_agent="myapp")#基于openStreetMap
location = geolocator.geocode(query="南京站")
print(location.raw)
print((location.longitude,location.latitude))#WGS84坐标系
print(location.address)

geolocator = BaiduV3(api_key='输入你申请的ak')#基于百度API构造实例
location = geolocator.geocode(query="南京站")#检索字符串
print(location.raw)#返回原始信息
print((location.longitude,location.latitude))#输出百度坐标系下经纬度坐标
print(location.address)
OpenStreetMap结果:
{'place_id': 304447935, 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright', 'osm_type': 'node', 'osm_id': 8042210546, 'boundingbox': ['32.0912644', '32.0913644', '118.7913084', '118.7914084'], 'lat': '32.0913144', 'lon': '118.7913584', 'display_name': '南京站, 南京站换乘通道, 鼓楼区, 南京市, 盱眙县, 江苏省, 210037, China 中国', 'class': 'railway', 'type': 'stop', 'importance': 0.11100000000000002}
(118.7913584,32.0913144)
南京站, 南京站换乘通道, 鼓楼区, 南京市, 盱眙县, 江苏省, 210037, China 中国

百度地图API结果:
{'location': {'lng': 118.80371375406085, 'lat': 32.093502120303725}, 'precise': 0, 'confidence': 50, 'comprehension': 0, 'level': '火车站'}
(118.80371375406085,32.093502120303725)
火车站

计算距离

注意,geopy.distance下的geodestic默认测算的是WGS-84坐标系下的大地距离。

刚刚调用百度地图API进行的地理编码检索得到的是百度坐标系下的经纬度,需提前进行转换。

这里还是直接用OpenStreetMap下的WGS-84坐标系下的经纬度作为示例。

from geopy.geocoders import Nominatim#经纬度检索
from geopy.distance import geodesic#计算距离

geolocator = Nominatim(user_agent="myapp")
location1 = geolocator.geocode(query="南京站")
location2 = geolocator.geocode(query="南京禄口国际机场")
print((location1.longitude,location1.latitude))
print((location2.longitude, location2.latitude))
print('两地距离%s公里'%geodesic((location1.latitude,location1.longitude), (location2.latitude,location2.longitude)).km)#可以设置单位为公里、米、英里等
输出结果:
(118.7913584,32.0913144)
(118.87176715003275,31.7324679)
两地距离40.51108155886417公里

基于多元LSTM模型的短时交通流量预测

正好这学期选修了一门交通流理论的课程,这里介绍一下我最后的课程论文,如何基于上一篇提到的在PeMS数据库下载到的数据,应用LSTM模型进行短时交通流量预测。

1. 数据准备

2019年9月1日至9月28日四周的交通流量数据,数据粒度是5分钟一统计,属性包含流率(veh/ 5 minutes),速度(mph),占有率(%),重车比例(%)。

数据展示.PNG

2. 数据描述性统计

(1) 绘制流率、速度、密度三参数基本图

flow&occ.png

speed&occ.png

(2) 概率密度分布

绘制流率、速度的概率密度分布图和累积概率密度分布图。

流量的概率密度分布.png

速度的概率密度分布.png

(3) 时间序列变化

观察流量、重车分布、速度、占有率的时序变化。 以9月1日一天的数据为例:

交通流一天.png

速度占有率一天.png

所有四周的流量时间序列变化:

时间序列流量.png

3. LSTM模型构建

以前三周数据训练,最后一周数据预测。时间步设为12,即前一个小时预测下一个5分钟。 话不多说,直接上代码。

import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from keras.preprocessing.sequence import TimeseriesGenerator
from keras.models import Sequential
from keras.layers import LSTM, Dense, Activation
from sklearn.metrics import mean_absolute_error as mae
from sklearn.metrics import mean_squared_error as mse
from sklearn.metrics import r2_score
import matplotlib.pyplot as plt
import numpy as np

# 将序列转换为监督学习问题
def series_to_supervised(datasetX,datasetY,lag):
    print('x的属性数量',datasetX.shape[1])
    data_gen = TimeseriesGenerator(datasetX,datasetY, length=lag,
                                   batch_size=1)  # length是滑lag,sampling_rate是timesteps,batch_size是y的维度
    X_out, Y_out = data_gen[0]
    for j in range(0, len(data_gen)):
        batch = data_gen[j]
        x, y = batch
        X_out = np.concatenate((X_out, x))
        Y_out = np.concatenate((Y_out, y))
    X_out = np.delete(X_out, 0, axis=0)
    Y_out = np.delete(Y_out, 0)
    print('X shape',X_out.shape)
    print('Y shape', Y_out.shape)
    return X_out,Y_out

# 加载数据集
path='.\'
olddf=pd.read_excel(path+'PeMS数据.xlsx',sheet_name='Sheet1')
df=olddf.copy(deep=False)
df['Flow (Veh/5 Minutes)']=df['Flow (Veh/5 Minutes)'].map(lambda x:3*x)#转换为veh/h/ln

#生成lstmX,Y
input_attributes=['Flow (Veh/5 Minutes)','Occupancy (%)','Speed (mph)','Truck Prop (%)']
datasetX=df[input_attributes].values
datasetY=df['Flow (Veh/5 Minutes)']
scalerx = MinMaxScaler(feature_range=(0, 1))
scalery = MinMaxScaler(feature_range=(0, 1))
X_scaled = scalerx.fit_transform(datasetX)
Y_scaled= scalery.fit_transform(np.array(datasetY).reshape(-1, 1))
X,Y=series_to_supervised(X_scaled,Y_scaled,12)#12个数据点即1小时

#划分训练集与测试集
X_train,X_test,Y_train,Y_test= train_test_split(X,Y,test_size=0.25,random_state=0)
print('X_train shape',X_train.shape)
print('X_test shape',X_test.shape)
print('Y_train shape',Y_train.shape)
print('Y_test shape',Y_test.shape)


#构建模型
# input_dim是输入的train_x的最后一个维度,train_x的维度为(n_samples, time_steps, input_dim)
model = Sequential()
model.add(LSTM(30, input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(Dense(1))
model.add(Activation('tanh'))
model.compile(loss='mse', optimizer='adam')

# 拟合神经网络模型
history = model.fit(X_train, Y_train, epochs=50, batch_size=64, validation_data=(X_train, Y_train), verbose=2,
                    shuffle=False)

# 绘制训练loss数据
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
ax1.plot(history.history['loss'], label='train')
ax1.plot(history.history['val_loss'], label='test')
ax1.set_ylabel('Loss')
ax1.set_xlabel('Epochs')
plt.legend()
plt.show()

# 做出预测
yhat = model.predict(X_test)
invY_predict=scalery.inverse_transform(np.array(yhat).reshape(-1,1))
invY_test=scalery.inverse_transform(np.array(Y_test).reshape(-1,1))

print('lstm结果')
print('r_square', r2_score(invY_test,invY_predict))
print('mae', mae(invY_test,invY_predict))
print('rmse', np.sqrt(mse(invY_test,invY_predict)))

fig2 = plt.figure(figsize=(10,7) , dpi=80)
ax2 = fig2.add_subplot(111)
ax2.plot(invY_test,color='blue', linestyle='-',label='Ground Truth')
ax2.plot(invY_predict,color='red', linestyle='--',label='LSTM Prediciton')
ax2.set_ylabel('Flow (veh/h/ln)')
ax2.set_xlabel('Date')
xlabel=[]
for i in range(22,30):
    xlabel.append('9/%d'%(i))
ax2.set_xticks(range(0,2304,288))
ax2.set_xticklabels(xlabel,rotation=90)
plt.legend()
plt.show()

#绘制9/28一天的图
fig3 = plt.figure(figsize=(10,7) , dpi=80)
ax3 = fig3.add_subplot(111)
ax3.plot(invY_test[-288:],color='green', linestyle='-',label='Ground Truth')
ax3.plot(invY_predict[-288:],color='purple', linestyle='--',label='LSTM Prediciton')
ax3.set_ylabel('Flow (veh/h/ln)')
ax3.set_xlabel('Time')
xlabel=[]
for i in range(0,25):
    xlabel.append('%d:00'%(i))
ax3.set_xticks(range(0,289,12))
ax3.set_xticklabels(xlabel,rotation=90)
plt.legend()
plt.show()

结果展示:

最后一周所有的预测:

全部预测.png 9月28日结果: 9.28预测.png 预测的效果还可以,毕竟只设置了单隐层。

下载PeMS交通流数据指南

今天给大家推荐一个开放的交通数据库,美国加州交通运输局的PeMS数据库,这里有着长达10年的高速公路检测器数据。包含流率、速度、占有率、重车比例、延误、车辆行驶里程、车辆行驶时间、交通事故等类型数据。很多学者都用这里的数据进行研究。 所以这里给大家介绍一下这个数据库下载数据的使用方式。

1. 要有可以科学上网的VPN

这个请先自行解决。

2. 登录PeMS网站并注册账号

官方网址:http://pems.dot.ca.gov/ 首页右侧有apply for an account的链接,注册完毕后回到首页右上角登陆已通过的注册账号。

PeMS首页.PNG

3. 明确要下载的数据类型:线:路段|点:检测器

登录进去后,可以看到上面有一栏“Overview, Facilities&Devices, Performance, Data Quality, Events”,这里细分又有很多数据,大家可以自行根据需要点进去查看。 这里我主要介绍下载集计的交通流量、速度、占有率等交通流宏观参数数据。

PeMS登陆后界面.PNG

如这张图所示,以下载某个检测器数据为例,我这里下载I5高速公路主线上编号#716895的检测器Aggregates集计数据。 然后就会跳转到这个检测器的数据,并且系统也提供了基础的数据图表供你直观观看。

检测器数据示例.PNG

4. 选择数据的属性和精度

Quantity, Second Quantity:要下载的数据类型,如流量、速度、占有率等。 Granularity: 数据精度,月、周、日、5分钟的颗粒度。 另外,可以选择数据的日期覆盖时段、节假日、车道等。

然后点击需要下载的数据格式,这里一般下载EXPORT to.XLS,比较便于后续数据分析。

好了,就是这么简单,下一篇我来介绍一下我如何用这里的数据进行交通流量的时间序列建模预测。

【Windows+Cygwin+Darknet+OpenCV】简易上手实现YOLOv3目标检测

YOLO(You only look once)是github上很火的一个目标检测算法。它的官网提供了很方便的用C语言编写的程序Darknet。 但是官网提供的很方便的编译方法是基于Linux和Mac系统的。我这次来讲讲我是如何在自己windows系统下配置Darknet模块的。 注:我这次是下了Cygwin来模拟Linux系统,因为不想下体积占据几个G的Visual Studio来进行编译,Cygwin安装包本身只有1.3M大小。 如果有Visual Studio,可以参照AlexeyAB版本进行配置。

官网图

基础配置流程

配置过程参照官网:https://pjreddie.com/darknet/yolo/

(1) 将github上的https://github.com/pjreddie/darknet 整个项目下载到本地电脑。 注:此处建议使用下载.zip压缩包的方式,不是直接用git clone到本地文件夹,不然可能后面会遇到couldn’t open file: data/coco.names的问题。 (2) 切换到darknet文件夹,使用make命令编译C语言源文件。 此时,Windows系统下在cmd命令行会报错无法使用make命令。因为make是linux系统下编译源文件使用的命令。官网也有注明这些命令只在Linux和Mac系统上测试过,未在windows系统下测试。 所以,下载Cygwin软件实现在windows平台模拟linux系统操作命令,而后可以使用make命令编译源码,生成darknet.exe可执行文件。安装配置Cygwin 参照这篇博客以及其下面的问答:https://blog.csdn.net/chunleixiahe/article/details/55666792

在Cygwin编译成功

(3) 下载别人已训练好的yolov3.weights模型权重文件,放于darknet根目录下。 官网链接(下载较慢):https://pjreddie.com/darknet/yolo/ 百度云链接:https://pan.baidu.com/s/1CVgvP4hQQvDNbKmXhmkxqw 提取码:jnhn (4) 使用命令./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg完成测试。因为没有配置OpenCV,图片结果不会直接显示的屏幕上,而是存于默认文件夹的根目录predictions.jpg。 但是此时默认的程序不会将置信度显示在图片上,只打印于命令行,图片会存于根目录下predictions.jpg

官方测试图片结果不含置信度

(5) 为实现将预测的置信度显示于检测结果图片上,更改默认darknet文件夹下的src/image.c文件draw_detections函数。 参照:https://blog.csdn.net/qq_34795071/article/details/86665620

int i,j;

for(i = 0; i < num; ++i){
    char labelstr[4096] = {0};
    int class = -1;
char possible[10];//存放检测的置信值
    for(j = 0; j < classes; ++j){
  sprintf(possible,"%.2f",dets[i].prob[j]);//置信值截取小数点后两位赋给possible
        if (dets[i].prob[j] > thresh){
            if (class < 0) {
                strcat(labelstr, names[j]);
        strcat(labelstr, possible);//标签中加入置信值
                class = j;
            } else {
                strcat(labelstr, ", ");
                strcat(labelstr, names[j]);
        strcat(labelstr, possible);//标签中加入置信值
            }
            printf("%s: %.0f%%\n", names[j], dets[i].prob[j]*100);
        }
    }

(6) 删除掉原编译好的darknet.exe, libdarknet.a, libdarknet.so,重新使用make编译源文件,再执行上述检测语句,即可存储含有置信度的图片。

dog_predictions

(7) 若想更改检测的默认置信度,在检测命令后添加 -thresh <数值>。 ./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg -thresh 0.4

至此已经完成了最基础的Darknet配置来实现YOLOv3算法。

OpenCV拓展实现实时目标检测

(1) 安装OpenCV,拓展可支持的图片类型,并且将结果自动弹窗显示: OpenCV(Windows版本的即可)安装完毕后,需要再次使用Cygwin下载Linux支持的OpenCV相应文件,并将darknet根目录下Makefile用文本打开,开头部分设为OPENCV=1,才可成功编译可支持OpenCVdarknet.exe。 编译完基于OpenCV的可执行程序后,不能如原来一样在命令行直接输入检测语句,不然会出现无法展示的报错,配置并启动Xterm才可以解决。

opencv配置后在命令行弹框报错

Cygwin输入export DISPLAY=:0.0startxwin &即可启动Xterm,然后输入相应命令,即可出现弹框,如下所示。

在Xterm成功显示至窗口屏幕.PNG

Xterm使用两则小贴士:(1)鼠标中键实现“粘贴”;(2)ctrl+右键可以改字号。 (2) 参照这篇博客【python+OpenCV+YOLOv3打开笔记本摄像头模型检测】的代码,使用python程序,通过OpenCV调用摄像头实现实时检测。 这篇文章调用的是电脑自带摄像头,我通过给安卓手机下载IP Webcam软件,实现调用手机摄像头的实时目标检测。 具体代码如下:

import numpy as np
import cv2
import os

def video_demo():
    # 加载已经训练好的模型路径,可以是绝对路径或者相对路径
    weightsPath = "../yolov3.weights"
    configPath = "../cfg/yolov3.cfg"
    labelsPath = "../data/coco.names"
    # 初始化一些参数
    LABELS = open(labelsPath).read().strip().split("\n")  # 物体类别
    COLORS = np.random.randint(0, 255, size=(len(LABELS), 3), dtype="uint8")  # 颜色
    boxes = []
    confidences = []
    classIDs = []
    net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)
    # 读入待检测的图像
    # 0是代表摄像头编号,只有一个的话默认为0

    url = 'http://192.168.0.103:8080/video'##手机ip cam地址
    # url='D:\darknet-master\\airplane.avi'#本地视频
    capture = cv2.VideoCapture(url)
    while (True):
        ref, image = capture.read()
        (H, W) = image.shape[:2]
        # 得到 YOLO需要的输出层
        ln = net.getLayerNames()
        ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
        # 从输入图像构造一个blob,然后通过加载的模型,给我们提供边界框和相关概率
        blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416), swapRB=True, crop=False)
        net.setInput(blob)
        layerOutputs = net.forward(ln)
        # 在每层输出上循环
        for output in layerOutputs:
            # 对每个检测进行循环
            for detection in output:
                scores = detection[5:]
                classID = np.argmax(scores)
                confidence = scores[classID]
                # 过滤掉那些置信度较小的检测结果
                if confidence > 0.5:
                    # 框后接框的宽度和高度
                    box = detection[0:4] * np.array([W, H, W, H])
                    (centerX, centerY, width, height) = box.astype("int")
                    # 边框的左上角
                    x = int(centerX - (width / 2))
                    y = int(centerY - (height / 2))
                    # 更新检测出来的框
                    boxes.append([x, y, int(width), int(height)])
                    confidences.append(float(confidence))
                    classIDs.append(classID)
        # 极大值抑制
        idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.2, 0.3)
        if len(idxs) > 0:
            for i in idxs.flatten():
                (x, y) = (boxes[i][0], boxes[i][1])
                (w, h) = (boxes[i][2], boxes[i][3])
                # 在原图上绘制边框和类别
                color = [int(c) for c in COLORS[classIDs[i]]]
                cv2.rectangle(image, (x, y), (x + w, y + h), color, 2)
                text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i])
                cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
        cv2.imshow("Video", image)
        # 等待1ms显示图像
        c = cv2.waitKey(1)
        if c & 0xFF == ord('q'):  # 键盘输入英文字母q键退出视频
            break

cv2.destroyAllWindows()  # 销毁所有窗口
video_demo()

下面放一下我实时检测的画面:

接入手机摄像头实时检测.jpg

电脑实时检测示意画面.jpg

配置Darknet走过的一些弯路

(1) 下载CUDA实现GPU运算: 需要自己的显卡比较好,同时配置CUDA、CUDNN均需匹配版本号正确,这两个软件体积也特别大。配置这个很麻烦,Darknet官网也说明了这个安装很麻烦,所以不是长久专门使用,不必配置了。 但是没有GPU真的处理视频很卡。。。 (2) 一开始的make编译Makefile失败,尝试使用windows系统下的Visual Studio中的nmake等方式失败,尝试用MinGW也失败,最终使用Cygwin模拟linux成功。 (3) 基于已有的程序,安装完OpenCV后在模拟Linux系统下的视频流的目标侦测目前还是遇到一些问题,无法正常按帧检测,并实时在屏幕上显示检测结果。花费了2天时间进行尝试,还是没有解决这个bug,暂时放弃。有解决的朋友可以告诉我一下。 报错: (darknet:3866):GLib-GObject-CRITICAL **: g_object_set: assertion 'G_IS_OBJECT (object)' failed

视频报错.png

所以才最后转投了python程序去调用OpenCV做视频检测,如果你只想做图片检测,按照我上面的做法没问题。 (4) 所以当我看到最后的别人的博客调用python程序,去查src的源码实现YOLOv3,不需要配置keras和tensorflow,其实以后自己也可以这样做。自己当初放弃AlexeyAB版本的python接口是因为它还是需要导入windows编译过后的dll模块,所以放弃。不过,有兴趣的朋友还是可以一试。

【自然语言处理】Wordcloud词云分析+LDA主题分类

最近在一门课上,老师分享了一篇关于应用自然语言处理(NLP)模型分析交通领域研究主题分类的论文,我觉得写得很好很有意思。所以,自己也进行一下尝试。 主要分为Wordcloud词云展示Latent Dirichlet Allocation(LDA)模型主题分类两部分。

参考文献:Sun, L., & Yin, Y. (2017). Discovering themes and trends in transportation research using topic modeling. Transportation Research Part C: Emerging Technologies, 77, 49-66. doi:10.1016/j.trc.2017.01.013

本次分析的是2017年至2020年发表的交通领域关于“Mobility-as-a-Service(MaaS)”的30篇论文的摘要部分。

文献展示

wordcloud词云展示

  1. 首先对文本进行预处理:

    • 去除标点符号,按空格拆分句子 mytext=re.sub(r'[.,()]','',mytext).split(' ') #正侧表达式去除标点

    • 用NLTK的wordnet模块进行词形还原

        from nltk.stem import WordNetLemmatizer
        wnl = WordNetLemmatizer()
        remytext = ''
        for i in range(len(mytext)):
            mytext[i]=wnl.lemmatize(mytext[i]) #词性还原
            remytext=remytext+' '+mytext[i]
        mytext=remytext
      
      <strong>注:wordnet包需要另外独自安装,不然会报如下错误:</strong>`Resource wordnet not found. Please use the NLTK Downloader to obtain the resource:`
      
      ![wordnet缺失报错](wordnet缺失报错.PNG)
      <strong>这里补充wordnet包安装方法:</strong>
      (1) 命令行cmd打开,输入python;
      (2) 继续输入<code>import nltk</code><code>nltk.download()</code>如下图所示:
      
      ![wordnet下载cmd](wordnet下载cmd.PNG)(3) 可能会报错远程主机强制关闭了一个连接。
        解决办法:(1)连VPN (2)利用别人已经下载到本地的wordnet包,具体参照这篇博客。<a href="https://blog.csdn.net/Charchunchiu/article/details/96436736?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task">Python NLTK WordNet的在线与手动安装方法</a>
      (4) 正常情况下,弹出如下窗口,选择<code>Corpora/wordnet</code>下载即可。
      ![wordnet下载界面](wordnet下载界面.PNG)
    • 设置停用词

      from wordcloud import STOPWORDS#导入原有的停用词包
      additional_stopwords=[]
      with open(stopwordsfile,'r',encoding='UTF-8') as f:
      for line in f:
            additional_stopwords.append(line.replace("\n",""))
      stop_words = additional_stopwords + list(STOPWORDS)#额外添加自己的停用词
  2. 应用wordcloud包

    from wordcloud import WordCloud
    wordcloud = WordCloud(stopwords=stop_words,background_color='white',collocations=True,colormap='viridis',width=2160,height=1080,max_words=50,prefer_horizontal=1).generate(mytext)
    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis("off")
    plt.show()

词云展示

LDA主题分类

这里使用sklearnLDA包。 基于之前的文本预处理,还需要转换为词向量的形式,才可放入LDA模型训练。 具体代码如下:

from sklearn.feature_extraction.text import CountVectorizer #词向量转换模块
from sklearn.decomposition import LatentDirichletAllocation as LDA
import matplotlib.pyplot as plt
import time
from matplotlib.pyplot import MultipleLocator

#Initialise the count vectorizer with the English stop words
count_vectorizer = CountVectorizer(stop_words=stop_words)#这里也可以设置停用词
# Fit and transform the processed titles
count_data = count_vectorizer.fit_transform(mytext)

def print_topics(model, count_vectorizer, n_top_words):
    words = count_vectorizer.get_feature_names()
    for topic_idx, topic in enumerate(model.components_):
        print("\nTopic #%d:" % topic_idx)
        print(" ".join([words[i]
                        for i in topic.argsort()[:-n_top_words - 1:-1]]))
n_topics = range(3,7,1)
perplexityLst = [1.0]*len(n_topics)

#训练LDA并打印训练时间
lda_models = []
for idx, n_topic in enumerate(n_topics):
    print(idx,n_topic)
    lda = LDA(n_components=n_topic, max_iter=2000,learning_method='batch',

#                                    perp_tol=0.1, #default

#                                    doc_topic_prior=1/n_topic, #default

#                                    topic_word_prior=1/n_topic, #default

                                    verbose=0)
    t0 = time.time()
    lda.fit(count_data)
    perplexityLst[idx] = lda.perplexity(count_data)
    lda_models.append(lda)
    print ("# of Topic: %d, " % n_topics[idx])
    print ("done in %0.3fs, N_iter %d, " % ((time.time() - t0), lda.n_iter_))
    print ("Perplexity Score %0.3f" % perplexityLst[idx])

#打印最佳模型
number_words=10
best_index = perplexityLst.index(min(perplexityLst))
best_n_topic = n_topics[best_index]
best_model = lda_models[best_index]
print ("Best # of Topic: ", best_n_topic)
print_topics(best_model, count_vectorizer, number_words)

#绘制不同主题数perplexity的不同
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
xaxis=[]
for i in range(0,len(n_topics)):
    xaxis.append(n_topics[i])
ax.plot(xaxis, perplexityLst)
x_major_locator=MultipleLocator(1)
ax.set_xlabel("number of topics")
ax.set_ylabel("Approximate Perplexity")
plt.grid(True)
plt.show()

最终我这里选择了分为3个主题。虽然2个的perplexity效果好一些,但我根据需要选择了3个。

perplexity指数

Topic #1: 城市系统角度 model city public business alliance actor efficiency factor system new Topic #2: 各出行模式运营商角度 user time market adoption road potential intermediary car operator public Topic #3: 用户出行模式选择角度 car public model mode bundle sharing new travel choice demand

好了,这次就到这里了。具体的参数设置还是参照官方文档。

使用高德开放平台API获取POI位置和路线信息

借助地图API接口,帮助我们快速获取大量的静态、动态数据是非常有效的。 这次我就来讲讲怎么利用高德开发平台API接口,获取一些设施位置和路径规划信息。

高德开放平台

高德开放平台可以让你自己开发的应用嵌入高德服务,使用高德在地理信息服务上的贡献。 因为这次我主要需要用到的是一些信息搜索,所以用的是开发支持->Web服务->Web服务API,其他需要移动应用开发的可以去查询开发支持下的Web端、Andriod平台、IOS平台、微信小程序等等。

web_API_intro.PNG

如平台的简介,它可以帮你实现搜索、路径规划、行驶距离测量等功能。

1. 准备工作

申请一个高德的适用于Web服务的key,之后在URL里需要填上自己的key。注意个人用户每日每个key的使用次数是有限额的,超限了查询信息返回会报错,但一个人可以申请好多个。

key.PNG

2. 根据需要填充URL关键字

我们这次用关键字搜索功能,来查询POI(point of interest)信息,以查询某一城市的机场、火车站的枢纽地理信息为例。 根据开发文档提供的URL示例:https://restapi.amap.com/v3/place/text?parameters 我们把parameters替换为搜索时限定的一些关键词,并且用&连接不同的条件,记得替换你自己申请的key。 比如:https://restapi.amap.com/v3/place/text?keywords=火车站&city=北京&citylimit=true&extensions=all&key=你申请的key&offset=20&page=1

keywords_search.PNG

返回的结果,也是参照开发文档,注意弄清层级结构,即可获取对应信息,默认返回json格式。

result_parameter.PNG

我这里会主要想要获取经纬度信息,在['pois']->['poi']->['location']下面。

3. 使用python批量访问获取结果

用python的requests库,获取访问结果,完整代码如下。这里用简单的GET方式填充URL的参数即可,以后自己爬其他的信息还有可能要用到POST方式,但以字典方式传送参数也是一样的。

import requests
import math
import json
import pandas as pd

def get_station(city,type):  # 抓取场站信息
    url1 = "https://restapi.amap.com/v3/place/text?keywords=%s&city=%s&citylimit=true&extensions=all&key=你自己申请的key&offset=20&page=%d"%(type,city,1)#查询机场和火车站的经纬度信息
    req = requests.get(url1)  # 请求高德地图Place API返回数据
    content = req.content
    data = json.loads(content)  # 将获取的信息封装为字典
    num=int(data['count'])  # 提取场站总数
    result = data['pois']  # 提取字典中的有效信息
    print(num)

    infoDf = pd.DataFrame(columns=['名称', '经度', '纬度', '城市', '类型', '别名'])
    if num==0:#返回有数据的情况下
        print('%s无%s'%(city,type))

    #第一次的信息别浪费了
    for i in range(len(result)):
        print(i)
        str_temp = result[i]  # 保存总数到链表第一个元素
        if len(str_temp['alias']) == 0:
            alias = ''
        else:
            alias = str_temp['alias']

        print(str_temp['name'],str_temp['location'].split(',')[0],str_temp['location'].split(',')[1],str_temp['cityname'],alias)
        singleinfo={'名称':str_temp['name'],'经度':str_temp['location'].split(',')[0],'纬度':str_temp['location'].split(',')[1],'城市':str_temp['cityname'],'类型':type,'别名':alias}
        singleinfoDf=pd.DataFrame(singleinfo,columns=['名称', '经度', '纬度', '城市','类型','别名'],index = [0])
        infoDf = pd.concat([infoDf, singleinfoDf], axis=0, ignore_index=True)

    totalpage=math.ceil(num/20)#每一页显示20条数据,算好页数
    if totalpage >1 :
        for n in range(2,totalpage+1):#从第2页起
            url2 = "https://restapi.amap.com/v3/place/text?keywords=%s&city=%s&citylimit=true&extensions=all&key=e3bc4d79724c51578f54e141d4085394&offset=20&page=%d"%(type,city,n)#查询机场和火车站的经纬度信息
            req = requests.get(url2)  # 请求高德地图Place API返回数据
            content = req.content
            data = json.loads(content)  # 将获取的信息封装为字典
            result = data['pois']  # 提取字典中的有效信息
            for i in range(len(result)):
                print(i)
                str_temp = result[i]  # 保存总数到链表第一个元素
                if len(str_temp['alias'])==0:
                    alias=''
                else:
                    alias=str_temp['alias']
                singleinfo = {'名称': str_temp['name'], '经度': str_temp['location'].split(',')[0],
                              '纬度': str_temp['location'].split(',')[1], '城市': str_temp['cityname'],'类型':type, '别名': alias}
                singleinfoDf = pd.DataFrame(singleinfo,columns=['名称', '经度', '纬度', '城市','类型','别名'],index = [0])
                infoDf = pd.concat([infoDf,singleinfoDf],axis=0,ignore_index=True)

    return infoDf

def run():  # 开始抓取文件
    citylist=['石家庄','唐山','邯郸','保定','沧州','邢台','廊坊','承德','张家口','衡水','秦皇岛']#,'张家口','衡水','秦皇岛'
    typelist=['机场','火车站']
    whole_info = pd.DataFrame(columns=['名称', '经度', '纬度', '城市','类型','别名'])
    for cityname in citylist:
        for type in typelist:
            info = get_station(cityname,type)
            whole_info=  pd.concat([whole_info,info],axis=0,ignore_index=True)

    whole_info.to_csv('/京津冀机场火车站信息.csv',index=False,encoding='utf_8_sig')

if __name__ == '__main__':
    run()

类似地,大家可以参照以上代码,去查询一下餐厅、公交站等其他设施的信息。

*获取路径规划信息

刚才是介绍如何用关键字搜索功能,进行一些POI点的信息查询。现在做一些稍微复杂一点点的更深入的查询。 查询两个点之间的不同交通方式的路径规划信息,比如驾车路线、耗时、距离,公交的路线、耗时、花费等。 此时查询路径规划的对应开发文档。

route_planning.PNG

总结

  • 高德开发平台API会在查询一些信息时,起到很大帮助(百度开放平台API也是有相似的功能)。重点要去研读一下他们提供的开发文档,并且知道URL的组成,这样你就可以个性化的获取你想要的信息了。
  • 更多的内容,还是需要自己去不断发掘。

下载Bing搜索界面每日高清美图方法

Bing搜索的每日一图真的很好看,该如何下载呢?

  • 进入Bing搜索主页

    Bing首页.PNG

  • F12打开控制台。 在Elements下的head中找到图片链接地址。

    head链接.PNG

  • 复制粘贴到浏览器打开,右键图片另存为即可下载1920*1080分辨率无水印的图。 如果想下载更高清的UHD大图,将链接两处1920*1080的部分改为UHD即可。

  • 如果想下载前几天的图。 点Network,按Ctrl+R刷新页面,再点首页右下角的向左的箭头,前面图片的链接就会显示出来。 同理复制链接粘贴打开下载。

    前面链接.PNG

  • 最后还是要注意,图片有版权,不能商业使用。

配置Hexo的历程和一些bug解决方案

这篇主要来讲讲我怎么入手搭建自己的Hexo博客。我主要是按照这篇教程Hexo+Github博客搭建完全教程来做的,感谢洪卫 ,他已经写的非常详细了。 请大家按照这个教程先做下去!有遇到其他问题可以来看看我的回答,也许能帮到你哦。 我主要会补充一些这篇文章中没有提到的问题和解决方案

1. 安装hexo报错bash: hexo: command not found

在验证npmnode安装正确的情况下,输入npm install -g hexo-cli这条语句后,会经过漫长等待并出现很多error,再输入hexo -v报错bash: hexo: command not found说没有安装成功。这是国内镜像源的问题,使用淘宝镜像安装。 先输入npm config set registry "https://registry.npm.taobao.org",再输入npm install hexo-cli g。就会加快安装并且成功啦。

2. hexo init 超级慢

使用淘宝镜像初始化,在hexo init MyBlog之前,先输入npm --registry https://registry.npm.taobao.org info underscore,然后再输入hexo init MyBlog,接着就可以照着洪卫的博客继续做下去啦。

3. ssh-key 配置

当输入完ssh-keygen -t rsa -C "youremail"之后,系统会让你输入一个文件夹路径来保存id_rsa.pubid_rsa文件,建议你输入你的博客的完整根目录。 比如我的就是D:\software\web storm project\EvaBlog。 在github上传公钥的时候,就可以找到这个文件id_rsa.pub将内容复制过去。 也许你会收到报错Permission denied (publickey),很大概率是因为网速,你过一会儿再试一遍ssh -T git@gitee.com,就能看到对你say Hi和告知successfully了!

4. 免去每次提交时输入Github用户名和密码的方法

更改_config.yml文件最后deploy属性:

deploy:
  type: git
  repository: git@github.com:你的用户名/你的用户名.github.io.git
  branch: master

5. 用markdown语法![](/img.png)本地图片显示不出来

更新

hexo5之后参考这个方法进行配置hexo博客如何插入图片,仍然使用![](img.png)方法。


旧解决方案

参考链接:

hexo官方资源文件夹设置

hexo引用本地图片无法显示

这是hexo的问题。首先我们需要安装一个图片路径转换的插件,这个插件名字是hexo-asset-image

  • 安装:npm install https://github.com/CodeFalling/hexo-asset-image --save
  • 更改根目录下的_config.yml文件,修改post_asset_folder: true
  • 然后参照这篇博文更改/node_modules/hexo-asset-image/index.js下的配置。
'use strict';
var cheerio = require('cheerio');

// http://stackoverflow.com/questions/14480345/how-to-get-the-nth-occurrence-in-a-string
function getPosition(str, m, i) {
  return str.split(m, i).join(m).length;
}

var version = String(hexo.version).split('.');
hexo.extend.filter.register('after_post_render', function(data){
  var config = hexo.config;
  if(config.post_asset_folder){
        var link = data.permalink;
    if(version.length > 0 && Number(version[0]) == 3)
       var beginPos = getPosition(link, '/', 1) + 1;
    else
       var beginPos = getPosition(link, '/', 3) + 1;
    // In hexo 3.1.1, the permalink of "about" page is like ".../about/index.html".
    var endPos = link.lastIndexOf('/') + 1;
    link = link.substring(beginPos, endPos);

    var toprocess = ['excerpt', 'more', 'content'];
    for(var i = 0; i < toprocess.length; i++){
      var key = toprocess[i];

      var $ = cheerio.load(data[key], {
        ignoreWhitespace: false,
        xmlMode: false,
        lowerCaseTags: false,
        decodeEntities: false
      });

      $('img').each(function(){
        if ($(this).attr('src')){
            // For windows style path, we replace '\' to '/'.
            var src = $(this).attr('src').replace('\\', '/');
            if(!/http[s]*.*|\/\/.*/.test(src) &&
               !/^\s*\//.test(src)) {
              // For "about" page, the first part of "src" can't be removed.
              // In addition, to support multi-level local directory.
              var linkArray = link.split('/').filter(function(elem){
                return elem != '';
              });
              var srcArray = src.split('/').filter(function(elem){
                return elem != '' && elem != '.';
              });
              if(srcArray.length > 1)
                srcArray.shift();
              src = srcArray.join('/');
              $(this).attr('src', config.root + link + src);
              console.info&&console.info("update link as:-->"+config.root + link + src);
            }
        }else{
            console.info&&console.info("no src attr, skipped...");
            console.info&&console.info($(this));
        }
      });
      data[key] = $.html();
    }

  }
});
  • 然后将所引用的图片放在_posts下与文章同名文件夹下

    文件路径示例截图.PNG

  • 用hexo语法,如我的示例引用:

     {% asset_img 文件路径示例截图.PNG %}
  • 请注意你的图片命名不要有空格,不然也会不显示。

  • 之后你的博客文章引用的图片在主页和归档等子页面都可以正常显示了。

开门之作——小白HTML-CSS-JavaScript入门摸索历程

我是一个非计算机专业的同学,不过也因为时代发展,专业需要,也会用python写一些小代码。

平时呢热爱摄影、视频制作、还有视觉上好看的事物

我想开始学Web Design技术也主要是因为,我喜欢的一个YouTuber他的大学专业也本来是网页设计……Peter Mckinnon!

好了正式开始!

1. 学习资源

地址:MDN Web Docs

这是一个非常优质、可以称之为鼻祖Mozilla开源社区项目。它其中详细介绍了Web Design的各种基础技术知识。好好学,系统性地学,真的会有巨大的收获。 而且大多数内容都有中文版本。

MDN截图.PNG

2. 我的入门历程

  • 花1-2天时间阅读、上手操作HTML部分教程:
    • 了解HTML的结构<head>,<body>,<script>等;
    • 知道文本<p>(<h1><div><span>)、列表<ul><ol>、超链接<a href>、表格<table>、表单<form>的格式、用途;
    • 接触CSS的样式知识;
    • 知道如何选择特定内容querySelector
    • 表单<form>那里创建对象响应可能有些难,不过没关系,先仿照着学下去
  • 花1天时间学习CSS部分教程:
    • 了解CSS结构;
    • 知道如何选择特定部分,并修改样式;
    • 学习网页排版位置设置知识 (虽然这里我也没有好好学就跳过了);
  • 花3-4天时间学习JavaScript部分教程:
    • 变量、函数、循环等编程基础与其他编程语言大同小易,这个基础应该原本就具备;
    • 学会动态操纵文档,DOM树操作非常重要!
    • 会在浏览器Console控制台调试程序;
    • 控件响应事件学习,这样静态网页才能动起来
    • 其他还有更深层次的前端知识,异步处理,Canvas、OpenGL画图等等我先没有具体去学, 因为我的初衷是创建一个个人博客,就急于来自己上手尝试了。在此还是强烈建议有识之士去好好学习的。

3. 心得小结

虽然我自己也没有完完全全吃透MDN官方教程上的内容,但是自己这几天照着官方文档和示例去学习,主要有两大感受:

  • 系统性!这个教程比其他网络上的博客或者一些网站更专业更全面,并且有示例源码可以仿照学习。
  • 开心啊!终于自己可以看懂之前一些html网页源码内容,对于无论是爬虫、调用API、Echarts使用等等都很有帮助。

这个教程非常棒,以后遇到很多困惑都可以再回去查,而且发现网络上很多的解决方案的原始链接都是它!快去学习一下鼻祖的MDN Web Docs吧!

  • © 2020-2022 Eva Ren
  • Powered by Hexo Theme Ayer
    • 本站总访问量
    • 本页面总访问量
  • 载入运行时间...

请我喝杯咖啡吧~

支付宝
微信