Predictive layer
Where is crime likely to happen next?
CityCrimeMap publishes a machine-learning-based predicted risk overlay on every city map. It highlights the small share of city blocks where reported incidents are most likely to concentrate in the near future.
On San Francisco the model's top 10% of city cells captures roughly 59% of reported incidents — a PAI of 5.92 against a random baseline of 1.0.
How the model works
- Grid the city into small square cells. For dense cities we use 300 m cells; for smaller cities 200–250 m so the map has visible contrast. A typical US city ends up with somewhere between 5,000 and 15,000 grid cells.
- Compute a smoothed density of past incidents per cell. This is a kernel density estimate (KDE) — a standard statistical technique for turning a scatter of points into a continuous surface. We rescale it (log-transform, normalize) so the machine-learning model can actually learn from it.
- Train a random forest model to predict the incident count per cell in a held-out future window, using the KDE feature plus each cell's coordinates and lagged counts. Random forests are ensemble models built from hundreds of decision trees; they're a well-established baseline for spatial prediction because they handle non-linearities and sparse features gracefully.
- Show only the top 10% of cells by predicted risk. Cells with zero predicted risk are dropped entirely so the GeoJSON payload stays small.
The methodology is a machine-learning adaptation of Risk Terrain Modeling, published in Wheeler & Steenbeek (2021), Journal of Quantitative Criminology. Our full implementation is open source at tidycop-hotspots (MIT).
What the numbers mean
We publish the Predictive Accuracy Index (PAI) for every city we cover. PAI = (share of incidents captured) ÷ (share of area used). A PAI of 1.0 means the model is no better than picking cells at random; 2.0 means it's twice as good; 3.0+ is a strong lift. It's the standard metric in the predictive-policing academic literature.
Concretely, if the top 10% of San Francisco cells has a PAI of 4.6, that means those cells together contain about 46% of the reported incidents in the held-out test window — almost 5× what you'd get by guessing.
| City | PAI @ 10% | Verdict | Train set | Grid |
|---|---|---|---|---|
| San Francisco, CA | 5.92 | excellent lift | 1001 rows | 32 cells · 300 m |
| Boston, MA | 4.88 | excellent lift | 833 rows | 43 cells · 200 m |
| Seattle, WA | 4.87 | excellent lift | 965 rows | 45 cells · 300 m |
| Providence, RI | 4.74 | excellent lift | 450 rows | 19 cells · 200 m |
| Gainesville, FL | 4.46 | excellent lift | 349 rows | 22 cells · 250 m |
| Washington, DC, DC | 4.45 | excellent lift | 667 rows | 38 cells · 300 m |
| Minneapolis, MN | 4.38 | excellent lift | 883 rows | 44 cells · 300 m |
| Hartford, CT | 4.32 | excellent lift | 859 rows | 28 cells · 250 m |
| Pittsburgh, PA | 4.00 | very strong lift | 1094 rows | 39 cells · 300 m |
| Denver, CO | 3.66 | very strong lift | 1002 rows | 57 cells · 300 m |
| Cleveland, OH | 3.44 | very strong lift | 1006 rows | 51 cells · 300 m |
| Baltimore, MD | 3.20 | very strong lift | 1002 rows | 57 cells · 300 m |
| Los Angeles, CA | 3.06 | very strong lift | 1002 rows | 64 cells · 500 m |
| Indianapolis, IN | 2.52 | very strong lift | 951 rows | 74 cells · 300 m |
| Detroit, MI | 2.51 | very strong lift | 1001 rows | 67 cells · 300 m |
| Kansas City, MO | 2.10 | strong lift | 1001 rows | 40 cells · 300 m |
| Dallas, TX | 1.92 | strong lift | 1214 rows | 63 cells · 400 m |
| Houston, TX | 1.79 | strong lift | 1017 rows | 78 cells · 300 m |
| Rochester, NY | 1.68 | strong lift | 191 rows | 15 cells · 250 m |
| Chicago, IL | 1.51 | strong lift | 1002 rows | 79 cells · 300 m |
| Cincinnati, OH | 1.09 | modest lift over random | 207 rows | 16 cells · 250 m |
| New Orleans, LA | Predictive layer not enabled for this city yet. | |||
Sorted by PAI, best model first. Training sets are short right now (a few hundred rows per city) because we're only ingesting the last ~45 days. Longer training histories are on the roadmap and will improve every one of these numbers.
What the model does not do
We're deliberately narrow about what the predictive layer is for. It's a research-backed tool for public awareness, not a policing product.
- It predicts places, not people. The model outputs a risk score for a 300-meter grid cell. It does not identify individuals, license plates, faces, or any person-level attribute. Predictive policing systems that target individuals have a troubling accuracy and civil-liberties record; we don't build those.
- It inherits the biases of the underlying data. Reported crime data reflects both real crime and where policing looks. Neighborhoods with more police presence tend to have more reported incidents even at the same true crime rate. The risk overlay inherits that bias. We flag it explicitly instead of hiding it.
- It's not real-time. The city portals we ingest lag the real world by days to weeks. If you want notifications about crimes reported near a specific address right now, use SpotCrime's free daily email alerts.
- Short training windows produce noisy models. Cities with sparse data score close to — or below — the random baseline right now. That's honest: with 200 rows to train on, you can't learn much.
Compared to other crime maps
Most public crime maps show only historical dots. That's useful for a look-back but doesn't tell you where risk concentrates going forward. To our knowledge, CityCrimeMap is the only free, open-source, city-agnostic crime map that ships a peer-reviewed predictive layer.
- Community Crime Map (LexisNexis): historical dots only. No forecasting.
- CrimeMapping.com: historical dots only. No forecasting.
- Nextdoor: user-reported anecdotes. No data model, no verification.
- SpotCrime: best-in-class historical maps and free alerts. No public predictive layer.
- CityCrimeMap: historical map + predicted-risk overlay + open-source methodology + honest validation metrics.
See predictions for your city
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
See predicted risk →
Have questions about the model? Read the full methodology page, the FAQ, or file an issue on GitHub.