TDN-IntensityGMM-TW

Machine-learning ground-motion models (GMM) for Taiwan. Given an earthquake's magnitude, depth and epicentre, they predict PGA and PGV at any target location, from which the CWA seismic intensity is obtained. Shipped as self-contained ONNX files that run anywhere onnxruntime runs.

Flagship: TDN-IntensityGMM-TW-524k-v1.onnx - trained on 523,569 station records from 1,181 Taiwan earthquakes (2020-2025), merging the P-Alert MEMS network and the CWA strong-motion reports.

Model family

Naming: TDN-<task>-TW-[source-]<records>k-v<n>

file task training data records
TDN-IntensityGMM-TW-524k-v1.onnx PGA/PGV regression P-Alert + CWA (merged) 523,569
TDN-IntensityGMM-TW-PAlert-479k-v1.onnx PGA/PGV regression P-Alert only 478,846
TDN-IntensityGMM-TW-CWA-45k-v1.onnx PGA/PGV regression CWA reports only 44,723
TDN-IntensityCLF-TW-524k-v1.onnx 10-class intensity P-Alert + CWA (merged) 523,569
TDN-IntensityCLF-TW-PAlert-479k-v1.onnx 10-class intensity P-Alert only 478,846
  • IntensityGMM predicts log10(PGA) and log10(PGV); the ONNX graph raises them back to linear units, so it outputs PGA (gal) and PGV (cm/s). Intensity follows from the CWA threshold table below.
  • IntensityCLF is a direct 10-way softmax over the CWA intensity scale and returns class probabilities. Useful when you want a calibrated distribution rather than a point estimate, and it recovers rare high intensities better than binning the regression output.

Quick start

import numpy as np
import onnxruntime as ort

sess = ort.InferenceSession("TDN-IntensityGMM-TW-524k-v1.onnx")

def features(M, depth, ev_lat, ev_lon, t_lat, t_lon):
    import math
    p1, p2, dl = math.radians(ev_lat), math.radians(t_lat), math.radians(t_lon - ev_lon)
    a = math.sin((p2 - p1) / 2) ** 2 + math.cos(p1) * math.cos(p2) * math.sin(dl / 2) ** 2
    dist = 2 * 6371.0 * math.asin(math.sqrt(a))
    lnR = math.log(max(math.hypot(dist, depth), 3.0))
    az = math.atan2(math.sin(dl) * math.cos(p2),
                    math.cos(p1) * math.sin(p2) - math.sin(p1) * math.cos(p2) * math.cos(dl))
    return [M, depth, dist, lnR, ev_lat, ev_lon, t_lat, t_lon, math.sin(az), math.cos(az)]

x = np.array([features(6.5, 10.0, 23.9, 121.6, 24.0, 121.7)], dtype=np.float32)
pga, pgv = sess.run(None, {"features": x})
print(float(pga[0][0]), "gal", float(pgv[0][0]), "cm/s")

A ready-made wrapper and CLI live in the repository (predict_point.py, palert/predict.py); a township-resolution ShakeMap renderer is in shakemap.py.

Inputs and outputs

Input features: float32[N, 10]. The feature order is fixed:

# name how to compute
0 M magnitude (ML)
1 depth focal depth (km)
2 dist epicentral distance (km), haversine
3 lnR ln(max(sqrt(dist^2 + depth^2), 3))
4, 5 ev_lat, ev_lon epicentre
6, 7 t_lat, t_lon target site
8, 9 sinAz, cosAz azimuth, epicentre -> site

Only dist, lnR and the azimuth depend on the target, so a whole ShakeMap is one batched call.

Output - IntensityGMM: PGA[N,1] (gal), PGV[N,1] (cm/s). IntensityCLF: intensity_probs[N,10].

Intensity (CWA 10-level scale) is the max of the PGA and PGV bins:

level 0 1 2 3 4 5弱 5強 6弱 6強 7
PGA (gal) 0.8 2.5 8 25 80 140 250 440 800 -
PGV (cm/s) 0.2 0.7 1.9 5.7 15 30 50 80 140 -

Class index i runs 0..9 in that order.

Training data

source network events station records period
P-Alert P波警報器強震網 (IES Academia Sinica / NTU), ~780 MEMS stations 696 478,846 2024-01-19 .. 2026-10-06
CWA reports 中央氣象署 顯著有感地震報告 (free-field strong motion) 1,088 44,723 2020-01-01 .. 2025-12-27
merged both 1,181 groups 523,569 2020-2025

Magnitudes 3.5-7.2, epicentral distances 0.4-570 km.

Labels. P-Alert: PGA/PGV from the public station records. CWA: per-station PGA/PGV from the published earthquake-report parameter files. Both give three components plus a combined value per station. The CWA threshold table above reproduces the intensity that the CWA itself printed in those reports for 98.5% of records, which is a useful sanity check on both the table and the parsing.

Cross-source event matching. The two catalogs describe overlapping earthquakes with different clock conventions (P-Alert is UTC, CWA reports are local time) and different id schemes. Events were matched one-to-one with tight tolerances (origin times within 60 s, epicentre within 0.2 deg, magnitude within 0.8), and the train/test split is grouped by matched event, so the two sources of a single earthquake never straddle the split. 603 cross-source pairs were matched. Looser tolerances chain aftershock sequences together and were rejected.

Training procedure

  • MLP 10 -> 256 -> 256 -> 256 -> 2 (SiLU), input standardisation baked into the ONNX graph, AdamW + OneCycle, 120 epochs, batch 8192.
  • Targets are log10(PGA) and log10(PGV) (roughly log-normal, so regression in log space).
  • Sample weights 1/sqrt(stations_per_event) so large events do not dominate.
  • Event-grouped split, 85% / 15%.
  • Classifier: same trunk, 10-way softmax, class weights 1/sqrt(count).

Evaluation

Event-grouped held-out splits. The splits are not identical across rows (different datasets, different held-out event counts), so compare within a dataset, not across the first two rows:

dataset model held-out PGA R^2 PGV R^2 intensity exact within +-1
P-Alert IntensityGMM 104 ev / 71,410 rec 0.777 0.741 0.756 0.985
P-Alert IntensityCLF 104 ev / 71,410 rec - - 0.743 0.984
CWA IntensityGMM 163 ev / 6,419 rec 0.698 0.723 0.705 0.988
merged IntensityGMM 177 ev / 82,282 rec 0.782 0.739 0.766 0.984
merged IntensityCLF 177 ev / 82,282 rec - - 0.761 0.984

R^2 is on log10; intensity exact is the share of records whose binned intensity matches the reference exactly.

Per-class recall (P-Alert split), showing why the classifier exists:

level n IntensityGMM IntensityCLF reference GMM
0 43,451 0.879 0.862 0.797
1 16,123 0.631 0.589 0.758
2 8,129 0.501 0.561 0.369
3 2,850 0.436 0.413 0.329
4 721 0.388 0.477 0.359
5弱 95 0.189 0.168 0.189
5強 26 0.231 0.000 0.038
6弱 13 0.077 0.769 0.000

Comparison with YuYu1015/YuYu1015-IntensityGMM-TW-45k-v1

Evaluated on the same P-Alert held-out split, with the identical feature definition:

model PGA R^2 PGV R^2 intensity exact within +-1
TDN-IntensityGMM-TW-PAlert-479k-v1 0.777 0.741 0.756 0.985
YuYu1015-IntensityGMM-TW-45k-v1 0.703 0.576 0.715 0.985

The reference's own train/test split is unknown, so treat this as a sanity check rather than a rigorous benchmark. Notably its "45k" matches the size of the CWA report corpus (44,723 records), so it was likely trained on the same CWA reports; our -CWA-45k- variant is the direct counterpart at that data scale, and the merged variant is what you get by scaling up ~12x.

Limitations

  • Intensity is binned, not modelled. The GMM predicts continuous PGA/PGV; the intensity label follows from fixed thresholds, so accuracy near a threshold flips on tiny changes. The classifier avoids this but is less accurate overall.
  • High intensities are rare. Levels 5弱 and above are 0.02% of the data, so tail accuracy is limited by data volume, not model capacity.
  • CWA reports only list felt stations (intensity >= 1), so the CWA-only variant never sees weak motion and its PGA/PGV range is compressed.
  • Site effects are not modelled. There is no Vs30, topography, basin or station-response term. Two stations at the same distance can differ by a factor of several; the model predicts the conditional mean.
  • Instrument differences. CWA free-field strong-motion sensors record higher acceleration than P-Alert MEMS sensors at the same site, so the merged model runs a little hot compared with the P-Alert-only model.
  • Taiwan only. Extrapolation to other regions, or to magnitudes above ~7.2, is untested.
  • Not for life-safety or alerting decisions.

Repository

TDN-IntensityGMM-TW-524k-v1.onnx          flagship regression model
TDN-IntensityGMM-TW-PAlert-479k-v1.onnx   P-Alert-only variant
TDN-IntensityGMM-TW-CWA-45k-v1.onnx       CWA-only variant
TDN-IntensityCLF-TW-524k-v1.onnx          flagship classifier
TDN-IntensityCLF-TW-PAlert-479k-v1.onnx   P-Alert-only classifier
README.md                                 this model card
LICENSE                                   Apache-2.0
.gitattributes .gitignore                 LFS rules, excludes regenerated data
shakemap.png                              example ShakeMap, merged flagship model
shakemap_palert.png                       same event, P-Alert-only model
checkpoints/                              PyTorch checkpoints + metrics JSON
data/                                     township centres + township boundaries for shakemap.py
                                          (county outlines for use_model.py's grid demo are not
                                          shipped; shakemap.py and use_model.py both degrade
                                          gracefully without them, or fetch them per the pipeline)
palert/                                   inference + feature + training helpers
predict_point.py                          self-contained single-point CLI
shakemap.py                               township ShakeMap renderer
use_model.py                              demo: single site, station ranking, ShakeMap
fetch_all.py  fetch_cwa.py  fetch_cwa_scweb.py     data download
merge_datasets.py                         merge P-Alert + CWA, event-matched
train.py  train_intensity.py               training
export_onnx.py  export_intensity_onnx.py   ONNX export
evaluate_onnx.py  compare.py               evaluation

The training datasets are not shipped - they are several hundred MB and subject to the source terms above. Rebuild them with the fetch scripts, or use the ONNX files directly; only shakemap.py --from-event needs the dataset, and --M/--depth/--ev-lat/--ev-lon covers the same ground without it.

pip install -r requirements.txt
python predict_point.py --M 6.5 --depth 10 --ev-lat 23.9 --ev-lon 121.6 \
                        --t-lat 24.0 --t-lon 121.7
python shakemap.py --M 7.1 --depth 19.7 --ev-lat 23.88 --ev-lon 121.57

Citation

Please cite the source datasets, which are what make these models possible.

Central Weather Administration (CWA)

以中央氣象署(CWA)強震觀測資料(2020–2025)訓練;震度門檻依 CWA 2020 十級制。

Central Weather Administration (CWA, Taiwan). (2012). Central Weather Administration Seismographic Network [Data set]. International Federation of Digital Seismograph Networks. https://doi.org/10.7914/SN/T5

P-Alert Strong Motion Network

梁文宗、邱昊德、李文蕙、古進上、楊民、吳逸民(2023)。2023年版P波警報器強震網的網路資料服務平台。台灣地震科學中心簡訊,第40期,0004。 doi: 10.30067/TECNL.202306_(40).0004

Liang, W.-T., Qiu, H.-D., Li, W.-H., Ku, C.-S., Yang, M., & Wu, Y.-M. (2023). The 2023 version of the P-Alert (P-wave alarm) Strong Motion Network online data service platform. TEC Newsletter, No. 40, 0004. https://doi.org/10.30067/TECNL.202306_(40).0004

The network itself is described in:

Wu, Y.-M., Chen, D.-Y., Lin, T.-L., Hsieh, C.-Y., Chin, T.-L., Chang, W.-Y., Li, W.-S., & Ker, S.-H. (2013). A High-Density Seismic Network for Earthquake Early Warning in Taiwan Based on Low Cost Sensors. Seismological Research Letters, 84(6), 1048-1054. https://doi.org/10.1785/0220130085

Note the DOI contains an underscore: TECNL.202306_(40).0004. It is sometimes reproduced without it, in which case it does not resolve.

Station coordinates included at data/raw/stations.json (787 stations) come from the same network's public station list, accessed through the platform described in the reference above.

Map data

shakemap.py needs township geometry; it is included so the renderer works out of the box. These files are map data, not training data - the models were not trained on them.

Township boundaries - data/twtown.geojson, the twtown2010.4 file (0.0001 degree simplification) from ronnywang/twgeojson. That project built it from the Taiwan Ministry of the Interior's Socio-Economic Geographic Information System (內政部國土資訊系統社會經濟資料庫共通平台, SEGIS), 2012 vintage / post-五都升格, and republished it as GeoJSON for the g0v community.

The upstream repository states its source but declares no explicit licence, so the terms of the original MOI/SEGIS data govern. Verify those terms before redistributing the geometry; for the model artifacts themselves nothing depends on it beyond drawing the figure.

Note the 2010 vintage: that file still says 桃園縣 and uses 市/鎮/鄉 where the 2020s say 桃園市/區. shakemap.py reconciles the naming at draw time (see its module docstring for the full list of differences).

Township centres - data/tw_town_centers.json: 371 township / city-district centres with postal codes, from the public gist memochou1993/aa9b6b1185221f88a03109f10d32e5e2.

Data-use statement

中文:

本研究之模型訓練與驗證資料,係採用由中央研究院與國立臺灣大學合作建置之 P-Alert 強震觀測網(梁文宗等,2023)開放資料庫。研究中自其提供之測站紀錄 提取各測站之最大地動加速度(PGA)與最大地動速度(PGV)作為迴歸標的,並以 地震規模、震源深度、震央座標與測站座標推得之震央距與方位角作為輸入特徵, 投入機器學習地震動模型(Ground Motion Model)進行 PGA 與 PGV 之預測,再依 中央氣象署震度分級表轉換為震度;另將中央氣象署顯著有感地震報告之各測站 PGA、PGV 與震度(2020–2025)併入同一訓練集。

English:

Training and validation data come from the open database of the P-Alert Strong Motion Network (Liang et al., 2023), jointly built by Academia Sinica and National Taiwan University. Per-station peak ground acceleration (PGA) and peak ground velocity (PGV) were taken as the regression targets, and event magnitude, focal depth, epicentral coordinates and site coordinates were reduced to epicentral distance and azimuth as input features, feeding a machine-learning Ground Motion Model; the CWA intensity scale is then applied. Per-station PGA, PGV and intensity from CWA significant-earthquake reports (2020-2025) were merged into the same training set.

Terminology note

"GMM" in this repository means Ground Motion Model, the engineering seismology term for a model predicting ground-motion intensity measures from source, path and site parameters. It is a neural network (MLP) here, not a Gaussian Mixture Model, which shares the same abbreviation in machine learning. Please keep the two apart when citing this work.

This model also does not process waveforms. P-Alert data were read through the network's public per-station PGA/PGV records, not extracted from SAC-format acceleration files, and no P-wave features (such as Pd or tau_c) are used.

This model

TDN Studio · walbcglgh1113 (2026). TDN-IntensityGMM-TW [Model]. https://huggingface.co/walbcglgh/TDN-IntensityGMM-TW

The repository TDN-Intensity-v1 hosts the model family whose artifacts are named TDN-IntensityGMM-TW-* (PGA/PGV regression) and TDN-IntensityCLF-TW-* (direct intensity classification). When you cite it, please also cite the data references above, and name the variant and version you used, for example TDN-IntensityGMM-TW-524k-v1.

License

Code and model weights are released under Apache-2.0. The training data is not redistributed here and remains subject to its source terms; cite the data providers as above.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support