背景
METR_LA analogue ressults
- Forecasting using spatio-temporal data with combined Graph Convolution + LSTM model, StellarGraph demos
- ipynb
數據特性之比較(Graph components)
- 圖形(節點、邊緣、加權等)為靜態、節點特徵值則為動態
- 單一特徵
項目 | METRO_LA | 2019.nc_NO2 | 說明 |
---|---|---|---|
data source | LA交通局數據 | 2019.nc CMAQ公版模式背景濃度模擬結果 | |
節點 | 速度監測站點 | 島內各網格點 | 前者較少、後者較多 |
特徵值 | 交通速度 | 空氣污染濃度值 | 分部有顯著差異(詳下) |
時間頻率特徵 | 每5分鐘一筆 | 每小時一筆 | |
邊緣加權 | 站點間的距離(作為邊緣的加權量) | 網格點間距離-0.25 |
parameters
項目 | METRO_LA | 2019.nc_NO2 | 說明 |
---|---|---|---|
seq_len | 10 | 72 | |
pre_len | 12 | 24 | |
gc_layer_sizes | [16, 10] | [16, 72] | |
gc_activations | relu | relu | |
lstm_layer_sizes | [20, 10] | [20, 72] | |
lstm_activations | tanh | tanh | |
epochs | 100 | 200 | |
batch_size | 60 | 60 | |
MASE | 0.698 | 0.650 | 同一數量級 |
Loss/MSE during training
METR_LA速度預報訓練 | 2019.nc_NO2 |
Distribution over segments
- speed training and testing results
- training及testing都是扁胖形分布、訓練組更胖一些。表示原始數據可以符合高斯分布,並沒有顯著的極端值。訓練組的符合度更好一些。
- 測試組之模擬誤差略為偏低
METR_LA速度預報測試結果 | 2019.nc_NO2 |
- NO2
- 原始數據與高斯模式的符合度不高。訓練及測試組皆然。(空氣品質的分布特性為對數高斯分布。)
- training及testing都有強烈的趨中性質
- 二者的平均絕對誤差值還蠻接近的
- 測試組之誤差略為偏低
all test result visualization
- speed predictoins
METR_LA速度預報測試結果 | 2019.nc_NO2(部分值) |
- NO2 predictions
- 可以抓到日變化的趨勢
- 對高值毫無預測能力。還需借助於其他模型、如
- 預先分類再予訓練
程式設計重點說明
台灣島多邊形之讀取
- 使用Voronoi作業過程中的半成品
import geopandas as gpd
root='/nas2/cmaqruns/2022fcst/fusion/Voronoi/'
boundary=gpd.read_file(root+'boundary_shape.shp')
boundary_shape = boundary.geometry[0]
島內格點的篩選
- 此處使用shapely.geometry.Polygon.within函數
- 先篩出符合的點的名稱標籤(
name
) - DataFrame.loc中設定boolean將原來資料表篩減,減省至少2/3。
x1d=[nc.XORIG+nc.XCELL*(i+0.5) for i in range(ncol)]
y1d=[nc.YORIG+nc.YCELL*(i+0.5) for i in range(nrow)]
X,Y=np.meshgrid(x1d,y1d)
X,Y=X.flatten(),Y.flatten()
lons, lats= pnyc(X,Y, inverse=True)
pnts=[Point(lon,lat) for lon,lat in zip(lons,lats)]
dfNod=pd.DataFrame({'geometry':pnts,'name':[str(i) for i in range(NM)]})
name_inside=dfNod.loc[dfNod.geometry.map(lambda p:p.within(boundary_shape)),'name']
...
s=set(name_inside)
n=len(s)
dfNod2=dfNod.loc[dfNod.name.map(lambda x:x in s)].reset_index(drop=True)"
網格點兩兩距離之計算
- 這個問題如果用迴圈來設計,將會是一個災難。
- 用shapely.geometry.Point.distance函數、完全沒有幫助
- 即使計算對角線上(或下)一半,在映射到另一半,可以減省一半的計算時間,還是沒有太大的幫助。
- 可以利用None維度的技巧,來重複2維矩陣中特定的一個部分。(參矩陣階層numpy.newaxis(None)的用法)
- 下列程式段落中的n即為網格點個數,因為是計算兩兩距離(d),因此d的維度是2維,大小都是n。
- 預先將網格點X、Y值處理成1維向量,其長度為n
X,Y=np.array(dfNod2.X),np.array(dfNod2.Y)
- 設定終點為第0個維度、起點則為第1個(另一個)維度
- 用矩陣標示法直接計算這個d[n,n]的方法,就是定義相對應的終點(X1,Y1)與起點(X2,Y2),進行差值計算、取平方、相加、再取根號。
d[:,:]=np.sqrt((X1-X2)**2+(Y1-Y2)**2)
- 因此X1、X2、Y1、Y2的形狀,也必須完全與d相同
- 先予以填充0值,預留記憶體(空的容器)。
- 起點為第0個維度,因此X1、Y1第0個維度的內容必須完全與X,Y相同,另一個維度則複製即可。此處以None將向量複製擴張成矩陣。
- 同理應用在終點(X2、Y2),維度設定與起點(X1、Y1)相反即可。
- 交錯寫法,是因為複製、貼上、將X改成Y,是最快的編輯方式
d=np.zeros(shape=(n,n))
X1=np.zeros(shape=(n,n))
Y1=np.zeros(shape=(n,n))
X2=np.zeros(shape=(n,n))
Y2=np.zeros(shape=(n,n))
X,Y=np.array(dfNod2.X),np.array(dfNod2.Y)
X1[:,:],X2[:,:]=X[:,None],X[None,:]
Y1[:,:],Y2[:,:]=Y[:,None],Y[None,:]
d[:,:]=np.sqrt((X1-X2)**2+(Y1-Y2)**2) #dfNod2.geometry[j].distance(dfNod2.geometry[i])
#for j in range(n):
# for i in range(0,j):
# d[j,i]=d[i,j]
加權的計算
- 原範例是用交通速度測點間的距離來加權,距離越大的路段速度會越快,加權越重。通過2個測點的速度比較容易相近(車輛運動的慣性物理性質),越近的測點,車速會降低,加減速的敏感性就越高(作者認定的模型)。
- 此處空氣品質則相反,距離越遠的點差異可能就越大,越相近的點差異會越小。因此使用距離的倒數來加權
- 同一點的距離為0,倒數無意義,且不能參與取極值過程。因此取倒數後直接令其為1(足夠小的暫定值)。
- 取極值之後,再將對角線值全都設為最大值,再除以此最大值,以使最大值為1。
- 取0.25次方的用意是讓空間上的漸變過程趨緩一些
d=1/d*1000.
for j in range(n):
d[j,j]=1.
dmax=d.max()
for j in range(n):
d[j,j]=dmax
d=np.sqrt(np.sqrt(d/dmax))