On actual numbers for each of the 6 standard polling regions of the country, the model would have projected 168 Liberals, 114 Conservatives, 51 NDP, 4 Bloc and 1 Green. That is quite a bit better than the actual projection, but still farther away than had been the case in earlier elections (where misses with actual numbers tended to be around 5 seats for the main parties, rather than around 15).
Here's an analysis of what was off for each polling region. As you can see, there isn't much of a common thread across the country. The only issue that is somewhat recurring is that vote shares tend to move less in seats where a party has either very low or very high support (which makes sense: you can't drop by much if you're already really low, and you have fewer potential new supporters if you're already really high), and thus tend to move a bit more in other seats. Thus, the 2019 model will attempt to take this into account.
Projected Actual [Projection on actual popular vote, without ad hoc last-minute adjustments]
LIB - 26 (53.5%) 32 (58.7%) 
CON - 3 (21.1%) 0 (19.0%) 
NDP - 3 (20.2%) 0 (18.0%) 
GRN - 0 (4.2%) 0 (3.5%) 
In Atlantic Canada, the Liberals outperformed the polls. Moreover, the model included an adjustment based on historical results that had New Brunswick partly swinging with the rest of Atlantic Canada, and partly with Ontario. That backfired, as the Liberal swing in NB was actually similar to the swing in the rest of Atlantic Canada (and much higher than in ON). Finally, the Liberals gained more in tight ridings than in blowouts. Those gains were from both the NDP and Tories, so I don't see this as evidence of strategic voting.
Lessons: Simply model NB with the rest of Atlantic Canada. If a party is gaining in a region and has extremely high support in some ridings, further gains in those ridings may be smaller - and thus, gains in other ridings may be larger and bring more seats.
NDP - 31 (26.3%) 16 (25.3%) 
LIB - 26 (30.1%) 40 (35.6%) 
CON - 11 (20.5%) 12 (16.8%) 
BQ - 10 (19.4%) 10 (19.4%) 
GRN - 0 (2.6%) 0 (2.3%) 
In Québec, the Liberals again outperformed the polls. Note that here, with actual results, the projection would actually have given them too many seats! The Bloc did exactly as I projected, but the model would have given it too few seats had the actual percentages been used for other parties.
The reasons why the model would have been pretty off even with actual vote percentages are a bit complicated. In the 450 area, the Bloc lost less support than the model expected while the NDP lost more. In the 514 area, the NDP held up better than expected, while the Liberals gained less. Put these together, and you have the Bloc winning more seats than expected, and the Liberals winning fewer.
Also, in the Quebec City area, the Conservatives did much better than expected (making big gains relative to 2011 while actually sliding in the rest of the province) at the expense of everyone else.
Lessons: Perhaps the smaller changes in the 514 could be picked up by a model with regional elasticities as the 514 vote often moves less than the rest of Québec. But I'm not sure how it would have been possible to project what happened in the 450 and the Quebec City area without access to regional polling breakdowns...
LIB - 71 (44.3%) 80 (44.8%) 
CON - 36 (34.3%) 33 (35.0%) 
NDP - 14 (16.7%) 8 (16.6%) 
GRN - 0 (3.7%) 0 (2.9%) 
In Ontario, the polls were pretty much bang on, at least after my pro-CPC turnout adjustment! The seat projection, though, was too charitable to the NDP, who didn't resist as well as expected. The problem was almost entirely in Toronto and Northern Ontario. Was it strategic voting in these strong NDP/Liberal areas? The Liberals targeting smartly? Or was it simply that the NDP had more votes to lose?
The model did very well in the rest of the province. An adjustment based on regional breakdowns from polls amplifying the swing in the 905 area (from Tories to Liberals) helped, as raw uniform swing would have left the Tories with too many seats (around 40).
Lesson: Assuming somewhat proportional swing, rather than uniform swing, would have helped predict bigger NDP drops in Toronto and Northern Ontario.
CON - 17 (41.7%) 15 (43.0%) 
LIB - 5 (32.6%) 8 (34.4%) 
NDP - 6 (20.7%) 5 (19.1%) 
GRN - 0 (4.1%) 0 (2.7%) 
In the Prairies, the polls did well too. The Liberals picked up 3 more seats than the model expected, all in the Winnipeg area. In those 3 seats (and nowhere else in MB/SK), the Liberals outperformed the projection by more than 10 points! And this didn't really look like strategic voting as the gains were from both the Tories and the NDP.
In fact, the Liberals overperformed across the board in MB, and underperformed across the board in SK, while it was the reverse for the Conservatives. Not exactly sure why - the provincial Tories were quite popular in MB at the time. The Liberals usually get more votes in MB than SK, but the gap has exploded: ~4% in 2006 and 2008, ~8% in 2011, ~21% in 2015. The Tories went from just 3% more in SK than MB in 2011 to 11% more in 2015. Perhaps SK went from "more like MB" to "more like AB" due to its resource boom?
Lesson: Not sure... This looks like a case of two provinces no longer moving together politically, but unfortunately lumped together in most polls.
CON - 32 (56.3%) 29 (59.6%) 
LIB - 1 (24.4%) 4 (24.6%) 
NDP - 1 (15.0%) 1 (11.6%) 
GRN - 0 (3.3%) 0 (2.5%) 
The story is pretty straightforward and intuitive in AB: Liberals support picked up more in cities, which is where they had a chance of winning seats.
Lesson: Here, the proportional model would have worked better if you looked at the Liberal number. But it would have worked worse if you looked at the Conservative number: Tory support dropped more in ridings where they were already weaker. So really, the lesson is that a party's support moves most when it's neither too high nor too low.
CON - 20 (32.1%) 10 (30.0%) 
NDP - 11 (25.1%) 14 (25.9%) 
LIB - 10 (32.8%) 17 (35.2%) 
GRN - 1 (8.9%) 1 (8.2%) 
In BC, the Liberals slightly outperformed the polls, at the expense of the Conservatives. The bigger issue, though, was that the model was way too generous to the Conservatives seat-wise. Here, we have perhaps the patterns most suggestive of strategic voting and/or excellent targeting by Liberals/NDP. The Liberals way underperformed uniform swing in Vancouver Island and the Kootenays, where it is weaker than the NDP, and somewhat exceeded it elsewhere. Where Liberals underperformed, the Greens were the main beneficiaries EXCEPT in tight NDP-Conservative races, where the NDP benefited. This helped the NDP win/solidify seats on Vancouver Island and the Kootenays.
The above paragraph also means that the Liberals overperformed elsewhere, which helped the Liberals win seats. That alone does not, however, explain why the Liberals gained so many extra seats. It appears that the far suburbs of Vancouver (seats like Mission--Matsqui--Fraser Canyon, Pitt Meadows--Maple Ridge and Cloverdale--Langley City) swung especially strongly toward the Liberals.
Also, on the basis of regional breakdowns from polls, I had the NDP being weaker than uniform swing on Vancouver Island, to the benefit of the Greens. As it turns out, while this was correct for the Greens, it was wrong for the NDP - it was the Liberals that undershot there. This was significant as it made the model incorrectly give two NDP seats to the Tories. I also made an adjustment based on a riding poll that incorrectly shifted a seat from the Liberals to the Tories.
Finally, the model did not account for James Moore leaving politics and the Greens not running in Kelowna--Lake Country, both of which likely added seats to the Liberals.
So, in short, uniform swing would have been somewhat off in BC, perhaps due to strategic voting. Moreover, counterproductive inclusion of regional breakdown/riding polls, as well as idiosyncratic riding-level factors, happened to push in the same direction. As a result, the model was frankly embarrassingly inaccurate in BC.
Lesson: Not sure how to guard against inaccurate regional breakdowns, other than ignoring them. But then again regional breakdowns elsewhere (e.g. in Québec) would have been so useful! Other than that, it looks like strategic voting might have been a substantial phenomenon in BC.