Awesome
transdim
<h6 align="center">Made by Xinyu Chen • :globe_with_meridians: <a href="https://xinychen.github.io">https://xinychen.github.io</a></h6>Transportation data imputation (a.k.a., transdim).
Machine learning models make important developments in the field of spatiotemporal data modeling - like how to forecast near-future traffic states of road networks. But what happens when these models are built on incomplete data commonly collected from real-world systems (e.g., transportation system)?
<br>Table of Content
- About this Project
- Tasks and Challenges
- Implementation
- Quick Start
- Documentation
- Publications
- Contributors
About this Project
In the transdim project, we develop machine learning models to help address some of the toughest challenges of spatiotemporal data modeling - from missing data imputation to time series prediction. The strategic aim of this project is creating accurate and efficient solutions for spatiotemporal traffic data imputation and prediction tasks.
In a hurry? Please check out our contents as follows.
<br>Tasks and Challenges
<p align="center"> <img align="middle" src="https://github.com/xinychen/transdim/blob/master/images/missing.png" width="800" /> </p> <p align = "center"> <b>Figure 1</b>: Two classical missing patterns in a spatiotemporal setting. </p>Missing data are there, whether we like them or not. The really interesting question is how to deal with incomplete data.
We create three missing data mechanisms on real-world data.
-
Missing data imputation 🔥
- Random missing (RM): Each sensor lost observations at completely random. (★★★)
- Non-random missing (NM): Each sensor lost observations during several days. (★★★★)
- Blockout missing (BM): All sensors lost their observations at several consecutive time points. (★★★★)
- Spatiotemporal prediction 🔥
- Forecasting without missing values. (★★★)
- Forecasting with incomplete observations. (★★★★★)
Implementation
Open data
In this project, we have adapted some publicly available data sets into our experiments. The original links for these data are summarized as follows,
- Multivariate time series
- Birmingham parking data set
- California PeMS traffic speed data set (large-scale)
- Guangzhou urban traffic speed data set
- Hangzhou metro passenger flow data set
- London urban movement speed data set (other cities are also available at Uber movement project)
- Portland highway traffic data set (including traffic volume/speed/occupancy, see data documentation)
- Seattle freeway traffic speed data set
- Multidimensional time series
For example, if you want to view or use these data sets, please download them at the ../datasets/ folder in advance, and then run the following codes in your Python console:
import scipy.io
tensor = scipy.io.loadmat('../datasets/Guangzhou-data-set/tensor.mat')
tensor = tensor['tensor']
In particular, if you are interested in large-scale traffic data, we recommend PeMS-4W/8W/12W and UTD19. For PeMS data, you can download the data from Zenodo and place them at the folder of datasets (data path example: ../datasets/California-data-set/pems-4w.csv
). Then you can use Pandas
to open data:
import pandas as pd
data = pd.read_csv('../datasets/California-data-set/pems-4w.csv', header = None)
For model evaluation, we mask certain entries of the "observed" data as missing values and then perform imputation for these "missing" values.
Model implementation
In our experiments, we implemented some machine learning models mainly on Numpy
, and written these Python codes with Jupyter Notebook. If you want to evaluate these models, please download and run these notebooks directly (prerequisite: download the data sets in advance). In the following implementation, we have improved Python codes (in Jupyter Notebook) in terms of both readiability and efficiency.
Our proposed models are highlighted in bold fonts.
- imputer (imputation models)
Notebook | Guangzhou | Birmingham | Hangzhou | Seattle | London | NYC | Pacific |
---|---|---|---|---|---|---|---|
BPMF | ✅ | ✅ | ✅ | ✅ | ✅ | 🔶 | 🔶 |
TRMF | ✅ | 🔶 | ✅ | ✅ | ✅ | 🔶 | 🔶 |
BTRMF | ✅ | 🔶 | ✅ | ✅ | ✅ | 🔶 | 🔶 |
BTMF | ✅ | ✅ | ✅ | ✅ | ✅ | 🔶 | 🔶 |
BGCP | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
BATF | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
BTTF | 🔶 | 🔶 | 🔶 | 🔶 | 🔶 | ✅ | ✅ |
HaLRTC | ✅ | 🔶 | ✅ | ✅ | ✅ | ✅ | ✅ |
LRTC-TNN | ✅ | 🔶 | ✅ | ✅ | 🔶 | 🔶 | 🔶 |
- predictor (prediction models)
Notebook | Guangzhou | Birmingham | Hangzhou | Seattle | London | NYC | Pacific |
---|---|---|---|---|---|---|---|
TRMF | ✅ | 🔶 | ✅ | ✅ | ✅ | 🔶 | 🔶 |
BTRMF | ✅ | 🔶 | ✅ | ✅ | ✅ | 🔶 | 🔶 |
BTRTF | 🔶 | 🔶 | 🔶 | 🔶 | 🔶 | ✅ | ✅ |
BTMF | ✅ | 🔶 | ✅ | ✅ | ✅ | ✅ | ✅ |
BTTF | 🔶 | 🔶 | 🔶 | 🔶 | 🔶 | ✅ | ✅ |
- ✅ — Cover
- 🔶 — Does not cover
- 🚧 — Under development
For the implementation of these models, we use both
dense_mat
andsparse_mat
(ordense_tensor
andsparse_tensor
) as inputs. However, it is not necessary by doing so if you do not hope to see the imputation/prediction performance in the iterative process, you can removedense_mat
(ordense_tensor
) from the inputs of these algorithms.
Imputation/Prediction performance
- Imputation example (on Guangzhou data)
(a) Time series of actual and estimated speed within two weeks from August 1 to 14.
(b) Time series of actual and estimated speed within two weeks from September 12 to 25.
The imputation performance of BGCP (CP rank r=15 and missing rate α=30%) under the fiber missing scenario with third-order tensor representation, where the estimated result of road segment #1 is selected as an example. In the both two panels, red rectangles represent fiber missing (i.e., speed observations are lost in a whole day).
- Prediction example
Quick Start
This is an imputation example of Low-Rank Tensor Completion with Truncated Nuclear Norm minimization (LRTC-TNN). One notable thing is that unlike the complex equations in our paper, our Python implementation is extremely easy to work with.
- First, import some necessary packages:
import numpy as np
from numpy.linalg import inv as inv
- Define the operators of tensor unfolding (
ten2mat
) and matrix folding (mat2ten
) usingNumpy
:
def ten2mat(tensor, mode):
return np.reshape(np.moveaxis(tensor, mode, 0), (tensor.shape[mode], -1), order = 'F')
def mat2ten(mat, tensor_size, mode):
index = list()
index.append(mode)
for i in range(tensor_size.shape[0]):
if i != mode:
index.append(i)
return np.moveaxis(np.reshape(mat, list(tensor_size[index]), order = 'F'), 0, mode)
- Define Singular Value Thresholding (SVT) for Truncated Nuclear Norm (TNN) minimization:
def svt_tnn(mat, tau, theta):
[m, n] = mat.shape
if 2 * m < n:
u, s, v = np.linalg.svd(mat @ mat.T, full_matrices = 0)
s = np.sqrt(s)
idx = np.sum(s > tau)
mid = np.zeros(idx)
mid[:theta] = 1
mid[theta:idx] = (s[theta:idx] - tau) / s[theta:idx]
return (u[:,:idx] @ np.diag(mid)) @ (u[:,:idx].T @ mat)
elif m > 2 * n:
return svt_tnn(mat.T, tau, theta).T
u, s, v = np.linalg.svd(mat, full_matrices = 0)
idx = np.sum(s > tau)
vec = s[:idx].copy()
vec[theta:] = s[theta:] - tau
return u[:,:idx] @ np.diag(vec) @ v[:idx,:]
- Define performance metrics (i.e., RMSE, MAPE):
def compute_rmse(var, var_hat):
return np.sqrt(np.sum((var - var_hat) ** 2) / var.shape[0])
def compute_mape(var, var_hat):
return np.sum(np.abs(var - var_hat) / var) / var.shape[0]
- Define LRTC-TNN:
def LRTC(dense_tensor, sparse_tensor, alpha, rho, theta, epsilon, maxiter):
"""Low-Rank Tensor Completion with Truncated Nuclear Norm, LRTC-TNN."""
dim = np.array(sparse_tensor.shape)
pos_missing = np.where(sparse_tensor == 0)
pos_test = np.where((dense_tensor != 0) & (sparse_tensor == 0))
dense_test = dense_tensor[pos_test]
del dense_tensor
X = np.zeros(np.insert(dim, 0, len(dim))) # \boldsymbol{\mathcal{X}}
T = np.zeros(np.insert(dim, 0, len(dim))) # \boldsymbol{\mathcal{T}}
Z = sparse_tensor.copy()
last_tensor = sparse_tensor.copy()
snorm = np.sqrt(np.sum(sparse_tensor ** 2))
it = 0
while True:
rho = min(rho * 1.05, 1e5)
for k in range(len(dim)):
X[k] = mat2ten(svt_tnn(ten2mat(Z - T[k] / rho, k), alpha[k] / rho, np.int(np.ceil(theta * dim[k]))), dim, k)
Z[pos_missing] = np.mean(X + T / rho, axis = 0)[pos_missing]
T = T + rho * (X - np.broadcast_to(Z, np.insert(dim, 0, len(dim))))
tensor_hat = np.einsum('k, kmnt -> mnt', alpha, X)
tol = np.sqrt(np.sum((tensor_hat - last_tensor) ** 2)) / snorm
last_tensor = tensor_hat.copy()
it += 1
if (it + 1) % 50 == 0:
print('Iter: {}'.format(it + 1))
print('MAPE: {:.6}'.format(compute_mape(dense_test, tensor_hat[pos_test])))
print('RMSE: {:.6}'.format(compute_rmse(dense_test, tensor_hat[pos_test])))
print()
if (tol < epsilon) or (it >= maxiter):
break
print('Imputation MAPE: {:.6}'.format(compute_mape(dense_test, tensor_hat[pos_test])))
print('Imputation RMSE: {:.6}'.format(compute_rmse(dense_test, tensor_hat[pos_test])))
print()
return tensor_hat
- Let us try it on Guangzhou urban traffic speed data set:
import scipy.io
import scipy.io
import numpy as np
np.random.seed(1000)
dense_tensor = scipy.io.loadmat('../datasets/Guangzhou-data-set/tensor.mat')['tensor']
dim = dense_tensor.shape
missing_rate = 0.2 # Random missing (RM)
sparse_tensor = dense_tensor * np.round(np.random.rand(dim[0], dim[1], dim[2]) + 0.5 - missing_rate)
- Run the imputation experiment:
import time
start = time.time()
alpha = np.ones(3) / 3
rho = 1e-5
theta = 0.30
epsilon = 1e-4
maxiter = 200
tensor_hat = LRTC(dense_tensor, sparse_tensor, alpha, rho, theta, epsilon, maxiter)
end = time.time()
print('Running time: %d seconds'%(end - start))
<br>This example is from ../imputer/LRTC-TNN.ipynb, you can check out this Jupyter Notebook for details.
Documentation
- Intuitive understanding of randomized singular value decomposition. July 1, 2020.
- Generating random numbers and arrays in Matlab and Numpy. October 9, 2021.
- Reduced-rank vector autoregressive model for high-dimensional time series forecasting. October 16, 2021.
- Dynamic mode decomposition for spatiotemporal traffic speed time series in Seattle freeway. October 29, 2021.
- Analyzing missing data problem in Uber movement speed data. February 14, 2022.
- Using conjugate gradient to solve matrix equations. February 23, 2022.
- Inpainting fluid dynamics with tensor decomposition (NumPy). March 15, 2022.
- Temporal matrix factorization for multivariate time series forecasting. March 20, 2022.
- Forecasting multivariate time series with nonstationary temporal matrix factorization. April 25, 2022.
- Implementing Kronecker product decomposition with NumPy. June 20, 2022.
- Tensor autoregression: A multidimensional time series model. September 3, 2022.
- Reproducing dynamic mode decomposition on fluid flow data in Python. September 6, 2022.
- Convolution nuclear norm minimization for time series modeling. October 3, 2022.
- Reinforce matrix factorization for time series modeling: Probabilistic sequential matrix factorization. October 5, 2022.
- Discrete convolution and fast Fourier transform explained and implemented step by step. October 19, 2022.
- Matrix factorization for image inpainting in Python. December 8, 2022.
- Circulant matrix nuclear norm minimization for image inpainting in Python. December 9, 2022.
- Low-rank Laplacian convolution model for time series imputation and image inpainting. December 10, 2022.
- Low-rank Laplacian convolution model for color image inpainting. December 17, 2022.
- Intuitive understanding of tensors in machine learning. January 20, 2023.
- Low-rank matrix and tensor factorization for speed field reconstruction. March 9, 2023.
- Bayesian vector autoregression forecasting
- Structured low-rank matrix completion
Publications
-
Xinyu Chen, Zhanhong Cheng, HanQin Cai, Nicolas Saunier, Lijun Sun (2024). Laplacian convolutional representation for traffic time series imputation. IEEE Transactions on Knowledge and Data Engineering. 36 (11): 6490-6502. [DOI] [Slides] [Data & Python code]
-
Xinyu Chen, Lijun Sun (2022). Bayesian temporal factorization for multidimensional time series prediction. IEEE Transactions on Pattern Analysis and Machine Intelligence, 44 (9): 4659-4673. [Preprint] [DOI] [Slides] [Data & Python code]
-
Xinyu Chen, Mengying Lei, Nicolas Saunier, Lijun Sun (2022). Low-rank autoregressive tensor completion for spatiotemporal traffic data imputation. IEEE Transactions on Intelligent Transportation Systems, 23 (8): 12301-12310. [Preprint] [DOI] [Data & Python code] (Also accepted in part to MiLeTS Workshop of KDD 2021, see workshop paper)
-
Xinyu Chen, Yixian Chen, Nicolas Saunier, Lijun Sun (2021). Scalable low-rank tensor learning for spatiotemporal traffic data imputation. Transportation Research Part C: Emerging Technologies, 129: 103226. [Preprint] [DOI] [Data] [Python code]
-
Xinyu Chen, Jinming Yang, Lijun Sun (2020). A nonconvex low-rank tensor completion model for spatiotemporal traffic data imputation. Transportation Research Part C: Emerging Technologies, 117: 102673. [Preprint] [DOI] [Data & Python code]
-
Xinyu Chen, Zhaocheng He, Yixian Chen, Yuhuan Lu, Jiawei Wang (2019). Missing traffic data imputation and pattern discovery with a Bayesian augmented tensor factorization model. Transportation Research Part C: Emerging Technologies, 104: 66-77. [DOI] [Slides] [Data] [Matlab code] [Python code]
-
Xinyu Chen, Zhaocheng He, Lijun Sun (2019). A Bayesian tensor decomposition approach for spatiotemporal traffic data imputation. Transportation Research Part C: Emerging Technologies, 98: 73-84. [Preprint] [DOI] [Data] [Matlab code] [Python code]
-
Xinyu Chen, Zhaocheng He, Jiawei Wang (2018). Spatial-temporal traffic speed patterns discovery and incomplete data recovery via SVD-combined tensor decomposition. Transportation Research Part C: Emerging Technologies, 86: 59-77. [DOI] [Data]
This project is from the above papers, please cite these papers if they help your research.
Collaborators
<table> <tr> <td align="center"><a href="https://github.com/xinychen"><img src="https://github.com/xinychen.png?size=80" width="80px;" alt="Xinyu Chen"/><br /><sub><b>Xinyu Chen</b></sub></a><br /><a href="https://github.com/xinychen/transdim/commits?author=xinychen" title="Code">💻</a></td> <td align="center"><a href="https://github.com/Vadermit"><img src="https://github.com/Vadermit.png?size=80" width="80px;" alt="Jinming Yang"/><br /><sub><b>Jinming Yang</b></sub></a><br /><a href="https://github.com/xinychen/transdim/commits?author=Vadermit" title="Code">💻</a></td> <td align="center"><a href="https://github.com/yxnchen"><img src="https://github.com/yxnchen.png?size=80" width="80px;" alt="Yixian Chen"/><br /><sub><b>Yixian Chen</b></sub></a><br /><a href="https://github.com/xinychen/transdim/commits?author=yxnchen" title="Code">💻</a></td> <td align="center"><a href="https://github.com/MengyingLei"><img src="https://github.com/MengyingLei.png?size=80" width="80px;" alt="Mengying Lei"/><br /><sub><b>Mengying Lei</b></sub></a><br /><a href="https://github.com/xinychen/transdim/commits?author=MengyingLei" title="Code">💻</a></td> <!-- <td align="center"><a href="https://github.com/lijunsun"><img src="https://github.com/lijunsun.png?size=80" width="80px;" alt="Lijun Sun"/><br /><sub><b>Lijun Sun</b></sub></a><br /><a href="https://github.com/xinychen/transdim/commits?author=lijunsun" title="Code">💻</a></td> <td align="center"><a href="https://github.com/HanTY"><img src="https://github.com/HanTY.png?size=80" width="80px;" alt="Tianyang Han"/><br /><sub><b>Tianyang Han</b></sub></a><br /><a href="https://github.com/xinychen/transdim/commits?author=HanTY" title="Code">💻</a></td> --> <!-- </tr> <tr> <td align="center"><a href="https://github.com/xxxx"><img src="https://github.com/xxxx.png?size=100" width="100px;" alt="xxxx"/><br /><sub><b>xxxx</b></sub></a><br /><a href="https://github.com/xinychen/transdim/commits?author=xxxx" title="Code">💻</a></td> --> </tr> </table>- Advisory Board
<br>See the list of contributors who participated in this project.
Supported by
<a href="https://ivado.ca/en"> <img align="middle" src="https://github.com/xinychen/tracebase/blob/main/graphics/ivado_logo.jpeg" alt="drawing" height="70" hspace="50"> </a> <a href="https://www.cirrelt.ca/"> <img align="middle" src="https://github.com/xinychen/tracebase/blob/main/graphics/cirrelt_logo.png" alt="drawing" height="50"> </a> <br>License
This work is released under the MIT license.