Paper · 2018-04-05 · cs.LG, stat.ML
Inferring transportation modes from GPS trajectories using a convolutional neural network
Classifies travel mode (walk, bike, bus, driving, train) from raw GPS trajectories with a 1-D CNN over 200-point segments. Each point gets four channels: speed, acceleration, jerk and bearing rate. A seven-model ensemble reaches 84.8% test accuracy on GeoLife, author-reported; the test set also guided epoch selection.
Convolutional neural networkData augmentationTime series classificationtransportationgpstrajectorymode-inferencecnntime-series
AI-compiled by claude-haiku-5-5 on 2026-10-18, not yet reviewed by a human. Every claim cites its source; check it when a detail matters.
In plain words
Your phone's GPS log is a long list of timestamped positions. From that list alone you can often tell whether someone was walking, cycling, on a bus, in a car or on a train, because each mode moves in its own characteristic way. Traffic planners want this information, and collecting it by asking people is slow and unreliable.
Older methods first computed a fixed set of hand-made summaries of a trip, such as average speed or number of stops, and then fed them to a classic classifier. This paper instead turns the raw positions into a small image-like grid. Each column is one GPS point, and the rows hold how fast the device was moving, how quickly that speed changed, how quickly the acceleration changed, and how much the heading turned. A convolutional neural network learns its own features from that grid.
The authors clean the data first, removing impossible jumps and smoothing the track. They then compare many small network designs and combine several trained copies into a vote. The best combined model is more accurate on the same benchmark than the hand-crafted methods they compare against, although the numbers come from the authors' own experiments.
TL;DR
A GeoLife-based study that classifies five travel modes (walk, bike, bus, driving, train) from GPS points alone. Each 200-point segment becomes a (1 × 200 × 4) tensor of speed, acceleration, jerk and bearing rate §3.1 §3.2.1. A 1-D CNN, tuned by hand, reaches 79.8% test accuracy; 62 training epochs and an ensemble of seven bootstrap-trained copies reach 84.8% (author-reported) §5.1 tab. 4. Use it as a baseline for trajectory-based mode inference, but note the random segment-level split and the test-set-based epoch choice (see Pitfalls).
Problem
Travel-mode distribution is used for planning and policy, and surveys are costly and give low response rates §1. GPS logs are cheap to collect but carry only positions and times §1. Feature-based methods depend on hand-made features, which break under traffic and environmental conditions and reflect the designer's bias §1 §2. Earlier deep-learning work either turned trajectories into images from dwell time or used point-level features sampled at a fixed time interval, which the authors argue loses information §2. Labelled GPS data is scarce, which the authors name as the main obstacle to better results §6.
Method
Overview. Each user's log is cut into trips, cleaned, smoothed and split into fixed-length segments. Each segment carries four motion channels per point. A hand-tuned 1-D CNN with a softmax output classifies each segment. The final model is an ensemble of seven copies, each trained on a bootstrap sample of the training set, whose softmax outputs are averaged §3 §3.2.6 §6.
Step 1: trips and labels §4. A log is split into trips wherever the gap between consecutive points exceeds 10 minutes. The labelled trips for each mode are then matched to the user's label file. Driving covers taxi and car; all rail modes (subway, train, railway) are merged into "train" §4.
Step 2: segments §4 §3.2.1. Trips are converted into segments of M = 200 points, the median trip length. Segments with identical labels are concatenated before this step, and segments with fewer than 10 points are discarded. Long segments are truncated to M and short ones padded with zeros §3.2.1. Section 3.1 describes this as subdividing or padding instead §3.1; see Pitfalls.
Step 3: remove invalid points §3.1 tab. 2. Drop any point whose timestamp is greater than that of the next point. Drop points whose speed or acceleration exceeds a per-mode threshold from Table 2. The thresholds are set from published speed limits, vehicle capability and human power, according to the authors §4.
Step 4: smooth §3.1 §4. A Savitzky–Golay filter with window 9 and polynomial order 3 is applied to the trajectory to remove random errors §4. The paper places this step before feature extraction, but also says it is applied to "all segments' sequences" §3.1.
Step 5: motion features eq. 1–7 fig. 1. For a point P1 and its successor P2, with Δt the time between them:
- Speed is the Vincenty geodesic distance divided by Δt eq. 1. Vincenty's formula is cited to §3.1.
- Acceleration is the change in speed divided by Δt eq. 2.
- Jerk is the change in acceleration divided by Δt eq. 3.
- Bearing is the direction of the segment P1→P2, relative to north eq. 4–6. Latitude and longitude are in radians; the output is in degrees §3.1.
- Bearing rate is the absolute difference of consecutive bearings eq. 7.
Step 6: input tensor §3.2.1 fig. 2. The four channels are stacked into a tensor of shape (1 × M × 4), with M = 200. Each channel is a row of M values, one per point.
Step 7: network §3.2 tab. 1. The network stacks 1 × 3 convolutions with stride 1 and zero-padding so the length is unchanged §3.2.2. ReLU follows each convolution §3.2.3. A 1 × 2 max-pool with stride 1 is inserted between blocks §3.2.4. Dropout is applied in some places, and the number of filters per layer is set by a manual search §3.2.6 §3.2.7. Fully connected layers have one-quarter of the neurons of the flattened layer before them, and the last layer has five outputs tab. 1 caption. Softmax gives class probabilities §3.2.5.
Step 8: train §3.2.8 §5.1. Each candidate is trained with categorical cross-entropy and the Adam optimizer, batch size 64. Architectures are compared after 10 epochs. The final model G is trained for 62 epochs. Epoch count is then chosen by the peak of the test curve §5.1 fig. 3.
Step 9: ensemble §3.2.6 §5.1 §6. Seven copies of model G are each trained on a bootstrap sample of the training set, drawn with replacement. Their softmax outputs are averaged.
Pseudocode (Python-flavoured; paper equations are in the Key equations list):
# Pipeline overview [§3] [§4]
# Input: one user's GPS log (lat, long, timestamp)
# Output: class probabilities over 5 modes for each 200-point segment
def make_segments(points):
# Split the log into trips at gaps over 10 minutes [§4]
trips = split_on_time_gap(points, gap_seconds = 10 * 60)
segments = []
for trip in trips:
# Fixed-length segments of M = 200 points [§4] [§3.2.1]
for piece in fixed_length_pieces(trip, length = 200):
# Discard segments with fewer than 10 points [§4]
if count(piece) >= 10:
segments.append(piece)
return segments# Clean and smooth one segment [§3.1] [§4]
def clean_segment(points, speed_limit, accel_limit):
# Drop points whose timestamp is later than the next point's [§3.1]
points = drop_non_increasing_time(points)
# Drop points above the per-mode speed and acceleration limits [tab. 2]
points = drop_over_limits(points, speed_limit, accel_limit)
# Savitzky-Golay smoothing: window 9, polynomial order 3 [§4]
return savgol_smooth(points, window = 9, order = 3)# Motion channels for one segment [eq. 1-7] [fig. 2]
def motion_channels(points):
# Geodesic distance over the time step to the next point [eq. 1]
speeds = vincenty(points[:-1], points[1:]) / time_steps
# Change of speed over the time step [eq. 2]
accels = diff(speeds) / time_steps[1:]
# Change of acceleration over the time step [eq. 3]
jerks = diff(accels) / time_steps[2:]
# Bearing of each step, in degrees, from radians [eq. 4-6]
bearings = bearing_degrees(points[:-1], points[1:])
# Absolute change of bearing between consecutive steps [eq. 7]
bearing_rates = abs(diff(bearings))
return speeds, accels, jerks, bearing_rates# Ensemble of seven models [§3.2.6] [§5.1] [§6]
def train_ensemble(train_set, count = 7):
models = []
for index in range(count):
# Bootstrap sample of the training set, drawn with replacement [§3.2.6]
subset = sample_with_replacement(train_set)
models.append(train_cnn(subset, epochs = 62)) # epochs [§5.1]
return models
def predict(models, segment):
# Average the softmax outputs of all members [§3.2.6]
probs = mean([model(segment) for model in models])
return probs # (5,) mode probabilities# Optimizer and loss [§3.2.8]
# Adam: learning rate 0.001, beta1 0.9, beta2 0.999, epsilon 1e-8
optimizer = adam(lr = 0.001, beta1 = 0.9, beta2 = 0.999, eps = 1e-8)
# Categorical cross-entropy over the 5 mode labels, batch size 64
loss = cross_entropy(predicted_probs, one_hot_labels)Key equations, as printed in the paper:
S_{p_1} = \frac{\mathrm{Vincenty}(P_1, P_2)}{\Delta t} eq. 1
A_{p_1} = \frac{S_{p_2} - S_{p_1}}{\Delta t} eq. 2
J_{p_1} = \frac{A_{p_2} - A_{p_1}}{\Delta t} eq. 3
y = \sin[p_2(\mathrm{long}) - p_1(\mathrm{long})] \cdot \cos[p_2(\mathrm{lat})] eq. 4
x = \cos[p_1(\mathrm{lat})]\sin[p_2(\mathrm{lat})] - \sin[p_1(\mathrm{lat})]\cos[p_2(\mathrm{lat})]\cos[p_2(\mathrm{long}) - p_1(\mathrm{long})] eq. 5
\mathrm{Bearing}_{(p_1)} = \arctan(y, x) eq. 6
BR_{(p_1)} = \left| \mathrm{Bearing}_{(p_2)} - \mathrm{Bearing}_{(p_1)} \right| eq. 7
Hyperparameters
| Name | Value | Where | Notes |
|---|---|---|---|
| Travel modes (output classes) | 5: walk, bike, bus, driving, train | §4 tab. 2 | Output layer has 5 neurons tab. 1 caption |
| Trip split gap | 10 minutes | §4 | Between consecutive points |
| Segment length M | 200 points | §4 §3.2.1 | Median trip length §4; padding or truncation per §3.2.1 |
| Minimum points per segment | 10 | §4 | Shorter segments discarded |
| Max speed per mode | walk 7, bike 12, bus 34, driving 50, train 34 m/s | tab. 2 | Used to drop invalid points §3.1 |
| Max acceleration per mode | walk 3, bike 3, bus 2, driving 10, train 3 m/s² | tab. 2 | Used to drop invalid points §3.1 |
| Savitzky–Golay window | 9 | §4 | Applied to GPS trajectories |
| Savitzky–Golay polynomial order | 3 | §4 | |
| Convolution filter size | 1 × 3 | §3.2.2 tab. 1 caption | Stride 1; zero-padding keeps size (inferred from "same size", §3.2.2) |
| Filters per conv layer | 32, 64, 128, 256 per Table 1 | tab. 1 §3.2.7 | Configuration-specific; see Table 1 notes below |
| Max-pool size and stride | 1 × 2, stride 1 | §3.2.4 tab. 1 caption | |
| Activation | ReLU | §3.2.3 | |
| Dropout rate P | 0.5 (selected from grid 0.2–0.8) | §5.1 | Grid by 5-fold CV on training set |
| Fully connected width | one-quarter of previous flattened layer | tab. 1 caption §3.2.5 | Last FC = 5 |
| Optimizer | Adam | §3.2.8 | |
| Learning rate | 0.001 | §3.2.8 | Decay not stated |
| Adam β1, β2, ε | 0.9, 0.999, 1e-8 | §3.2.8 | Paper states these are Adam's defaults |
| Batch size | 64 | §3.2.8 | |
| Weight initialisation | Glorot and Bengio scheme | §3.2.8 | Exact variant (uniform or normal) not stated |
| Loss | categorical cross-entropy | §3.2.8 | |
| Epochs for architecture search | 10 | §3.2.8 | |
| Epochs for final model G | 62 | §5.1 | Peak of test curve; see Pitfalls |
| Ensemble size | 7 copies of model G | §5.1 §6 | Bootstrap sample each |
| Train/test split | 80% / 20%, random over segments | §5 | Validation split not stated |
| Weight decay, LR schedule, seeds | not stated | ||
| Input normalisation | not stated | Channels fed as computed; scaling not mentioned |
Table 1 (CNN configurations) tab. 1. Nine configurations A–I. All configurations share the same input and output layers, and differ in filter counts, presence of max-pool and dropout, and FC depth. Model G has two 32-filter convolutions, two 64-filter, and two 128-filter layers, with max-pool after each block tab. 1 §5.1. The placement of dropout and FC layers in column G could not be verified reliably from the rendered table, so check column G directly against the PDF before implementing. The text states that G is shallower than H and I §5.1.
Table 2 (samples and thresholds) tab. 2:
| Mode | Segments | Max speed (m/s) | Max acceleration (m/s²) |
|---|---|---|---|
| Walk | 10,372 | 7 | 3 |
| Bike | 5,568 | 12 | 3 |
| Bus | 7,292 | 34 | 2 |
| Driving | 4,490 | 50 | 10 |
| Train | 4,722 | 34 | 3 |
Total 32,444 segments §4.
Results
Author-reported. Setup: GeoLife GPS trajectories from 69 users (Microsoft repository version 1.3) §4 p. 371. Models built with Keras on a TensorFlow CPU backend. Hardware: Intel Core i7 at 2.50 GHz with 16 GB RAM §5 §5.1. Training model G for 62 epochs took about 25 minutes §5.1.
Table 4 (improvement steps for model G) tab. 4:
| Step | Test accuracy (%) |
|---|---|
| Original model G (Table 1) | 79.8 |
| Model G with optimal P values | 79.8 |
| Model G trained for optimal 62 epochs | 82.3 |
| Ensemble of seven model G | 84.8 |
Table 3 (CNN configurations A–I, test accuracy %) tab. 3: A 74.5, B 75.0, C 76.9, D 75.1, E 77.0, F 69.2, G 79.8, H 79.6, I 78.3.
Table 5 (confusion matrix, ensemble of model G, test set of 6,489 segments) tab. 5. Rows are actual, columns are predicted, as printed:
| Actual \ predicted | Walk | Bike | Bus | Driving | Train | Sum | Recall % |
|---|---|---|---|---|---|---|---|
| Walk | 2014 | 53 | 40 | 3 | 2 | 2112 | 95.7 |
| Bike | 171 | 946 | 32 | 3 | 1 | 1153 | 82.6 |
| Bus | 147 | 23 | 1104 | 70 | 25 | 1369 | 81.1 |
| Driving | 71 | 17 | 171 | 601 | 42 | 902 | 67.4 |
| Train | 75 | 17 | 31 | 24 | 806 | 953 | 85.3 |
| Sum | 2478 | 1056 | 1378 | 701 | 866 | 6489 | – |
| Precision % | 81.6 | 90.3 | 80.7 | 86.6 | 92.3 | – | – |
See Pitfalls: the printed recall, precision and column totals do not all match the printed counts.
Table 6 (comparison with classical methods, test set) tab. 6. The hyperparameters were tuned by grid search with 5-fold CV on the training set. The paper labels the random forest "RT" in the table and "RF" in the text.
| Model | Hyperparameter | Range | Optimal | Test acc. % | Avg. precision % | Avg. recall % | Avg. F-score % |
|---|---|---|---|---|---|---|---|
| KNN | No. of neighbours | [3, 40] | 5 | 63.5 | 63.2 | 63.5 | 62.4 |
| SVM | Regularization | [0.5, 20] | 4 | 65.4 | 66.9 | 65.4 | 64.9 |
| DT | Max. depth | [1, 40] | 10 | 75.2 | 75.2 | 75.2 | 74.9 |
| RF (RT) | No. of trees | [5, 100] | 85 | 78.1 | 78.2 | 78.1 | 77.7 |
| MLP | No. of hidden layers | [1, 10] | 1 | 59.4 | 58.8 | 59.4 | 54.6 |
| CNN-A | Already satisfied | NA | NA | 75.6 | 75.2 | 75.6 | 74.8 |
| Best CNN (ensemble) | Already satisfied | NA | NA | 84.8 | 86.3 | 82.4 | 83.9 |
Table 7 (comparison with prior GeoLife studies, test accuracy) tab. 7: Zheng et al. 2008a: 76.2; Endo et al. 2016: 67.9; "Wang et al." (see Pitfalls): 74.1; this study's ensemble of model G: 84.8.
Figures. fig. 1 shows the bearing between consecutive GPS points. [fig. 2] shows the four-channel (1 × M × 4) input for one segment. fig. 3 plots training and test accuracy against epochs for model G: training accuracy keeps rising to about 96%, test accuracy levels off around 81–82% after about 30 epochs §5.1.
Paper vs code
No official code. The paper gives no repository or project link, and no code
link appears in the arXiv metadata. Searches: GitHub repository search for
"transportation mode inference CNN GPS trajectories Dabiri" and "GPS
transportation mode CNN Dabiri Heaslip" returned 0 results. No code is
cloned or cited, and the code field is omitted.
Pitfalls
- Epoch selection uses the test set. Section 3.2.8 says the epoch count is the maximum of the validation score, but Section 5.1 and fig. 3 choose it by the test curve. The 82.3% and 84.8% figures are therefore optimistic. A clean protocol needs a separate validation split, which the paper does not describe.
- Random split over segments, not users. The 80/20 split is random over segments §5. Segments from the same user and trip can land in both sets, which inflates accuracy. The paper does not report a user-level split.
- Table 5 does not add up as printed. Recomputing from the counts gives recall 95.4, 82.0, 80.6, 66.6 and 84.6 %, versus printed 95.7, 82.6, 81.1, 67.4 and 85.3 %. Precision computed from the same matrix is 81.3, 89.6, 80.1, 85.7 and 92.0 %. The printed predicted-Train total (866) is also 10 short of the column sum (876); the grand total (6,489) matches the row sums. Diagonal total is 5,471 of 6,489, which is 84.3%, while Table 4 reports 84.8%. Treat Table 5 as approximate.
- Padding and truncation conflict. Section 3.1 says long trips are subdivided and short ones padded with zeros §3.1. Section 3.2.1 says long segments are truncated §3.2.1. Zero padding also feeds zero speeds and accelerations into the network, and the paper does not say whether features are computed before or after padding.
- Thresholds for unseen tracks. Table 2 gives per-mode speed and acceleration limits, used on labelled training segments §4. The paper says unseen tracks are segmented the same way §4 but does not say which limits apply at inference, when the mode is unknown.
- Smoothing target and order. The Savitzky–Golay filter is described as smoothing GPS trajectories §4, but also as applied to "all segments' sequences" §3.1. Whether it runs before or after feature computation is not explicit.
- Time step Δt. Equations 1–3 use the same Δt for speed, acceleration and jerk. Which point the features are assigned to (P1 or P2) is not stated, and the last point of a segment has no successor, so its values are undefined in the paper.
- Bearing rate. Equation 7 takes the absolute difference of bearings in degrees without wrapping. A turn from 359° to 1° gives 358, not 2. Also, the arctangent is written as arctan(y, x); the quadrant convention is implied.
- No input normalisation stated. The four channels have very different scales (speed in m/s, bearing rate in degrees). No scaling is mentioned.
- Pooling geometry. Max-pool uses a 1 × 2 window with stride 1 §3.2.4. With no padding this shortens the sequence by one per pool. The paper says the pooling layer's input and output depth match, but does not state the output length.
- Class imbalance. Counts range from 4,490 (driving) to 10,372 (walk) tab. 2. No class weights or resampling are described. Headline accuracy therefore favours walk.
- "Wang et al." in Table 7. The name does not appear in the reference list, which has Hao et al. (2017) and Xiao et al. (2017). The card cannot tell which is meant.
- Comparisons with prior work. Table 7 compares against studies whose preprocessing and splits are not described here. Treat the gaps as indicative only.
- Compute. About 25 minutes for 62 epochs on a CPU §5.1. The ensemble requires seven such trainings.
- Unstated details. Seeds, weight decay, learning-rate schedule, validation split size, whether all ensemble members use 62 epochs, and the exact Glorot variant are all not stated.
Lineage
- Builds on: hand-crafted-feature mode inference with GeoLife, as in Zheng et al. (2008a, 2008b), cited in the paper. Those works have no card here, so nothing from them is used. The paper uses the same segment features as the hand-crafted baseline for its classical comparison §5.2.
- Compared against: KNN, SVM, decision tree, random forest and MLP baselines tab. 6; prior GeoLife deep-learning and feature studies tab. 7.
- Superseded by: not known from content already in this wiki.
Source and license
Adapted from “Inferring transportation modes from GPS trajectories using a convolutional neural network” by Sina Dabiri, Kevin Heaslip (arXiv:1804.02386), used under CC0 1.0. Changes: condensed and restructured for implementation, with tables, equations and algorithms taken from the paper and its code, each cited to its source. Not affiliated with or endorsed by the authors.