<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Daniel Wilson on Medium]]></title>
        <description><![CDATA[Stories by Daniel Wilson on Medium]]></description>
        <link>https://medium.com/@harenil?source=rss-508d054415bc------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*uBr3MIwvx2bqsQtyBzk-Hw.jpeg</url>
            <title>Stories by Daniel Wilson on Medium</title>
            <link>https://medium.com/@harenil?source=rss-508d054415bc------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 03:16:59 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@harenil/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Jupyter Notebooks Made Me A Lazy Programmer…]]></title>
            <link>https://medium.com/data-science/jupyter-notebooks-made-me-a-lazy-programmer-bef237c310bf?source=rss-508d054415bc------2</link>
            <guid isPermaLink="false">https://medium.com/p/bef237c310bf</guid>
            <category><![CDATA[jupyter]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[jupyterlab]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Daniel Wilson]]></dc:creator>
            <pubDate>Mon, 22 Oct 2018 12:01:01 GMT</pubDate>
            <atom:updated>2018-11-03T00:21:44.095Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XgObFNgx5ETslRA5SBZJtA.png" /><figcaption>Don’t try this at home.</figcaption></figure><h4>…and not in the right way</h4><p>Like most data scientists and machine learning practitioners, I use Jupyter Notebooks to prototype, perform data analysis, and communicate my results to other team members, upper management, customers, and stakeholders. Jupyter is fantastic for this, yet somehow after some time coding in notebooks almost exclusively, I found my coding abilities starting to slip. After a while, I found myself picking up bad habits.</p><p>Often times I’d find myself copying and pasting large code blocks that I could easily reuse or tossing random imports wherever I needed them. This is fine if you’re just hacking something together, but when it comes time to present your code or assemble into a full demo or solution, you’re left scrambling to assemble your fragments into something resembling a sophisticated predictive model developed by a so-called machine learning “expert”.</p><blockquote>What happens to the result if you change X to Y and run it?</blockquote><p>We’ve all heard it. You’re giving a live demonstration after proudly stating you can run your model on the fly and generate results right before their eyes! Never mind that you just spent the previous 6 hours polishing your plots, tables, and other visualizations to effectively communicate your results. Since you’ve designed your model in a notebook, the code may very well be fragmented and not well generalized to handle the question. Sometimes this is unavoidable, but I’ve found that I’ve been in this situation more than once, and come out with less credibility as a result. We’ve all been there (…right?)</p><p>It’s not notebooks that I have a problem with, not by a long shot. Notebooks rock. I think back to why I started using notebooks in the first place. Bear with me here, there’s a point to all of this.</p><p>I was working on a machine that acted as a gateway to my team’s YARN cluster and a farm of other virtual machines that I developed on. For my early career I had used many different IDEs and text editors to develop my code and models. Now I was working within an environment where doing this was challenging. I quickly became fast friends with <em>vim</em>. Vim is everywhere and it’s much more powerful than most people realize.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yuULAuPlfcBR7MdtBJ5eJw.png" /><figcaption>vim — it actually doesn’t suck.</figcaption></figure><p>This was an entirely different issue. I quickly began to become a vim power user and found myself more productive than I had been before! My coding abilities improved and soon I found myself churning out new algorithms all the time, being able to jump from system to system without having to reconfigure my development environment at every turn. I was unstoppable…</p><p>…or so I thought. Even though I could write a lot of scripts and code to produce visualizations, tables, or write to out database, without the embarrassment of being asked to code in the middle of a demo. Even then, I was forced to think before I coded — to design my model before I wrote it. This left with with a TON of reusable design patterns I could use to build effective models. This grew my power exponentially and I assembled this code into libraries that I could call on a whim. Now my scripts were a mere pocketful of lines, yet lending insight that had taken me hundreds in the past. Mastering vim had made me lazy — in a good way! I had reached data science nirvana, but I was still missing something.</p><p>Somehow everything felt too rigid. Furthermore, I was working only on remote machines. It got really annoying copying exported images from matplotlib visualizations back to my root computer to view results, finicky X-forwarding, or relying on the larger infrastructure and it limitations. No, I wanted freedom again. I wanted my code to feel like I was working on a single machine once again, where I could just pop up a plot window and close it when I was done or wanted to continue program execution. Furthermore, I wanted to expose some of the data wrangling and algorithm capabilities I had codified into my precious libraries to our end users, some of which were data scientists themselves.</p><p>Enter Jupyter. Wow, as soon as I got my first Jupyter environment set up and running through a proxy I was hooked. I could access it from any gateway machine. Now I could even log directly into my environment from any machine and run interactive code. I could even do this right on a stakeholder’s machine and show them what I was doing with their data. It felt amazing. Soon my team had gotten Jupyter hub running within our environment. I could still develop my structured code and libraries on our virtual machines by using my old friend vim, but could rapidly prototype new algorithms using Jupyter. What could go wrong?</p><p>Well, as happens to most of us at some point, I changed jobs. I was working on new machines now. My old code? Inaccessible, in the hands of my former colleagues and completely out of sight for me. Oh well, on to bigger and better things!</p><p>I had learned a lot from my previous job, and I wanted to move forward with my acquired knowledge. I immediately went into developing a new model, this time I started in Jupyter notebooks. Quickly I found myself with messy code, fragmented notebooks. Don’t even get me started on scope issues! Then people started asking me to share my work with them. Uh oh, people will all see my gross code! Quickly I found myself cutting corners and taking shortcuts to get things running and simple, but at least I was productive again. My notebooks were self sufficient and able to be run top to bottom to fully explain my process and model.</p><blockquote>Why do you keep scrolling through so much code? I just want to see the results.</blockquote><p>Chances are, if you have demoed from a notebook before you’ve heard this, or at least something similar. And they’re right — most people don’t care about your code, so while showing it is nice for data scientists, it’s not so great for customers, you know, the guys that help you get paid?</p><p>Enter reveal.js. This changed the way I wrote notebooks! I could click a little tab and hide my code from the presentation. Want to show my code? It’s pretty simple to toggle on and off.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/591/1*9tSk2U-WOtYbUlGktsNvWw.png" /></figure><p>I still found myself falling back on lousy coding habits. I couldn’t find a balance between good coding practices and writing for re-usability and the agility that Jupyter provides. Essentially, because I wasn’t forced to think it through, I didn’t. <strong>I had become a lazy coder</strong>. Sure, I was effective, but I was still embarrassed by my code. Sometimes ugly code is important — we data scientists sometimes need to churn out a model, the beauty of the code be damned. If only there was a way to let notebooks be for quick prototyping, yet somehow hide my code when sharing my notebooks. I wanted to have demo-able notebooks, without having to twiddle a bunch of knobs and hide code to make it presentable. I needed something else. I needed…</p><p>…JupyterLab! JupyterLab was like a gift from the gods for me. Not only could I quickly hack together notebooks, I could copy and paste my classes and functions directly into text files in the very same web based environment. This got me planning again. Somehow just having text files editable alongside made notebooks made everything different. Not only editors though; lab gives you access to terminals. But wait, there’s more!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/595/1*4c1Ky12o3Cc50OS_DVx96A.png" /></figure><p>I got my vim back. Well, partly. It at least has the same key bindings that became muscle memory over the years. Of course, I had it all along, but now I have it alongside my beloved notebooks. Something still is missing though. I hate light themes. Notebooks is light by default, and only by installing a third-party extension can you switch to a dark them. There’s nothing wrong with that, unless you don’t have access to your Jupyter notebooks server that you’re using. JupyterLab has multiple dark themes for the text editor and a dark theme for lab as a whole.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WYkL4m2wSEy0jB9cmFfOEg.png" /></figure><p>Beautiful. What I have settled on (for now!) is a workflow where I rapidly iterate. If I find myself writing something that has no place in a demonstration, I stash it elsewhere and reference the file or library from my notebook. This now feels so much nicer than what I was doing before, and I’m just scratching the surface here. If you love notebooks, but find yourself falling into similar traps as me, give JupyterLab shot — I bet you’ll love it.</p><p>In summary:</p><ul><li>Keep your <em>real</em> code separate from your notebook, unless you’re writing a coding tutorial. This will give you much cleaner notebooks an getting in the habit of separating things will make you much more productive. Future you will thank you.</li><li>Think before you write. That will avoid having to hack something together on the spot to answer a question. Being able to run on the spot is part of the power of Jupyter, use it!</li><li>Use JupyterLab. Seriously, it’s amazing.</li><li>Have fun!</li></ul><p>*The opinions expressed in this article are my own, and not necessarily the same as my employer.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bef237c310bf" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/jupyter-notebooks-made-me-a-lazy-programmer-bef237c310bf">Jupyter Notebooks Made Me A Lazy Programmer…</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using Machine Learning to Predict Car Accident Risk]]></title>
            <link>https://medium.com/geoai/using-machine-learning-to-predict-car-accident-risk-4d92c91a7d57?source=rss-508d054415bc------2</link>
            <guid isPermaLink="false">https://medium.com/p/4d92c91a7d57</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[geoai]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[gis]]></category>
            <category><![CDATA[xgboost]]></category>
            <dc:creator><![CDATA[Daniel Wilson]]></dc:creator>
            <pubDate>Thu, 03 May 2018 17:03:20 GMT</pubDate>
            <atom:updated>2018-05-04T19:21:05.702Z</atom:updated>
            <content:encoded><![CDATA[<p><em>This article reflects some of the work we are doing at Esri to define spatially focused artificial intelligence and machine learning, however: The opinions in this article are my own, and not necessarily the opinions of my employer. This article is intended to be a simple technical introduction to one application of geo-spatial machine learning, not a fully mature solution. There’s a lot of excitement and some great, truly innovative work going on at Esri. I’m very excited to be a part of it!</em></p><p>Car accidents are a huge problem in our world. Nearly 1.3 <em>million</em> people die internationally every year from car accidents and in addition up to 50 million people are injured (<a href="http://asirt.org/initiatives/informing-road-users/road-safety-facts/road-crash-statistics">ASIRT</a>). <strong>Can machine learning help save lives?</strong> I believe the answer is yes, and this article details one possible approach.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oM17vZ6J_U9vJO89x6skjQ.png" /><figcaption>End result: an accident risk heat map</figcaption></figure><p>Many governments collect accident records and make these data <a href="https://crashmapping.utah.gov/">publicly available</a>. In addition, numerous road infrastructure data sets. We will make use of publicly available <a href="https://gis.utah.gov/data/transportation/roads-system/">road infrastructure data</a> and <a href="https://www.ncdc.noaa.gov/data-access">weather feeds</a> to attempt to predict accident risk per road segment, per hour within the state of Utah using supervised machine learning.</p><p>(<strong><em>Disclaimer: I’m using a slightly different accident data set that goes back to 2010, but isn’t available online</em></strong>)</p><h4>Our Approach</h4><p>We pose the car accident risk prediction as a classification problem with two labels (accident and no accident). It could equally be posed as a regression problem (number of accidents), but on our timescale (one hour) we don’t expect to see more than one accident per road segment so this simplifies the problem a bit. There are of course other approaches, but this is the one we take here. Commonly traffic is modeled by a Poisson or Negative binomial model. Choosing a small road segment and time interval allows us to treat each observation as a Bernoulli random variable (and thus use a cross-entropy loss function as the objective)</p><p>We can use the seven years and roughly half a million car accident records as our positive examples. You might then ask, you have positive labels, where are your negative labels? Great question! Every single road segment/hour combination is a possible negative example. Over 7 years and 400,000 discrete road segments, this amounts to roughly 24.5 BILLION potential negative examples.</p><p>Machine learning practitioners will notice an issue here, namely, class imbalance. SEVERE class imbalance. Essentially, if we were to use all of this data to train a model, our model would be heavily biased towards no accidents. This is a problem if we want to estimate accident risk.</p><p>To counter this problem, we instead don’t use all 24.5B negative examples, instead we take a sampling approach that will be detailed later in this article.</p><h4>Data Exploration</h4><p>What do nearly half a million accidents look like?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*kPHIDVKJiD4d4HqAPpjMBw.png" /><figcaption>That’s not a picture of the roads: this is just a heatmap of car accidents</figcaption></figure><p>Anyone who commutes definitely understands the impact of time on car accidents. We can visualize what this looks like for 7 years of accidents on the following chart:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/756/1*tSWHzN7kG0N1jZFXMQTQzg.png" /></figure><p>This follows our intuition: accidents are occurring mostly on weekday afternoons during peak rush hour. Another observation by looking at the vertical cross section is that accidents tend to peak in the December/January time-frame. Utah has frequent heavy snow and ice during this time so this is certainly not unexpected. This highlights the importance of good weather data as an input to this model. Utah sees about 15 accidents on an average day at the peak of rush hour.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1Xi-RNN--rtw4_U5Jr1Twg.png" /><figcaption>Exploration of some of the data using ArcGIS Pro</figcaption></figure><h4>The inputs?</h4><p>Now that we know what we want to predict, what are the inputs? What could cause a car accident. The answer, of course, is numerous factors, some of which we include in this analysis.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/616/1*wn408a8BDBAXcJRBVtD5ag.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/520/1*M3LG3LLLBjgg9EaFIhaHSQ.png" /><figcaption><strong>Left:</strong> Accidents typically cluster around intersections, particularly signalized ones. <strong>Right:</strong> Accidents happening more frequently in curvy road segments</figcaption></figure><ul><li>Weather (temperature, wind speed, visibility, rainy/snowy/icy, snow depth, rain depth, etc)</li><li>Time features: hour of day, day of the week, month of the year, solar azimuth/elevation</li><li>Static features such as speed limit, road curvature, average traffic volumes, proximity to intersections, road north/south/east/west alignment, road width, road surface type, etc</li><li>Human factors such as population density and distractions such as billboards</li><li>Graph derived features of the road network such as centrality and flow</li><li>Countless others</li></ul><p>This is where the geospatial portion of this analysis becomes important. This is inherently a spatial problem and our machine learning model needs to take into account many different geospatial data sources and their relationship with each other. This will include many geoprocessing operations, which can be computationally expensive. For this purpose, I’m using the ArcGIS platform.</p><p><strong><em>(Disclaimer: I’m an Esri employee, but I came from an open source geo background. You can definitely perform most of this analysis without using ArcGIS, but it will be more challenging. If you aren’t an ArcGIS user, I still highly recommend taking a look at the </em></strong><a href="https://developers.arcgis.com/python/"><strong><em>ArcGIS API for Python</em></strong></a><strong><em>, if only for the data wrangling capabilities as much of this data is available from various ArcGIS based services. The developers of this API have taken care to fallback on many open source utilities, such as shapely when ArcGIS isn’t available. A spatial database such as PostgreSQL with PostGIS will go a long way.)</em></strong></p><p>There are really two distinct parts of the inputs: the static features and the dynamic features.</p><p>The static features are the parts of the input data that, for the most part, do not change with time. This includes features derived from the road geometry, such as curvature or other properties, such as speed limit or population density. Of course, these aren’t <em>static</em> per say, but they are slowly changing so we can treat them as constant for all intents and purposes.</p><p>The dynamic features change depending on when we are making the prediction. These are the weather feeds, solar geometry, and time variables (hour, month, day, etc).</p><p>We need to compute all of these features for each road segment, of which we have around 400,000. We scripted this process using the <a href="http://pro.arcgis.com/en/pro-app/arcpy/get-started/what-is-arcpy-.htm">Arcpy</a> Python library included with ArcGIS Pro. Let’s take a look at an example of that really quick:</p><pre>billboards_url = &#39;<a href="https://maps.udot.utah.gov/arcgis/rest/services/FI_Mandli2012/MapServer/2&#39;">https://maps.udot.utah.gov/arcgis/rest/services/FI_Mandli2012/MapServer/2&#39;</a></pre><pre># Calc proximity to billboard<br>_ = arcpy.analysis.Near(&#39;centerlines_merged&#39;,<br>                        billboards_url)<br>_ = arcpy.management.CalculateField(&#39;centerlines_merged&#39;,&#39;proximity_to_billboard&#39;,&#39;!NEAR_DIST!&#39;)<br>_ = arcpy.management.DeleteField(&#39;centerlines_merged&#39;,[&#39;NEAR_DIST&#39;,&#39;NEAR_FID&#39;])</pre><p>The above code snippet used the “Near” tool to find the proximity to the nearest billboard for every road in our centerlines data. We computed numerous proximity based features to form our static feature dataset.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9r8DZj17lqhNliAiz0P3Rw.png" /><figcaption>Proximity to billboards. This feature captures some possible driver distractions, but also represents heavily traveled areas because advertisements are intended to be seen by a large audience.</figcaption></figure><p>We also had to derive features from the road geometries themselves. For example to estimate road curvature we used “sinuosity” as the metric. Sinuosity is the ratio between the path length and the shortest distance between the endpoints. Again, using Arcpy, we calculated this:</p><pre># Calc Sinuosity<br>code_block = \<br>&#39;&#39;&#39;<br>import math<br>def getSinuosity(shp):<br>    x0 = shp.firstPoint.x<br>    y0 = shp.firstPoint.y<br>    x1 = shp.lastPoint.x<br>    y1 = shp.lastPoint.y</pre><pre>euclid = math.sqrt((x0-x1)**2 + (y0-y1)**2)<br>    length = shp.length<br>    if euclid &gt; 0:<br>        return length/euclid<br>    return 1.0<br>&#39;&#39;&#39;<br>_ = arcpy.management.CalculateField(&#39;centerlines_merged&#39;,&#39;sinuosity&#39;,&#39;getSinuosity(!Shape!)&#39;,code_block=code_block)</pre><p>Let’s talk about weather now. There are many different weather feeds but we chose to use a reliable hourly weather source from NOAA. We have a handful of weather stations, but we need to know the weather at each road segment. One approach is to interpolate the weather at the surface stations to the individual road segments. To do this, we can use a technique known as “kriging” in the geostatistics community or Gaussian process regression in the machine learning community. ArcGIS has a built in “empirical Bayesian kriging” tool in the geostatistics toolbox that contains a robust implementation of this technique that uses an empirical prior distribution based on the data and removes a lot of the parameter twiddling. If this isn’t an option for you, there are other techniques such as inverse distance weighting or simple spatial joins (I did this initially for simplicity’s sake). If you have other data to estimate more precisely how geography affects weather features (such as elevation or more sophisticated climate models), you could load those into a geographically weighted regression model to gain even more accuracy.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uX8FuuDXMChsxPJu9CStOw.png" /><figcaption>Temperature interpolated between weather stations</figcaption></figure><p>In summary, there are numerous spatial operations performed to construct a useful feature set for accident prediction. These features will then be used to create a training set for the supervised machine learning model.</p><h4>Building the training set</h4><p>With the geospatial processing completed, we can turn our attention to actually building the training set. For this we use the ArcGIS Python API, pandas, and a few other miscellaneous Python libraries. Most of this is standard data wrangling, but a critical piece of any of this working is the creation of negative samples; that is, what are counter examples to when accidents occurred.</p><p>One approach is to randomly sample some number of roads/times when accidents didn’t occur, but this has some shortfalls. There are a lot of times and roads when accidents simply do not occur often, but the much more important problem to solve is differentiating accident vs not on roads where accidents happen frequently. What is it that causes accidents?</p><p>We chose to use a sampling approach that builds up a set of negative examples that are very similar to our positive examples so that the machine learning model can learn to find the fine differences between when there is and isn’t an accident. Of course, there’s an element of randomness to it as well so we also sample situations that are very different. The approach is as follows:</p><ol><li>Randomly select an accident record from positive examples</li><li>Randomly alter: the road segment, the hour of the day, or the day of the year.</li><li>If the new sample isn’t with in the accident records, add to the list of negative samples</li><li>Repeat until we have a large number of negative samples (a few times the number of positive samples)</li></ol><p>This gives us a training set that is challenging to work with because it’s very hard to tell the positive and negative examples apart. This isn’t an issue — this is a difficult problem and we’re not concerned with making our numbers look good, we care about practical results. This is a commonly used approach for situations such as this.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/652ee5815bbc0fb49b101367cf6cfa12/href">https://medium.com/media/652ee5815bbc0fb49b101367cf6cfa12/href</a></iframe><p>As shown in the above gist, categorical variables such as hour, weekday, and month are one-hot encoded. All continuous variables are transformed to z-scores using the scikit-learn StandardScaler. We also transform the sinuosity with a logarithmic transform since most values are near 1 and we want to pick up more on the small difference than the large ones (long windy roads).</p><h4>The Model</h4><p>My go to machine learning approach is <a href="https://en.wikipedia.org/wiki/Gradient_boosting">gradient boosting</a>, particularly with the <a href="http://xgboost.readthedocs.io/en/latest/">XGBoost</a> library. The approach builds upon a very intuitive machine learning concept called a decision tree. Decision trees work by finding splits on different features that separate the labels. Unfortunately, decision trees have a tendency to over-fit to a training set, meaning they don’t generalize to new data, which is a crucial part of a predictive model. Gradient boosting works by combining the results from many different decision trees together and is extremely fast and powerful. Gradient boosting often times outperforms other approaches for many different problems and should be in any data scientist’s toolbox. XGBoost is a particularly good implementation of gradient boosting. We also trained other models, including a deep neural network, but found that not only did gradient boosting give the best overall performance (ROC AUC), it gave us more insight into why decisions where made. It should be noted that the deep neural network we built achieved higher recall at equal precision, but the curve was steep and the ROC AUC was a little smaller.</p><p>I won’t go into detail on the hyperparameter optimization and training, but here are the final model choices:</p><pre>params = {<br>    &#39;max_depth&#39;:6,<br>    &#39;min_child_weight&#39;: 5.0,<br>    &#39;reg_lambda&#39;: 1.0,<br>    &#39;reg_alpha&#39;:0.0,<br>    &#39;scale_pos_weight&#39;:1.0,<br>    &#39;eval_metric&#39;:&#39;auc&#39;,<br>    &#39;objective&#39;:&#39;binary:logistic&#39;,<br>    &#39;subsample&#39;:0.8,    <br>    &#39;eta&#39;:0.3<br>}</pre><p>We trained until convergence with 10 rounds of early stopping, achieving a final ROC AUC of around 0.828 on a holdout set. The final model had 80 trees.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/389/1*8i5_vxl2vvvlzR1chQh98Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/389/1*CoL1pdRvQ8X_4MBCZ3lKuw.png" /><figcaption>ROC Curve and Precision-Recall Curve</figcaption></figure><p>With a threshold of 0.19, we get the following performance characteristics:</p><pre>Test Accuracy: 0.685907494583<br>Test F1: 0.461524665975<br>Test Precision: 0.311445366528<br>Test Recall: 0.890767937497<br>Test AUC: 0.828257459986<br>Test AP: 0.388845428164<br>Train Accuracy: 0.68895115694<br>Train F1: 0.466528546103<br>Train Precision: 0.314947399182<br>Train Recall: 0.899402111551<br>Train AUC: 0.836489144112<br>Test AP: 0.410456610829</pre><p>Like I said earlier, we intentionally made the training set difficult to separate because we wanted the results to reflect the true performance of the model. The recall value of 0.89 means we are able to predict nearly 90% of car accidents, and the precision value of 0.31 means we are correct about those predictions about 30% of the time. It’s not perfect, but it’s a great start and definitely tells us something about our ability to predict accidents. There are numerous things we can do to improve the performance of this model, and perhaps I’ll revisit this in a future post.</p><h4>Some Results</h4><p>Great, now we have a model that achieves decent performance, what can we gather about how this model makes predictions? What features are used? What values are important to consider?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CiB3HFuHi1GLetkwQrGUpg.png" /><figcaption>XGBoost Feature Importance (How often do they appear in a tree to make decisions?)</figcaption></figure><p>You can see from the above plot that solar position and temperature are most important. There are several reasons why these are important features. Temperature acts as a proxy variable to things that are difficult to measure. For instance temperature has a relationship to the season and time of day during the season. It also tells us how likely the roads are to be icy.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/372/1*cYu47lniH84UlJWnKa8NkQ.png" /><figcaption>Notice a large peak around 0 Celsius</figcaption></figure><p>Obviously solar position tells us time of day and season, but it also allows us to model an interesting factor: is the sun in driver’s eyes? Let’s take a look at the split histogram for both solar elevation and road orientation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/372/1*1MqVw45pXL2PfI69uRy1PQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/372/1*g0Txu30sA0cYpd1pr7r6mg.png" /><figcaption><strong>Left:</strong> Notice the peak around 0 degrees elevation? This is near sunrise. <strong>Right: </strong>There are peaks at both 90 degrees and 0/180 degrees, but the peak at 0/180 degrees is higher. This indicates that east/west roads are more often used by the model to make a determination.</figcaption></figure><p>Going down the list we notice population density, accident_counts, proximity_to_billboard, proximity_to_signal are important features. These certainly make sense from our analysis. You may notice hour, weekday, and month are broken into multiple features through one-hot encoding. If we aggregate the importance from each hour, they actually make up a large contribution to the model. Less common weather features, such as icy (not often reported in our weather feed) and hailing appear in the model, but not as useful for making predictions.</p><p>What about the temporal performance of our model? Can it make predictions over time?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/880/1*Zwm6nsN_h0rC_nNU1v1nTg.png" /><figcaption>It’s not perfect, but for the most part we’re doing a good job. We were fairly far off around Feb 25th, but that was a particularly icy/snowy day and there wasn’t enough weather information to make that determination.</figcaption></figure><p>Keep in mind that this is not a time series model, we are simply estimating the expected counts for all road segments and aggregating them. We perform a mean/variance adjustment to the resulting time series since we had a training set biased towards accidents.</p><p>Finally, let’s take a look at the resulting model spatially.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-hO3BwLEti9CPd4XQkUeeA.png" /><figcaption>Generated Risk Map vs Real Accidents: A particularly icy hour/day in December. Only one of these accidents occurred on a low risk segment.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zalTOp77EGjmC22DR-m-7g.png" /><figcaption>Same hour, different area. This time all accidents occurred on high risk segments.</figcaption></figure><p>You’ll notice from the above graphics that there are plenty of places we’re predicting as high risk, but there are no accidents there. We are attempting to quantify risk using this model, but accidents are still a random occurrence. We believe with more features, especially real time traffic information, construction, important events, higher resolution weather, <em>etc.</em> that we can improve this model significantly, but it seems good for a first start.</p><h4>Why do we care?</h4><p>We built a decent model to predict accident risk, but what can we do with it? There are numerous possible applications, including the following that we have considered for applications:</p><ul><li>Safe route planning</li><li>Emergency vehicle allocation</li><li>Roadway design</li><li>Where to place additional signage (e.g. to warn for curves)</li></ul><p>Some engineers at Esri took this example and built a prototype safe routing app! It’s a pretty cool concept, take a look at it <a href="https://community.esri.com/groups/applications-prototype-lab/blog/2018/04/02/routing-around-future-accidents">here</a>.</p><p>That’s all I have today, thank you for reading! Have a better approach? Are we doing something poorly? Post in the comments below!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4d92c91a7d57" width="1" height="1" alt=""><hr><p><a href="https://medium.com/geoai/using-machine-learning-to-predict-car-accident-risk-4d92c91a7d57">Using Machine Learning to Predict Car Accident Risk</a> was originally published in <a href="https://medium.com/geoai">GeoAI</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>