<?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 Jeshua Bratman on Medium]]></title>
        <description><![CDATA[Stories by Jeshua Bratman on Medium]]></description>
        <link>https://medium.com/@nojeshua?source=rss-2a37a4a6293d------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*QZ1f8uKiTxLODD9TIK8d3A.png</url>
            <title>Stories by Jeshua Bratman on Medium</title>
            <link>https://medium.com/@nojeshua?source=rss-2a37a4a6293d------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 29 May 2026 18:20:19 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@nojeshua/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[Calibrating Classifiers in Reality]]></title>
            <link>https://medium.com/abnormal-security-engineering-blog/calibrating-classifiers-in-reality-82f7bdf1ac90?source=rss-2a37a4a6293d------2</link>
            <guid isPermaLink="false">https://medium.com/p/82f7bdf1ac90</guid>
            <category><![CDATA[ml-engineering]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Jeshua Bratman]]></dc:creator>
            <pubDate>Mon, 24 Jan 2022 16:50:02 GMT</pubDate>
            <atom:updated>2022-01-25T22:22:06.529Z</atom:updated>
            <content:encoded><![CDATA[<p><em>This post also appears on the </em><a href="https://abnormalsecurity.com/blog/calibrating-classifiers-in-reality"><em>Abnormal Blog</em></a><em>.</em></p><p>Abnormal’s fundamental job is to detect malicious emails like phishing and business email compromise attacks and other malicious events, such as suspicious sign-ins that indicate an account has been hacked. To do so, we have a complex web of features, sub-models, and classification models that decide on whether an event is malicious or not. Once we’ve built a model we must turn it into a classifier by selecting a threshold. This sounds easy, but there are many tricky details.</p><p>We’ll focus on the email attack detection case for this discussion and simplify it down to the core classification problem. The general approach is straightforward; we want to start with a probabilistic model <strong><em>M(X) </em></strong>that predicts attack probability given our features X.</p><p><strong>M(X) = P(attack | X)</strong></p><p>Other articles on this blog discuss this attack model itself (<a href="https://medium.com/abnormal-security-engineering-blog/combining-ml-models-to-detect-email-attacks-e1b4d1f2d14e">here</a>, <a href="https://medium.com/abnormal-security-engineering-blog/lessons-from-building-ai-to-stop-cyberattacks-7d593250989c">here</a>, and <a href="https://medium.com/abnormal-security-engineering-blog/re-scoring-an-ml-detection-engine-on-past-attacks-part-1-2845fd9f09f6">here</a>), so we won’t discuss that in this article. Here we are interested in what happens after we’ve built a model.</p><p>Once we have a probabilistic model, we could easily build an attack detector using thresholding to define a decision boundary.</p><p><strong>predict <em>attack</em> if M(X) &gt; threshold</strong></p><p>Such a classifier would have nice properties. For example, the precision will equal the threshold, and the recall is recoverable from a precision/recall curve. This property would allow us to easily trade between precision and recall for our business needs by sliding a threshold up and down. This is important because our clients are sensitive to both false positives and false negatives so tuning our detectors precisely is crucial to maintain a high-quality product.</p><p>But there’s a problem: In reality, we rarely find that trained models produce accurate probabilities. This is a problem of miscalibration<strong>.</strong> We will delve into the cause of this miscalibration in a bit, but usually, it is due to a combination of the learning algorithm (i.e. neural nets may not produce probabilities) and, more importantly, skewed data and labels distributions in the training dataset<strong><em>. </em></strong>But first, let’s focus on why miscalibration is a problem for an ML product.</p><p>As we said, the model does not line up to the probability distribution:</p><p><strong><em>M(X) ≠ P(attack | X)</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/996/1*mdZHr01YC-N8bp05qakgnQ.png" /></figure><p>We assume the model is still correlated with probability, if it is a good model. When it is not a probability, it throws off our thresholding strategy. Imagine we create a classifier as before:</p><p><strong>predict <em>attack</em> if M(X) &gt; threshold</strong></p><p>This threshold no longer lines up to an expected precision, and therefore, we must tune thresholds to meet desired performance characteristics. To appreciate why this is not ideal in practice, take Abnormal’s use case. We are carefully tuning our detectors to prevent email attacks. Often we may need to move a false positive rate from X% to Y%. To do so, we must go back to our data and solve for the right threshold. If we want to build simple control knobs or even an automated control system, we do not want to require this manual translation from the desired performance to a threshold.</p><p>In practice this caused some big issues, primarily:</p><ol><li>For each new model, we needed to carefully tune thresholds. This made it very hard to compare model A to model B on an even playing field. AUC gives one evaluation but tends to evaluate outside the operating range and we need more precise evaluations at particular thresholds. This difficulty slowed down our experimentation and pace of launching new models</li><li>We needed to control thresholds separately for each client for each model. As our client base grew, this became increasingly problematic. We knew we had to either better bake the client particulars into the model directly or somehow set thresholds automatically from data.</li></ol><p>The ideal solution is to calibrate our model by adding an extra layer to do this translation automatically:</p><p><strong>Calibrator(M(X)) = P(attack | X)</strong></p><p>A common approach is to use a regression from the model scores to an empirical probability to estimate the true probability on a calibration dataset (we’ll call this <strong><em>CalibrationDataset)</em></strong><em>. </em>If we do have a good calibration dataset, a common approach is to build a simple regression function, for example, isotonic regression, to re-map into probability space.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*vgA1dx072TBQFCBu" /></figure><p>The idea of isotonic regression is to partition the range of the model’s predictions into N buckets. For each bucket, estimate the expected ratio of positive to negative class, then draw a line between the buckets. There are many approaches to improve this by drawing a smoother function between the points instead of piecewise linear as depicted. For example, you could interpolate with linear regression or splines. These are simple details, but the difficult part is producing the <strong>CalibrationDataset</strong> on which this all depends.</p><p><strong>Sources of Error in Calibration Data</strong></p><p>As we discussed above, to calibrate a classifier (or train a model that is predicting probability correctly in the first place) we need to produce a dataset that is distributionally equivalent to the true probability of the online production system. Let’s imagine we have some true probability distribution of attacks.</p><p><strong>P_true(attack|features)</strong></p><p>At Abnormal, we know our training data is quite different from this distribution. One reason for this is that we heavily subsample negative examples (safe emails) and additionally use many positive examples (attack emails) from different time ranges. This is because we want to include the history of all attacks in our models, but we cannot include the history of all safe messages due to the enormity of the data. We have 100000x or more safe emails than attacks since the base rate is very low.</p><p>Additionally, we do not want to force ML engineers to attempt to produce a representative distribution every time they train a model. It may slow down iteration or cause other issues due to missing data, the need to experiment with filtering functions, etc. Instead, we prefer to train uncalibrated models and then fix them afterward with calibration.</p><p>That leaves us with the same problem, how do we produce a <strong>CalibrationDataset </strong>drawn from the true distribution?</p><p>First, let’s enumerate some types of distributional errors we commonly encounter:</p><ol><li><strong>Sampling distributional errors.</strong> The most obvious errors are from how we sample the positive and negative examples. We may select only 10% of negative samples since they are so prevalent.</li><li><strong>Label distributional errors.</strong> We do not and cannot label every message in a dataset. This means any calibration dataset will be only partially labeled.</li><li><strong>Client distributional errors.</strong> At Abnormal we have many different clients in different industries and particular characteristics. While there are other potential complicating variables, the client is a particularly impactful variable. We may have a distribution on some clients that do not translate to new clients. Ideally, as our models learn more across a larger sampling of clients this issue will continue to lessen but it must be taken into account.</li><li><strong>Data quality distributional errors.</strong> We may also have fundamental differences in feature values in our calibration dataset due to engineering data quality (for example some features may not be possible to backstate for certain samples).</li><li><strong>Time distributional shifts.</strong> Any calibration dataset will be earlier in time than the distribution on which we will be applying the model. There are fundamental time-based shifts due to naturally changing email traffic. Additionally, due to the adversarial nature of the problem, we expect the attack distribution patterns to change as adversaries evolve their strategy.</li></ol><p><strong>Attempting to Correct for These Errors</strong></p><p>It’s important to understand each of these possible sources of error and think through others if necessary. Once we understand the errors, we can build correction mechanisms. Ideally, we also produce small datasets that help us evaluate how much our correction methods succeed in this task. If we can correct each error source, we can ideally produce a good calibrator.</p><p>Here are some high-level ideas on how to correct for each error</p><p><strong>Correcting for sampling errors. </strong>This can be done by understanding the exact mechanism used to sample in the first place and reversing it. As a simple example, if we uniformly sampled 10% of the negative class, any statistic of that dataset will have probabilities shifted by a factor of 10 and we can shift them back.</p><p><strong>Correcting labeling error.</strong> For various reasons we cannot and do not label an entire dataset, but we can control exactly what we do and do not label within a dataset. We can use the labels selection criterion (i.e. how we choose which data to label in the first place) and sample (i.e. weigh labeled samples above unlabeled ones) weighting to help correct errors caused by unlabeled samples in a dataset.</p><p><strong>Correcting per-client error. </strong>We can manually learn marginal distributions for a customer and shift our calibrator to make up for these. Or if we want to get more sophisticated we can attempt to model clients through some featurization (for example the client’s industry or size) and learn marginal distributions across those features.</p><p><strong>Correcting data quality error. </strong>This error is easy to measure as we can compare distributions of model scores and features between our online system and historical batch data and then use that measurement to shift our distribution as needed.</p><p><strong>Correcting time distributional shifts.</strong> This is the hardest to correct for. One possibility is to attempt to model the shift with a time series model. Another method is to monitor and correct for distributional shifts with an online system measuring drift over time. Going into details here would be a blog post in its own right.</p><h3>Engineering an Imperfect Solution</h3><p>Unfortunately, even after significant work on this problem attempting to correct all these errors, we failed to produce a perfect all-around calibrator. Too many distributional errors persisted.</p><p>This sort of setback is common in ML engineering. Rather than give up, we instead thought creatively. We asked the question: <strong>Do we actually need a calibrated classifier?</strong></p><p>Well, yes and no. A calibrated classifier is sufficient, but not necessary. That is, could we loosen the requirements? To answer this question, we listed out the actual desiderata for our classifier:</p><ol><li><strong>Calibration matters only in a specific operating range. </strong>In reality, the model only needs to make good predictions at very high precision, and we care much less about calibration lower down in the PR curve because we are only remediating attacks for which we are quite confident, as almost all emails are safe. This is the key insight.</li><li><strong>Score stability property.</strong> The range of scores emitted by a classifier should be relatively stable across clients and across versions of the trained model. For example, we would like the score of 0.95 to mean roughly the same thing when we roll out a new model or on a newly onboarded client. Also, the score should be smooth: moving a threshold by some amount should smoothly affect the volume of flagged messages and the precision. If we have a stable score, we can more easily build systems on top of the model, such as a control system.</li><li><strong>Ranking property. </strong>Perhaps obvious, but the calibrator needs to generally rank messages from least likely to most likely to be attacks. That is, it should have a high AUC.</li></ol><p>Simplifying the problem made it more tractable. We ended up building a calibration system that has the following properties:</p><ol><li>Calibration is correct at about 0.95 precision.</li><li>Performance is not well calibration below this point, but it is relatively stable between clients and on new versions of the model.</li><li>Very low scores are uncalibrated and we do not trust the model much at all below low confidence predictions. Luckily, we rarely worry about performance low in the curve because we are using this classifier only to predict the positive attack class.</li></ol><p>Below is an illustration of stabilized predictor and how it might match up to the ideal calibrated predictor in some places and not others.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/575/0*8TGNISdUF9kydnmR" /></figure><h3>Conclusion</h3><p>Once we developed this calibration method, it made many tasks easier. Before calibration, we had to manage thresholds very carefully across clients and between models. Now, there is a single threshold to control for each model and this threshold is stable from one model to another and one client to another. For example, 0.95 means the same thing between models.</p><p>This has increased development speed and made it much easier to run experiments. Trusting this calibration method has also removed many moving parts an ML engineer must think about when comparing one model to another.</p><p>Key takeaways include:</p><ol><li>Start with a theoretical framework for a problem, but don’t be afraid to cut corners and simplify this framework to make progress. For example, the key insight that our model only needs to be calibrated at the top scores helped dramatically simplify the problem.</li><li>Reducing degrees of freedom helps with productivity. In our case, manually controlling thresholds per client or for new models could eke out slightly better performance, but sticking to a fixed calibration method and a single threshold allows easier progress because the ML engineer then does not need to think about the calibration problem for every model on top of the core feature and model improvement tasks.</li><li>There are many steps beyond the model itself to build a good product on top of ML. Do not focus solely on getting the best AUC, also think about managing thresholds, running experiments, iteration, and so on.</li></ol><p>If these problems interest you, <a href="https://abnormalsecurity.com/careers/">check out our open opportunities</a> because we’re hiring!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=82f7bdf1ac90" width="1" height="1" alt=""><hr><p><a href="https://medium.com/abnormal-security-engineering-blog/calibrating-classifiers-in-reality-82f7bdf1ac90">Calibrating Classifiers in Reality</a> was originally published in <a href="https://medium.com/abnormal-security-engineering-blog">Abnormal Security Engineering Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Abnormal Engineering Stories — Episode #2: Future of ML Platform]]></title>
            <link>https://medium.com/abnormal-security-engineering-blog/abnormal-engineering-stories-episode-2-future-of-ml-platform-edc0d1c8034b?source=rss-2a37a4a6293d------2</link>
            <guid isPermaLink="false">https://medium.com/p/edc0d1c8034b</guid>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[mlops]]></category>
            <category><![CDATA[ml-engineering]]></category>
            <category><![CDATA[ai-infrastructure]]></category>
            <dc:creator><![CDATA[Jeshua Bratman]]></dc:creator>
            <pubDate>Wed, 07 Jul 2021 18:54:58 GMT</pubDate>
            <atom:updated>2021-07-07T18:54:58.271Z</atom:updated>
            <content:encoded><![CDATA[<h3>Abnormal Engineering Stories — Episode #2: Future of ML Platform</h3><h3><strong>Future of ML Platform w/ Jeshua Bratman &amp; Nico Koumchatzsky</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Vhli1GkKRN-nPH5p7PvDTA.png" /></figure><p>Over the last three years building our ML-based cybersecurity products at <a href="https://abnormalsecurity.com/">Abnormal Security</a>, I’ve benefitted enormously from discussions with colleagues in the ML space. This podcast aims to make some of those conversations available.</p><p>In our second episode of Abnormal Engineering Stories, <a href="https://www.linkedin.com/in/nicolaskoumchatzky/">Nico Koumchatzky</a> and I discuss the future of ML platform, what it means to be an ML Engineer, and the ML challenges faced at Abnormal and Nvidia. Nico is the Senior Director of AI Infrastructure at Nvidia, and before that, he ran Twitter’s ML Platform team, “Twitter Cortex,” where he and I worked together.</p><p>This discussion includes:</p><ul><li>A wide-ranging and enjoyable discussion on the current and future state of ML platform with analogies to the history of software engineering</li><li>The role of the “ML Engineer” and why any successful ML practitioner needs to have one foot in the software engineering world (code, IDEs, databases, services, etc.) and the other foot in the machine learning world (experimentation, data science, algorithms, etc.)</li><li>Challenges we are trying to solve in our organizations including stopping cybercrime (at Abnormal) and building a platform to enable fast and large-scale ML and autonomous vehicles (at Nvidia)!</li></ul><p>We hope you enjoy it! Please do subscribe on <a href="https://podcasts.apple.com/us/podcast/abnormal-engineering-stories/id1568611449">Apple</a>, <a href="https://open.spotify.com/show/54BU7chbU8DBbnH4GT8JhS">Spotify</a>, or <a href="https://podcasts.google.com/feed/aHR0cHM6Ly9hYm5vcm1hbGVuZ2luZWVyaW5nLmxpYnN5bi5jb20vcnNz">Google Podcasts</a>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=%2F%2Fhtml5-player.libsyn.com%2Fembed%2Fepisode%2Fid%2F19735922%2Fheight%2F90%2Ftheme%2Fcustom%2Fthumbnail%2Fyes%2Fdirection%2Fforward%2Frender-playlist%2Fno%2Fcustom-color%2F88AA3C%2F&amp;display_name=Libsyn&amp;url=https%3A%2F%2Foembed.libsyn.com%2Fembed%3Fitem_id%3D19735922&amp;image=https%3A%2F%2Fassets.libsyn.com%2Fsecure%2Fcontent%2F106906229&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=libsyn" width="600" height="90" frameborder="0" scrolling="no"><a href="https://medium.com/media/9dace40f0f7fe2eb6b7928e998ee6293/href">https://medium.com/media/9dace40f0f7fe2eb6b7928e998ee6293/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=edc0d1c8034b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/abnormal-security-engineering-blog/abnormal-engineering-stories-episode-2-future-of-ml-platform-edc0d1c8034b">Abnormal Engineering Stories — Episode #2: Future of ML Platform</a> was originally published in <a href="https://medium.com/abnormal-security-engineering-blog">Abnormal Security Engineering Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Podcast: Building Applied ML Startups]]></title>
            <link>https://medium.com/abnormal-security-engineering-blog/podcast-building-applied-ml-startups-147a582c34c5?source=rss-2a37a4a6293d------2</link>
            <guid isPermaLink="false">https://medium.com/p/147a582c34c5</guid>
            <category><![CDATA[podcast]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <dc:creator><![CDATA[Jeshua Bratman]]></dc:creator>
            <pubDate>Fri, 02 Jul 2021 14:24:29 GMT</pubDate>
            <atom:updated>2021-07-02T14:24:29.582Z</atom:updated>
            <content:encoded><![CDATA[<p>It was a pleasure sitting down with <a href="https://www.linkedin.com/in/ACoAABZaGrIBY0lP_5YpmXAllwsuv2G1e4ohwto">Tim Shi</a> of Cresta and <a href="https://www.linkedin.com/in/ACoAAAeAfuoBDKXC0V04hGue9NQr0Y1SChy5jNI">Saam Motamedi</a> of <a href="https://www.linkedin.com/company/greylock-partners/">Greylock</a> to discuss building companies around machine learning technology!</p><p>It’s one thing to add machine learning and artificial intelligence to existing software, but it’s quite another to build a company with ML at its core like both <a href="https://www.linkedin.com/company/abnormalsecurity/">Abnormal Security</a> and <a href="https://www.linkedin.com/company/cresta-inc/">Cresta</a>. In this podcast episode, we discuss common hurdles we face building these companies especially cold start problems, and the importance of customer partnerships early on.</p><p>Listen here:</p><p><a href="https://greylock.com/greymatter/practical-innovation/">Practical Innovation | Greylock</a></p><p>You have to be very flexible. When starting a company, you really want to solve the problems that the customers have and not just go and do data science off in a void, but at the same time, these are tough machine learning problems that cannot be solved without careful algorithm and data design.</p><p>If solving hard ML and engineering problems for stopping cyber-attacks interests you, yes Abnormal is hiring! Please message me if curious to learn more and see open roles at <a href="https://lnkd.in/ePwUxhi">https://lnkd.in/ePwUxhi</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/1*e22d2R3tIscEbeNYauc-6w.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=147a582c34c5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/abnormal-security-engineering-blog/podcast-building-applied-ml-startups-147a582c34c5">Podcast: Building Applied ML Startups</a> was originally published in <a href="https://medium.com/abnormal-security-engineering-blog">Abnormal Security Engineering Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How you Should Design ML Engineering Projects]]></title>
            <link>https://medium.com/data-science/how-you-should-design-ml-engineering-projects-9af1930a4e2b?source=rss-2a37a4a6293d------2</link>
            <guid isPermaLink="false">https://medium.com/p/9af1930a4e2b</guid>
            <category><![CDATA[project-management]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[ml-engineering]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Jeshua Bratman]]></dc:creator>
            <pubDate>Tue, 06 Apr 2021 00:11:10 GMT</pubDate>
            <atom:updated>2021-04-06T00:11:10.693Z</atom:updated>
            <content:encoded><![CDATA[<h4>Analysis of ML engineering lifecycles, common pitfalls, and a copy-and-paste template you can use.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*woimC2Qs8kAMpNNNJfczyA.png" /><figcaption>Image source: <a href="https://pixy.org/author/Christopher_Lague/">Christopher Lague</a> on <a href="https://pixy.org/9039/">pixy</a></figcaption></figure><p>Machine learning engineering is hard, especially when developing products at high velocity (as is the case for us at Abnormal Security). Typical software engineering lifecycles often fail when developing ML systems.</p><p>How often have you, or someone on your team, fallen into the endless ML experimentation twiddling paralysis? Found ML projects taking two or three times as long as expected? Pivoted from an elegant ML solution to something simple and limited to ship on time?<em> If you answered yes to any of these questions, this article may be right for you.</em></p><p><strong>Purpose of this article:</strong></p><ol><li>Analyze why software engineering lifecycles fail for ML projects</li><li>Propose a solution with an<strong> accompanying design document template</strong> to help you and your team more effectively run ML projects</li></ol><h3>Software and Data Science Project Lifecycles</h3><p>Typical software engineering projects are about developing code and systems. They might go something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/985/1*gVhUj0pAHg71CZNM1a-ZQA.png" /><figcaption>(1) identify a product or infrastructure problem (2) discuss and design the software system to solve the problem (maybe with a <a href="https://www.forbes.com/sites/forbescommunicationscouncil/2020/09/24/ten-leadership-strategies-to-crawl-walk-run-your-way-to-success/?sh=5f1879763372">crawl/walk/run</a>) (3) break the problem into pieces and implement over the course of days, weeks, or months often using agile development processes (4) push into production and monitor (5) go back to the beginning of the cycle to improve the system as necessary (Image by Author)</figcaption></figure><p>This lifecycle is clearly not what happens for ML engineering projects. What about data experimentation? What about model training and evaluation?</p><p>Maybe we should look toward data science research projects and see if their lifecycle is more suited.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J6qXIE6BEYQt73ugH0kdWw.png" /><figcaption>A data science research project might go like this:<strong> </strong>(1) identify a question that can be answered with data (2) design experiments (3) wrangle data (4) evaluate hypotheses with data analysis or modeling (5) publish results or trained models. (Image by Author)</figcaption></figure><p>This lifecycle doesn’t seem right either. Pure data science research projects are about answering questions and not about building systems. What’s the middle ground?</p><h3>Machine Learning Engineering</h3><p>Machine learning engineering is at a unique crossroads between data science and software engineering. ML engineers will have trouble operating in a software engineering organization if you try to force everyone to operate in the typical software development lifecycle. On the other hand, operating a machine learning team like a pure data science or research team will result in nothing getting shipped to production.</p><p>ML engineers can get frustrated when they commit to a project that requires experimentation. When they inevitably have false starts because data does not support their initial hypothesis or because wrangling the data is much more difficult than anticipated, they start falling behind committed timelines. This sense of falling behind results in a feeling that a crucial part of their job — i.e., experimentation — feels like a constant failure compared to their colleagues working on software engineering tasks.</p><p><strong>A typical ML Engineering lifecycle goes as follows:</strong> (1) identify a problem (2) design software and experiment <em>(these are interconnected because the models you may plan to implement will depend on which experiments work out, but you may need to design feature and model code to run your experiments in the first place)</em> (3) implement code and wrangle data<em> (these may be interconnected because you may need to implement software to get the data you need and you may need the data to write and test the feature extraction or model training code)</em>(4) Analyze data, train models, evaluate results (5) publish results (6) test, deploy, and monitor code and models.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TvNnBocmAczJxXoFYrRloQ.png" /><figcaption>Typical ML Engineering lifecycle. The better the software design and experimental design, the less re-visiting required because a good design will anticipate the branches that may need to be taken. (Image by Author)</figcaption></figure><p>This ML engineering lifecycle is often invented on the job and not taught. It is possible to do very well by carefully laying out software and experimental design. Still, it is also easy to do poorly, leading to many false starts and winding paths toward a solution (that may never be reached).</p><h3>Junior ML Engineers vs Senior ML Engineers</h3><p>In a fantastic article by <a href="https://joulee.medium.com/">Julie Zhuo</a>, she illustratively compares <a href="https://medium.com/the-year-of-the-looking-glass/junior-designers-vs-senior-designers-fbe483d3b51e">Junior Designers vs. Senior Designers</a> — this visualization aptly pertains to Junior and Senior ML Engineers as well</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5A-2AHoNf0HuXtjKrTTo-A.png" /><figcaption>Process for Junior ML Engineer. Often they will meander through the space of implementations, experiments, and data without a clear method. This wastes time and can be frustrating. (Image by <a href="https://joulee.medium.com/">Julie Zhuo</a>, used with permission)</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VKBUcHES2SvYqpezfJc1Dw.png" /><figcaption>Process for Senior ML Engineer). Senior ML engineers will carefully lay out experimental paths, know when to cut them short, and proceed in more fruitful directions as well as know when one result indicates new directions to go. (Image by <a href="https://joulee.medium.com/">Julie Zhuo</a>, used with permission)</figcaption></figure><p>Methodical thinking and discipline are a must when iterating on experiments. Can we help ML engineers plan out work to follow this paradigm?</p><h3><strong>Design documents to aid ML Engineering Lifecycles</strong></h3><p>How can we encourage better ML engineering design?</p><p>A process we’ve implemented at Abnormal is to require all ML Engineering projects to go through a<strong> </strong>formal design review process using a design document template that helps the engineer do good software and experiment design simultaneously.</p><p><strong>What should be encouraged when designing ML Engineering projects?</strong></p><ol><li>Put the work into explicit forward-thinking experiments before rushing into implementation. This heads off the endless and fruitless ML/Data experimentation/twiddling experiment iterations we all find ourselves in from time to time.</li><li>Call out the *work* of experimentation as useful whether or not the experiment validates the hypothesis. There is value to disproving a hypothesis even if it does not lead to ML product improvements.</li><li>Design software with experiments in mind and design experiments with software in mind (i.e., what is capable of shipping to production). Wrangle your data in light of the systems you will be building and how that data will be available in production.</li></ol><p>With these in mind, we created this template to fill out at the start of any ML engineering project. An engineer should copy this template, fill in the details for their project, then presents the software and experimental design to the team for feedback and iteration. This process has greatly improved the success and velocity of projects, and we highly encourage adopting this design template (or something similar) for your ML Engineering team.</p><p>— — — — — — — — — — — — — — — — — — — — — — — <br>Abnormal Security’s ML Design Document Template<em> (to copy and fill in at the start of a new ML Engineering project). Feel free to use directly, modify and share!</em></p><h3>Problem Statement</h3><p><em>What are we specifically trying to solve, and why are we solving it now? A strong justification will tie this back to a product or customer problem.</em></p><h3>Goals</h3><p><strong>Software goals</strong></p><p><em>Describe the software system we wish to build and its capabilities.</em></p><p><strong>Metric goals</strong></p><p><em>Desired metric improvement, how are we going to measure the impact of this work, why do we want to improve the system in this way:</em></p><ul><li><em>Bad Example: Improve model’s performance</em></li><li><em>OK Example: Improve AUC by X% for the model</em></li><li><em>Good Example: Improve recall by X% for the class of false negatives without decreasing recall for any other classes by more than Y%.</em></li></ul><p><em>Expected metrics tradeoffs, if any: For example: Increase recall without decreasing precision by more than 5%.</em></p><h3>Experiment Design</h3><p><em>Unlike pure software projects, data science / ML projects often require data exploration, experimentation, failure, and changing design along the way when data has been collected. To help make a project successful, it is helpful to layout your potential branching points and how you will make decisions along the way. Additionally, all experiments should be evaluated against a baseline which is either a simple solution to the problem (simple algorithm, simple heuristic) or the current production solution if one exists.</em></p><h4>Data motivation</h4><p><em>Describe the problem that should be solved, use data to validate that this is indeed a worthy problem to solve. Is this actually going to have a real impact?</em></p><h4>Hypotheses</h4><p><strong>Hypothesis 1: </strong><em>method A will improve metric B by X% over baseline</em></p><p><strong>Method:</strong> <em>Describe the methodology you are approaching. For example, this might be a model architecture we are testing, a new feature we are adding, etc.<br></em><strong>Metric: </strong><em>Describe the metric or metrics we will use to evaluate the method.<br></em><strong>Success criteria: </strong><em>The measured metric results that will indicate success in this hypothesis. Ideally should be measured against a baseline.<br></em><strong>Timebox: </strong><em>X days, then check in with the team to decide the next steps<br></em><strong>Failure Next Steps: </strong><em>For example, go on to try Hypothesis 2<br></em><strong>Success Next Steps:</strong> <em>For example, push this model to production.</em></p><p><strong>Hypothesis 2: …<br></strong><em>The same set of questions for each hypothesis</em></p><p>…</p><h3>Software Design</h3><p><em>Describe the software systems and data pipelines needed to execute this project. What software needs to be built? What services and databases? What data will need to be available in production to run your model? Feel free to use normal software design documentation principles here.</em></p><h4>Execution</h4><p><em>What will be delivered and when will it be delivered. A strong plan will provide incremental value and will allow us to get to the crawl state quickly.</em></p><p><strong><em>Crawl: </em></strong><em>Minimum design to prove the efficacy of change before we invest too much time in software development.</em></p><p><strong><em>Walk: </em></strong><em>More thorough design aimed to be a relatively complete component.</em></p><p><strong><em>Run:</em></strong><em> Long-term design here; how would we make this a really first-class system or model.</em></p><h3>Considerations</h3><h4>Success criteria to launch?</h4><p><em>Describe metrics evaluated to advocate launching this model or change into production.</em></p><h4>What could go wrong?</h4><p><em>Describe all possibilities that might go wrong when we launch this?</em></p><ul><li><em>Which product surfaces could be affected?</em></li><li><em>How will this impact customers?</em></li><li><em>How will we monitor?</em></li><li><em>What will we do to roll back?</em></li></ul><h4>Security &amp; Privacy Considerations</h4><ul><li><em>What impact on security could this change have?</em></li><li><em>What impact on privacy could this change have?</em></li></ul><h3>Appendix: Experiment log</h3><p><em>Keep track of the results of each hypothesis tested and the decisions made along the way, branching points, learnings, revised hypothesis, and so on. It’s beneficial to remind yourself later and share how you approach this type of problem with others on the team.</em></p><p>— — — — — — — — — — — — — — — — — — — — — — —</p><p><em>This template has evolved over the years. Thank you to Dmitry Chechik, Yu Zhou Lee, Kevin Lau, Umut Gültepe, and Abhijit Bagri for all the input on this design process over time.</em></p><p>If you are interested in fascinating Applied ML engineering in the cybersecurity space, yes, <a href="https://abnormalsecurity.com/careers/">we’re hiring</a>!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9af1930a4e2b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/how-you-should-design-ml-engineering-projects-9af1930a4e2b">How you Should Design ML Engineering Projects</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[Re-Scoring an ML Detection Engine on Past Attacks (part 1)]]></title>
            <link>https://medium.com/abnormal-security-engineering-blog/re-scoring-an-ml-detection-engine-on-past-attacks-part-1-2845fd9f09f6?source=rss-2a37a4a6293d------2</link>
            <guid isPermaLink="false">https://medium.com/p/2845fd9f09f6</guid>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[data-engineering]]></category>
            <category><![CDATA[startup]]></category>
            <dc:creator><![CDATA[Jeshua Bratman]]></dc:creator>
            <pubDate>Mon, 29 Mar 2021 18:40:12 GMT</pubDate>
            <atom:updated>2021-06-18T20:46:53.533Z</atom:updated>
            <content:encoded><![CDATA[<p>Developing a machine learning product for cybersecurity comes with unique challenges. For a bit of background, Abnormal Security’s products prevent email attacks (think phishing, business email compromise, malware, etc.) and also identify accounts that have been taken over. These attacks are clever social engineering attempts launched to steal money (sometimes in the millions) or gain access to an organization for financial theft or espionage.</p><p>Detecting attacks is hard! We’re dealing with rare events: as low as 1 in 10 million messages or sign-ins. The data is high dimensional: all the free-form content in an email and linked or attached in an email. We require bleedingly high precision and recall. And, crucially, it is adversarial: attackers are constantly trying to outsmart us.</p><p>These factors have consequences for our ML system:</p><ol><li>The adversarial nature of the problem means the attack distribution is constantly shifting, so we must keep improving models. Attackers are often even using ML systems of their own to adapt their attacks!</li><li>Due to the rarity of attacks, we must retain every precious sample. We cannot afford to throw out older attacks simply because they do not have the latest features. We must instead re-compute these features.</li><li>Due to high dimensionality and volume, it is a big-data problem and requires efficient distributed data processing.</li></ol><p>To build a platform and team that can operate and improve our detection engine at high velocity, we must enable ML engineers to experiment with changes across the entire stack. This includes changes to underlying detection code, new datasets, new features, and the development of new models.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/448/1*9ATxvASCZHooOyiTq7PIWg.png" /><figcaption>Iteration for ML engineers working on detection problems at Abnormal. A lot goes into improving the detection stack, and it’s crucial to have a robust testing and evaluation suite that can evaluate across new models, datasets, new code, etc.</figcaption></figure><p>This loop is reminiscent of a software engineering CI/CD loop, but there are more moving pieces. When developing detectors, there may be new code involved, new datasets (that must be served online and offline), and new models. We must test this entire stack thoroughly, and the easier it is to test, the easier it will be to safely iterate.</p><p><strong>Why is testing the detection stack so important? </strong>Think about what could go wrong -- if, for example, we make an unintentional code change that modifies a feature used by a model (but we do not retrain the model), the effect could shift distributions, incorrectly classify, and miss a damaging attack. Since our system acts at incredibly high precision and recall, small changes can cascade to have large consequences.</p><h3>Re-generating an updated labeled dataset</h3><p>Our rescoring system has three important components</p><ol><li><strong>Golden Labels: </strong>The set of all labeled messages with features updated with the entire detection stem (including recent code, joined data, and prediction models). We affectionately call this dataset “Golden Labels.” It’s the gold standard label set, and it is also precious because it contains all attack examples from the past. This dataset feeds into the following two processes.</li><li><strong>Rescoring:</strong> Process to evaluate the entire detection system to produce performance analytics like precision, recall. We call this “rescored recall.” For example, we measure what percentage of historical attacks we would catch today with the current detection system. <em>Note: this is different than precision and recall evaluation on individual models on an evaluation set because we are testing </em><strong><em>an entire stack</em></strong><em> that includes multiple models, decision logic, feature extraction code, and datasets.</em></li><li><strong>Model Training: </strong>Like rescoring, re-training models requires up-to-date Golden Labels data. We must have correct and unbiased features to train our models so that the data observed when training matches up to the data at inference time. The features that feed into model training are organized as a DAG of dependencies where some features rely on other features or models (see our blog post on <a href="https://medium.com/abnormal-security-engineering-blog/graph-of-models-and-features-e5409ca07709">Graph of Models and Features</a> for more on this)</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/855/1*2I3shswkJiLfYKpmORHH9w.png" /><figcaption>Various steps in the model training and rescoring are dependent on the most recent datasets, code, models, and labeled samples. Since we don’t want to lose old attack samples, we must re-hydrate and re-extract features for all these old samples. This rescoring pipeline creates an updated dataset called<strong> “Golden Labels”</strong> used to ensure accurate data on the historical dataset.</figcaption></figure><h3>Requirements for Data Golden Labels Re-Generation</h3><p>For data that feeds into rescoring and model training to be effective, we have several requirements:</p><ol><li><strong>(historical samples support) </strong>Should be able to update all historical samples with the latest attribute extraction (1) code, (2) joined datasets, and (3) model predictions and evaluate proper and trustable analytics</li><li><strong>(unbiased feature requirement) </strong>Re-computed features on old samples accurately reflect how those features would appear if that sample were encountered today.</li><li>To produce unbiased aggregate features, the system must perform <strong>time-travel:</strong> evaluate samples as they would have looked at the time of the attack. Time travel ensures unbiased data and also helps us avoid <strong>future leakage: </strong>avoiding bringing any data from the future (to a past sample) that leaks labels into training features.</li><li>(<strong>developer effectiveness) </strong>ML Engineers must be able to easily develop, integrate, and deploy their changes to any area of the detection stack.<strong> </strong>Must be efficient enough to run frequently to retrain and evaluate changes and ad-hoc evaluations to answer “what-if” type questions.</li></ol><h4><strong>Ad-Hoc rescoring experiments</strong></h4><p>In addition to the automatic daily re-generation of “Golden Labels” (tagged to a particular code branch), we additionally have an Ad-Hoc rescoring pipeline allowing engineers to ask “what if” questions — that is, what happens to overall detection performance if we change one or more pieces of the system.</p><p>For example, we may not need to re-run the entire feature extraction stage if we are testing only a new model (and the downstream impact of that model). To do so, we rely on the most recent updated Golden Labels from the night before and run additional steps:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/405/1*baUJ__D-sNIUQHjKHxA3ZQ.png" /><figcaption>Partial re-evaluation allows us to test changes on parts of the stack without re-extracting all features.</figcaption></figure><p><strong>Example of an ad-hoc rescoring experiment</strong></p><p>We can either set up two configurations, “Baseline” and “Experiment,” or <em>run this on two different code branches</em>. It’s up to the ML engineer to decide how to run their experiment correctly. Eventually, we would like our CI/CD system to run rescoring on stages affected by particular code changes and automatically provide metrics, but for now, it is manual.</p><p>This example configuration tests what happens when we swap out a single model.</p><pre># Baseline configuration runs model scoring and decisioning.<br>baseline_config = RescoreConfig(<br>  [           <br>    MODEL_SCORING, # Evaluates ML models<br>    DETECTION_DECISIONS, # Evaluates our detection decisions using the model scores.<br>  ]<br>)</pre><pre># Experimental setup to swap a single model.<br>experiment_config = RescoreConfig(<br>  [<br>    MODEL_SCORING,<br>    DETECTION_DECISIONS,<br>  ],<br>  FinalDetectorRescoreConfig(<br>    replace_models=[ReplacementModelConfig(<br>      model_path=&quot;/path/to/experimental/model&quot;,<br>      model_id=ATTACK_MODEL<br>    )]<br>  )<br>)<br><br># Runs the rescoring and delivers analytics to the user.<br>run_rescoring(<br>  rescore_config=rescore_config,<br>  baseline_config=baseline_config<br>)</pre><p>We can use a similar system to generate model training data with experimental features.</p><h3>Running rescoring efficiently (part 2…)</h3><p>Both automatic and ad-hoc rescoring require a lot of heavy lifting behind the scenes. We run everything on Spark, and there are a lot of tricky data engineering problems to solve to satisfy the requirements listed above, especially the time travel problem. Read part 2 of this story here:</p><p><a href="https://medium.com/abnormal-security-engineering-blog/re-scoring-an-ml-detection-engine-on-past-attacks-part-1-2845fd9f09f6">Re-Scoring an ML Detection Engine on Past Attacks (part 1)</a></p><p>If you are interested in solving tough Applied ML engineering problems in the cybersecurity space, yes, <a href="https://abnormalsecurity.com/careers/">we’re hiring</a>!</p><p><em>Thanks to Justin Young, Carlos Gasperi, Kevin Lau, Dmitry Chechick, Micah Zirn, and everyone else on the detection team at Abnormal who contributed to this pipeline.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2845fd9f09f6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/abnormal-security-engineering-blog/re-scoring-an-ml-detection-engine-on-past-attacks-part-1-2845fd9f09f6">Re-Scoring an ML Detection Engine on Past Attacks (part 1)</a> was originally published in <a href="https://medium.com/abnormal-security-engineering-blog">Abnormal Security Engineering Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Graph of Models and Features]]></title>
            <link>https://medium.com/abnormal-security-engineering-blog/graph-of-models-and-features-e5409ca07709?source=rss-2a37a4a6293d------2</link>
            <guid isPermaLink="false">https://medium.com/p/e5409ca07709</guid>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[mlops]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Jeshua Bratman]]></dc:creator>
            <pubDate>Mon, 01 Feb 2021 15:51:46 GMT</pubDate>
            <atom:updated>2021-02-01T15:51:46.056Z</atom:updated>
            <content:encoded><![CDATA[<p>At the core of all Abnormal’s detection products sits a sophisticated web of prediction models. For any of these models to function we need deep and thoughtfully engineered features, careful modeling of sub-problems, and the ability to join data from a set of databases.</p><p>For example, one type of email attack we detect is called Business Email Compromise (BEC). A common BEC attack is a “VIP impersonation” in which the attacker pretends to be the CEO or other VIP in a company in order to convince an employee to take some action. Some of the inputs to a model detecting this sort of attack include:</p><ol><li>Model evaluating how similar the sender’s name appears to match a VIP (indicating impersonation)</li><li>NLP models applied to the text of the message</li><li>Known communication patterns for the individuals involved</li><li>Identity of the individuals involved extracted from an employee database</li><li>… and many more</li></ol><p>All these attributes are carefully engineered and may rely on one another in a directed graphical fashion.</p><p>This article describes Abnormal’s graph-of-attributes system which makes this type of interconnected modeling scalable. This system has enabled us to grow our ML team while continuing to rapidly innovate.</p><h3>Attributes</h3><p>We store all original entity data as rich thrift objects (for example a thrift object representing an email or an account sign-in). This allows flexibility in terms of the data types we log, enables easy, backward compatibility, and understandable data structures. But as soon as we want to convert this data into something that will be consumed by data science engines and models, we should convert these into attributes. An attribute is a simply-typed object (float / int / string / boolean) with a numeric attribute ID.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1MOWVuZiMp_7iasD" /></figure><p><strong>Attribute vs Features — </strong>Attributes are conceptually similar to features, but they might not be quite ready to feed into an ML model. These should be ready to convert into a form consumable by models. All the heavy lifting should occur at the time of attribute extraction, for example running inference on a model or hydrating from a database.</p><p>The core principles we are working off include:</p><ul><li>Attributes can rely on multiple modes of inputs (Other raw attributes, Outputs of models, Data hydrated from a database lookup or join)</li><li>Attributes should be flat data (i.e. primitives) and representable in a columnar database</li><li>Attributes should be simple to convert to features (for example you may need to convert a categorical attribute into a one-hot vector)</li><li>We will always need to change and improve attributes over time</li></ul><p><strong>Consuming Attributes — </strong>Once data is converted into a columnar format it can be consumed in many ways: Ingested into a columnar store for analytics, tracked in metrics to monitor distributional shifts, and converted directly into a feature dataframe ready for training with minimal extra logic.</p><h3>Directed graph of attributes</h3><p>Computing attributes as a directed graph allows enormous flexibility for parallel development by multiple engineers. If each attribute declares its inputs, we can ensure everything is queried and calculated in the correct order. This enables attributes of multiple types:</p><ol><li>Raw features</li><li>Heuristic that use many other features as input</li><li>Models that make a prediction from many other features</li><li>Embeddings</li></ol><p>Attribute Hydration Graph:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/681/0*H_Lj5NrW61u6Xp6w" /></figure><p>Explicitly encoding the graph of attributes seems complex but it will save you painful headaches down the road when you want to use one attribute as an input to another.</p><h3>Attribute versioning</h3><p>Inevitably we will want to iterate on attributes and the worst feeling is realizing that the attribute you want to modify is used by ten downstream models. How do you make a change without retraining all those models? How do you verify and stage the change?</p><p>This situation comes up frequently. Some common cases:</p><ul><li>An attribute is the output of a model or an embedding, you want to re-train the model, but this attribute is used by other models, or heuristics</li><li>An attribute relies on a database serving aggregate features and we would like to experiment with different aggregate bucketizations</li><li>We have a carefully engineered heuristic feature and we would like to update the logic</li></ul><p>If each attribute is versioned and downstream consumers register which version they wish to consume, then we can easily bump the version (while continuing to compute the previous versions) without affecting the consumers.</p><h3>Scaling an ML Team</h3><p>In addition to enabling flexible modeling of complex problems, this graph of models enables us to scale our ML engineering team. Previously we had a rigid pipeline of features and models which was really only amenable to a single ML engineer at a time to develop. Now, we can have multiple ML engineers developing models for sub-problems, and then combining the resulting features and models together later.</p><h3>There’s so much more to do</h3><p>We need to figure out how to more efficiently re-extract this graph of attributes for historical data and good processes for sunsetting older attributes. We would like to build a system that allows our security analysts and anyone else in the company to easily contribute attributes and allow those to automatically flow into downstream models and analysis. We need to improve our ability to surface relevant attributes and models scores important to a given decision back to the client to understand the reasons an event is flagged. And so much more… If these problems interest you, yes, <a href="https://abnormalsecurity.com/careers/">we’re hiring</a>!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e5409ca07709" width="1" height="1" alt=""><hr><p><a href="https://medium.com/abnormal-security-engineering-blog/graph-of-models-and-features-e5409ca07709">Graph of Models and Features</a> was originally published in <a href="https://medium.com/abnormal-security-engineering-blog">Abnormal Security Engineering Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Lazily Loading ML Models for Scoring with PySpark]]></title>
            <link>https://medium.com/abnormal-security-engineering-blog/lazily-loading-ml-models-for-scoring-with-pyspark-a167d4deed3c?source=rss-2a37a4a6293d------2</link>
            <guid isPermaLink="false">https://medium.com/p/a167d4deed3c</guid>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[pyspark]]></category>
            <category><![CDATA[tensorflow]]></category>
            <dc:creator><![CDATA[Jeshua Bratman]]></dc:creator>
            <pubDate>Fri, 11 Dec 2020 19:47:59 GMT</pubDate>
            <atom:updated>2020-12-11T19:47:59.399Z</atom:updated>
            <content:encoded><![CDATA[<p>Authors: <a href="https://medium.com/@nojeshua">Jeshua Bratman</a> and <a href="https://www.linkedin.com/in/vineetedupuganti/">Vineet Edupuganti</a></p><p>Our core email attack detection product at Abnormal works by processing each incoming message, applying a series of classification models, and ultimately deciding if a message might be an attack. This detection system runs in an online distributed system processing millions of messages per day.</p><p><strong>Rescoring</strong></p><p>One key component in our pipeline is called <strong><em>rescoring</em></strong>. This data pipeline loads historical examples of email attacks in order to evaluate the accuracy of our detection system with respect to historical attacks. Rescoring allows us to easily measure how changes to code and classification models impact the performance of the product.</p><p>High-level steps in rescoring:</p><ol><li>Re-process messages</li><li>Re-extract every attribute and feature</li><li>Re-run every detection model</li><li>Evaluate precision, recall, and other statistics</li></ol><p>Crucially, we need this batch evaluation pipeline to resemble our online decisioning flow as closely as possible, using the exact same code paths for the scoring module, but run over large sets of batch data using Spark. If the code running was not identical to our real-time scoring systems, we would not be able to trust that the rescoring results match true detection performance in our online system.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/745/0*egBm5sIMXodTzVTv" /></figure><p><strong>Lazy evaluation for rescoring models</strong></p><p>PySpark has been a very flexible batch processing tool, but one challenge we ran into with the above architecture surfaces when using certain optimized ML libraries. In this article, we’ll focus in particular on Tensorflow models (using Keras), and nearest-neighbor models (using <a href="https://github.com/spotify/annoy">Spotify’s Annoy library</a>). Neither plays nicely with Spark.</p><p>The straightforward approach would be:</p><ol><li>Load models into memory in the Spark driver equivalently to how our real-time scorer loads models</li><li>Broadcast these models to the Spark executors</li><li>Run each model across examples in Spark executors</li></ol><p>However, for both Tensorflow and Annoy, the loaded models exist outside the Python process memory space and therefore cannot be broadcast using PySpark (which attempts to just pickle the Python object).</p><p>Our simple solution is to broadcast only the bytes of the model and load them into memory in a lazy fashion.</p><pre>class ModelWrapper:<br>  def __init__(self, model_data):<br>    self.model_data = model_data</pre><pre>  def predict(self, features):<br>    if not self.initialized:<br>      self._load_model(self.model_data)<br>      # Predict</pre><pre>  def _load_model(self): <br>    # Initialize Tensorflow Graph &amp; Session<br>    # Load model into memory.</pre><p>This means the model is not actually loaded until the first time it is used to make a prediction.</p><p><strong>Example 1: Keras+Tensorflow models</strong></p><p>We use this lazy loading method, in particular, for Keras/TF models. Since the TensorFlow graph lives in memory outside of the Python process we must ensure this graph and session are created on the Spark executors. The models are loaded and used identically between the batch and realtime pipeline. Here’s how it looks:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CzNijbcHiZArvC_w" /></figure><p>The raw data we pass around for Keras models is simply</p><ol><li>The Keras JSON description</li><li>Trained weights in the .h5 format</li></ol><p>Sketch of loading Keras models from JSON &amp; H5:</p><pre>import h5py<br>from keras.models import model_from_json<br>from keras.engine import saving</pre><pre>model = model_from_json(model_json)<br>h5_file = h5py.File(io.BytesIO(model_bytes))</pre><pre>if “layer_names” not in f.attrs and “model_weights” in f:<br>   h5_file =h5_file[“model_weights”]</pre><pre>saving.load_weights_from_hdf5_group(h5_file, model.layers, reshape=reshape)</pre><p><strong>Example 2: Nearest Neighbor store using Annoy</strong></p><p>Just as with our Keras and TF models, we need to handle serialization and lazy loading when working with Annoy objects as well. Properly leveraging Annoy is an important requirement for our work on <a href="https://medium.com/abnormal-security-engineering-blog/intelligent-signatures-at-abnormal-security-48ef6c19d4b5?source=collection_home---4------1-----------------------">intelligent signatures</a> and gives us the ability to perform efficient nearest neighbor lookups with large quantities of data (i.e. given an embedding, find the entries in our nearest neighbor store with the most similar embeddings).</p><p>Originally developed by Spotify and used for music recommendations, Annoy uses an approximate approach that creates an index based on a set of trees to enable fast lookup. Additionally, the library allows one to build indices offline and share them across memory processes. Despite these benefits, there are a few challenges with leveraging Annoy objects in production, as we describe below.</p><p><strong>Serialization</strong></p><p>After building the Annoy index, it is important to be able to save it to a distributed file store, so we can load it in the same manner as our other models. However, a limitation of the Annoy library is that it only enables saving to disk, and other serialization methods (Pickle, for example) will not work. As such, we use an indirect approach whereby we save the index to a temporary file, read the corresponding bytes back, and store it as part of a larger serialized thrift object. To read the index, we load in the bytes directly from our online file store, save to a temporary file, and load in the index with the Annoy API. See below for corresponding code snippets.</p><pre>def get_annoy_bytes(annoyIndex):<br>   with tempfile.NamedTemporaryFile(suffix=&#39;.ann&#39;) as fp:<br>       fname = fp.name<br>       annoyIndex.save(fname)<br>       file = open(fname, &quot;rb&quot;)   <br>       annoy_bytes = file.read()<br>       file.close()<br>   return annoy_bytes</pre><pre>def read_annoy_bytes(dimension, distance, annoy_bytes):<br>   annoy_index = annoy.AnnoyIndex(dimension, distance)<br>   with tempfile.NamedTemporaryFile(suffix=&#39;.ann&#39;) as fp:<br>       fname = fp.name<br>       fp.write(annoy_bytes)<br>       annoy_index.load(fname)<br>   return annoy_indexdef get_annoy_bytes(annoyIndex):</pre><p><strong>Lazy loading</strong></p><p>In addition to serialization, we have to deal with the same challenges as the Keras models in terms of not being able to broadcast Annoy objects using PySpark. As such, we have to employ the lazy loading mechanism described above.<strong> </strong>With this approach, we initialize the Annoy index to None, such that we can broadcast without memory errors. Each time a given worker tries to score a message, the lazy init function is called, which loads in the Annoy index object. After the first time the object is loaded no additional read operations are required.</p><p><strong>Large scale ML at Abnormal</strong></p><p>In summary, this post provides a quick glimpse into a few of the challenges with running large-scale ML systems in production — namely leveraging libraries like Keras and Annoy in conjunction with big data frameworks like PySpark. We hope the methods we introduce for addressing lazy loading and serialization can be useful to you as you face similar challenges working with these tools.</p><p>To learn more about the exciting work that Abnormal is doing, check out the rest of our blog <a href="https://medium.com/abnormal-security-engineering-blog">here</a>. And if developing machine learning models and software systems to stop cybercrime interests you, <a href="https://abnormalsecurity.com/careers/">yes we’re hiring</a>!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a167d4deed3c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/abnormal-security-engineering-blog/lazily-loading-ml-models-for-scoring-with-pyspark-a167d4deed3c">Lazily Loading ML Models for Scoring with PySpark</a> was originally published in <a href="https://medium.com/abnormal-security-engineering-blog">Abnormal Security Engineering Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Stopping election interference emails attacks using ML]]></title>
            <link>https://nojeshua.medium.com/stopping-election-interference-emails-attacks-using-ml-8b693b65edb9?source=rss-2a37a4a6293d------2</link>
            <guid isPermaLink="false">https://medium.com/p/8b693b65edb9</guid>
            <dc:creator><![CDATA[Jeshua Bratman]]></dc:creator>
            <pubDate>Wed, 18 Nov 2020 02:45:26 GMT</pubDate>
            <atom:updated>2020-11-18T02:45:26.627Z</atom:updated>
            <content:encoded><![CDATA[<h3>Stopping election interference attacks using ML</h3><p>My favorite part of working at Abnormal Security is seeing the myriad of nefarious attacks we are able to stop. These attacks include everything from attempts to <a href="https://abnormalsecurity.com/blog/vendor-impersonation-payment-fraud/">steal millions of dollars</a>, to <a href="https://abnormalsecurity.com/blog/russian-based-ransomware-attack-using-malware-targeting-u-s-industries-underway/">installing ransomware crippling hospitals</a>, to state actors compromising our power grid. And — right the core of the product sits some tough ML problems. How do we robustly identify behavior anomalies? How do we quickly adapt to an ever-changing attack landscape? How do we catch these really carefully crafted social engineering strategies aimed to trick people?</p><p>Just before the election, an attack went out to thousands of voters in Florida <a href="https://abnormalsecurity.com/blog/election-interference/">trying to intimidate them into voting for Donald Trump</a>. Although our system did not stop these initially, we were able to quickly feed examples into our ML system and get it to catch on, and then subsequently prevent other election-based social engineering attacks. This used a pretty cool system we recently built —</p><ol><li>Rapidly fine-tunes models based on the newest data</li><li>Accepts hints in the form of examples emails, phrases, etc</li><li>Uses data augmentation to generalize and boost the impact of those hints (along with particular false negatives) have on the model parameters</li></ol><p>Not only was this able to immediately improve our system to catch the exact attack we saw but was able to generalize from the text content and behavioral patterns to identify other attacks trying to manipulate recipients using election-related strategies.</p><p>Read more about this project here:</p><p><a href="https://medium.com/abnormal-security-engineering-blog/stopping-new-email-attacks-with-data-augmentation-and-rapidly-training-models-89ab5b8fbf12">Stopping New Email Attacks with Data Augmentation and Rapidly-Training Models</a></p><p>And more broadly, if you are interested in our approach to email security, here are two other stories I recently published to our blog:</p><ul><li><a href="https://medium.com/abnormal-security-engineering-blog/intelligent-signatures-at-abnormal-security-48ef6c19d4b5">Intelligent Signatures at Abnormal Security</a></li><li><a href="https://medium.com/abnormal-security-engineering-blog/combining-ml-models-to-detect-email-attacks-e1b4d1f2d14e">Combining ML Models to Detect Email Attacks</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8b693b65edb9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Combining ML Models to Detect Email Attacks]]></title>
            <link>https://medium.com/abnormal-security-engineering-blog/combining-ml-models-to-detect-email-attacks-e1b4d1f2d14e?source=rss-2a37a4a6293d------2</link>
            <guid isPermaLink="false">https://medium.com/p/e1b4d1f2d14e</guid>
            <category><![CDATA[email-security]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Jeshua Bratman]]></dc:creator>
            <pubDate>Tue, 17 Nov 2020 23:31:12 GMT</pubDate>
            <atom:updated>2020-11-18T00:21:27.244Z</atom:updated>
            <content:encoded><![CDATA[<p>This article is a follow-up to one I wrote a year ago — <a href="https://medium.com/@nojeshua/lessons-from-building-ai-to-stop-cyberattacks-7d593250989c">Lessons from building AI to Stop Cyberattacks</a> — in which I discussed the overall problem of detecting social engineering attacks using ML techniques and our general solution at Abnormal. This post aims to walk through the process we use at Abnormal to model various aspects of a given email and ultimately detect and block attacks.</p><p>As discussed in the previous post, sophisticated social engineering email attacks are on the rise and getting more advanced every day. They prey on the trust we put in our business tools and social networks, especially when a message appears to be from someone on our contact list (but is not) or even more insidiously when the attack is actually from a contact whose account has been compromised. The FBI estimates that over the past few years over 75% of cyberattacks start with social engineering, usually through email.</p><h3>Why is this a hard ML problem?</h3><p><strong>A needle in a haystack</strong> — The first challenge is that the base rate is very low. Advanced attacks are rare in comparison to the overall volume of legitimate email:</p><ul><li>1 in 100,000 emails is advanced spear-phishing</li><li>less than 1 in 10,000,000 emails is advanced BEC (like invoice fraud) or lateral spear phishing (a compromised account phishing another employee)</li><li>When compared to spam, which accounts for 65 in every 100 emails, we have an extremely biased classification problem which raises all sorts of difficulties</li></ul><p><strong>Enormous amounts of data </strong>— At the same time, the data we have is large (many terabytes), messy, multi-modal, and difficult to collect and serve at low latency for a real-time system. For example, features that an ML system would want to evaluate include:</p><ul><li>Text of the email</li><li>Metadata and headers</li><li>History of communication for parties involved, geo locations, IPs, etc</li><li>Account sign-ins, mail filters, browsers used</li><li>Content of all attachments</li><li>Content of all links and the landing pages those links lead to</li><li>…and so much more</li></ul><p>Turning all this data into useful features for a detection system is a huge challenge from a data engineering as well as ML point of view.</p><p><strong>Adversarial attackers </strong>— To make matters worse, attackers actively manipulate the data to make it hard on ML models, constantly improving their techniques and developing entirely new strategies.</p><p><strong>The precision must be very high — </strong>to build a product to prevent email attacks we must avoid false positives and disruption of legitimate business communications, but at the same time catch every attack. The false-positive rate needs to be as low as one in a million!</p><p>For more examples of the challenges that go into building ML to stop email attacks, see the discussion <a href="https://medium.com/@nojeshua/lessons-from-building-ai-to-stop-cyberattacks-7d593250989c">Lessons from building AI to Stop Cyberattacks</a>.</p><p>To effectively solve this problem we must be diligent and extremely thoughtful about how we break down the overall detection problem into components that are solved carefully.</p><h3>Example:</h3><p>Let’s start with this hypothetical email attack and imagine how we could model various dimensions and how those models come together.</p><blockquote><strong>Subject: </strong>Reset your password<br><strong>From: </strong>Microsoft Support &lt;admin@fakemicrosoft.com&gt;<br><strong>Content:</strong> “Please click _here_ to reset the password to your account.”</blockquote><p>This is a simple and prototypical phishing attack.</p><p>As with any well-crafted social engineering attack, it appears nearly identical to a legitimate message, in this case, a legitimate password reset message from Microsoft. Because of this, modeling any single dimension of this message will be fruitless for classification purposes. Instead, we need break up the problem into component sub-problems</p><p><strong>Thinking like the attacker</strong></p><p>Our first step is always to put ourselves in the mind of the attacker. To do so we break an attack down into what we call “attack facets”.</p><p>Attack Facets:</p><ol><li>Attack Goal — What is the attacker trying to accomplish? Steal money? Steal credentials? Etc.</li><li>Impersonation Strategy — How is the attacker building credibility with the recipient? Are they impersonating someone? Are they sending from a compromised account?</li><li>Impersonated Party — Who is being impersonated? A trusted brand? A known vendor? The CEO of a company?</li><li>Payload Vector — How is the actual attack delivered? A link? An Attachment?</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/780/0*WoCh3U5ireiWeLWs" /></figure><p>If we break down the Microsoft password reset example, we have:</p><ol><li>Attack goal: Steal a user&#39;s credentials</li><li>Impersonation strategy: Impersonate a brand through a lookalike display name (Microsoft)</li><li>Impersonated party: The official Microsoft brand</li><li>Payload vector: A link to a fake login page.</li></ol><p><strong>Modeling the problem</strong></p><p>Building ML models to solve a problem with such a low base rate and precisions requirements forces a high degree of diligence when modeling sub-problems and feature engineering. We cannot rely just on the magic of ML.</p><p>In the last section, we described a way to break an attack into components. We can use that same breakdown to help inspire the type of information we would like to model about an email in order to determine if it is an attack.</p><p>All these models rely on similar underlying techniques — specifically</p><ul><li><strong>Behavior modeling:</strong> identifying abnormal behavior by modeling normal communication patterns and finding outliers from that</li><li><strong>Content modeling: </strong>understanding the content of an email</li><li><strong>Identify resolution:</strong> matching the identity of individuals and organizations referenced in an email (perhaps in an obfuscated way) to a database of these entities</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*xmvPrXX18R33YzWA" /></figure><p><strong>Attack Goal and Payload</strong></p><p>Identifying an attack goal requires modeling the content of a message. We must understand what is being said. Is the email asking the recipient to do anything? Is it an urgent tone? and so forth. This model may not only identify malicious content but safe content as well in order to differentiate the two.</p><p><strong>Impersonated Party</strong></p><p>What does an impersonation look like? First of all the email must appear to the recipient to look like someone they trust. We build identity models to match various parts of an email against known entities inside and outside an organization. For example, we may identify an employee impersonation by matching against the active directory. We may identify a brand impersonation by matching against the known patterns of brand-originating emails. We might identify a vendor impersonation by matching against our vendor database.</p><p><strong>Impersonation Strategy</strong></p><p>An impersonation happens when an email is not from the entity it is claiming to be from. To do so we identify normal behavior patterns to spot these abnormal ones. This may be abnormal behavior between the recipient and the sender. It may be unusual sending patterns from the sender. In the simplest case, like the example above, we can simply note that Microsoft never sends from “fakemicrosoft.com”. In more difficult cases, like account takeover and vendor compromise, we must look at more subtle clues like unusual geo-location and IP address of the sender or incorrect authentication (for spoofs).</p><p><strong>Attack Payload</strong></p><p>For the payload, we must understand the content of attachments and links. Modeling these requires a combination of NLP models, computer vision models to identify logos, URL models to identify suspicious links, and so forth.</p><p>Modeling each of these dimensions gives our system an understanding of emails particularly along dimensions that might be used by attackers to conduct social engineering attacks. The next step is actually detecting attacks</p><h4>Combining Models to Detect Attacks</h4><p>Ultimately we need to combine these sub-models to produce a classification result (for example P(Attack)). Just like any ML problem, the features given to a classifier are crucial for good performance. The careful modeling described above gives us very high bandwidth features. We can combine these models in a few possible ways.</p><p><strong>(1) One humongous classification model: </strong>Train a single classifier with all the inputs available to each sub-model. All the input features could be chosen based on the features that worked well within each sub-problem, but this final model combines everything and learns unique combinations and relationships.</p><p><strong>(2) Extract features from sub-models and combine to predict target — </strong>there are 3 ways we can go about this:</p><p><strong>(2.a) Ensemble of Models-as-Features: </strong>Each sub-model is a feature. Its output is dependent on the type of model. For example, a content model might predict a vector of binary topic features</p><p><strong>(2.b) Ensemble of Classifiers: </strong>Build sub-classifiers that each predict some target and combine them using some kind of ensemble model or set of rules. For example, a content classifier would predict the probability of attack given the content alone.</p><p><strong>(2.c) Embeddings: </strong>Each sub-model is trained to predict P(attack) like above or some other supervised or unsupervised target, but rather than combining their predictions, we extract embeddings, for example, by taking the penultimate layer of a neural net.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*R7UjxLm-Zz_yoJKW" /></figure><p>Each of the above approaches has advantages and disadvantages. Training one humongous model has the advantage of getting to learn all complex cross dependencies, but it is harder to understand and harder to debug, and more prone to overfitting. It also requires all the data available in one shot, unlike building sub-models that could potentially operate on disparate datasets.</p><p>The various methods of extracting features from sub-models also have tradeoffs. Training sub-classifiers is useful because they are very interpretable (for example we could have a signal that represents the suspiciousness of text content alone), but in some cases, it is difficult to predict the attack target directly from a sub-domain of data. For example, purely a rare communication pattern is not sufficient to slice the space meaningfully to predict an attack. Similarly as discussed above, a pure content model cannot predict an attack without context regarding the communication pattern. The embeddings approach is good, but also finicky, it is important to vet your embeddings and not just trust they will work. Also, the embedding approach is more prone to overfitting or accidental label leakage.</p><p>Most importantly with all these approaches, it is crucial to think deeply about all the data going into models and also the actual distribution of outputs. Blindly trusting in the black box of ML is rarely a good idea. Careful modeling and feature engineering are necessary, especially when it comes to the inputs to each of the sub-models.</p><h4>Our solution at Abnormal</h4><p>As a fast-growing startup, we originally had a very small ML team which has been growing quickly over the past year. With the growth of the team, we also have adapted our approach to modeling, feature engineering, and training our classifiers. At first, it was easiest to just focus on one large model that combined features carefully engineered to solve subproblems. However, as we’ve added more team members it has become important to split the problem up into various components that can be developed simultaneously.</p><p>Our current solution is a combination of all the above approaches depending on the particular sub-model. We still use a large monolithic model as one signal, but our best models use a combination of inputs including embeddings representing an aspect of an email and prediction values from sub-classifiers (for example a suspicious URL score).</p><p>Combining models and managing feature dependencies and versioning is also difficult.</p><h3>Takeaways for solving other ML problems</h3><ol><li>Deeply understand your domain</li><li>Carefully engineer features and sub-models, don’t trust black box ML</li><li>Solving many sub-problems and combining them for a classifier works well, but don’t be dogmatic. Sure, embeddings may be the purest solution, but if it’s simpler to just create a sub-classifier or good set of features, start with that.</li><li>Breaking up a problem also allows scaling a team. If multiple ML engineers are working on a single problem, they must necessarily focus on separate components.</li><li>Modeling a problem as a combination of subproblems also helps with explainability. It’s easier to debug a text model than a giant multi-modal neural net.</li></ol><h3>But, there’s a ton more to do!</h3><p>We need to figure out a more general pattern for developing good embeddings and better ways of modeling sub-parts of the problem, better data platforms, and feature engineering tools, and so much more. Attacks are constantly evolving and our client base is ever-growing leading to tons of new challenges every day. If these problems interest you, yes, <a href="https://abnormalsecurity.com/careers/">we’re hiring</a>!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e1b4d1f2d14e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/abnormal-security-engineering-blog/combining-ml-models-to-detect-email-attacks-e1b4d1f2d14e">Combining ML Models to Detect Email Attacks</a> was originally published in <a href="https://medium.com/abnormal-security-engineering-blog">Abnormal Security Engineering Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Lessons from building AI to Stop Cyberattacks]]></title>
            <link>https://medium.com/abnormal-security-engineering-blog/lessons-from-building-ai-to-stop-cyberattacks-7d593250989c?source=rss-2a37a4a6293d------2</link>
            <guid isPermaLink="false">https://medium.com/p/7d593250989c</guid>
            <category><![CDATA[business-email-compromise]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[email-security]]></category>
            <dc:creator><![CDATA[Jeshua Bratman]]></dc:creator>
            <pubDate>Tue, 19 Nov 2019 05:54:02 GMT</pubDate>
            <atom:updated>2019-11-21T00:49:12.284Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5-HNhEhN7QJ3OG6_LGQFcQ.png" /><figcaption>Successful Phishing attack on John Podesta that lead to the 2016 DNC email leaks. <a href="https://wikileaks.org/podesta-emails/emailid/34899">Released by WIkiLeaks.</a></figcaption></figure><p>On March 19th 2016 John Podesta, was tricked into revealing his Gmail credentials to a Russian-backed organization who then released emails regarding the Clinton campaign, effectively influencing the 2016 election.</p><p>Social engineering attacks like this (and much more sophisticated ones) are on the rise and getting more advanced every day. They prey on the trust we put in our business tools and social networks, especially when a message appears to be from someone on our contact list (but is not) or <em>even more insidiously when the attack is actually from a contact whose account has been compromised</em>. The FBI estimates that over the past few years over 75% of cyberattacks start with social engineering, usually through email.</p><h4>Why is this a new problem?</h4><p>Hasn’t email been around forever? Why hasn’t this problem been solved? Why is it a machine learning problem?</p><p>With more business being done online and connected to a single cloud login, as well as the increasing use of mobile devices where UX is often designed without security in mind, these forms of attacks have skyrocketed in number and are a threat to every organization that uses email. The sophistication and targeted nature of the attacks has, until recently, outpaced the existing email security.</p><p>The only way to effectively detect these attacks is by using modern machine learning techniques of deep natural language understanding combined with careful modeling of an organization’s typical communication patterns.</p><p>About a year and a half ago I left Twitter’s ML team to help found <a href="http://abnormalsecurity.com">Abnormal Security</a> where I lead the development of our AI system to detect and prevent these malicious emails.</p><p>I’m somewhat new to cybersecurity and to email security (though it has similarities to the problem of detecting abuse detection which I worked on at Twitter). It is a fascinating and scary world:</p><ul><li>There’s a multi-billion dollar economy of criminals using email-based attacks to steal money, account information, and trade secrets, but as many as 50% of these attacks are <strong>probably perpetrated by state-actors</strong>: either spy organizations or politically motivated organizations funded by states such as Russia, China, Iran, and North Korea. For example, <a href="https://en.wikipedia.org/wiki/Fancy_Bear">Fancy Bear (APT28)</a> was responsible for the successful attack on John Podesta, and is probably funded by the Russian security organization GRU</li><li>Using zero-day exploits are not the only tools attackers have. It’s better for criminals to save those for a rainy day or sell them to a state actor. It’s much easier to convince someone to give up their credentials and use those to escalate privileges until you can get what you want, either money or trade secrets</li><li>Existing email security has not been able to stop these attacks and the attacks are only getting more sophisticated.</li></ul><h3>Can we use modern AI to prevent attacks?</h3><p>There’s a long history of using ML to stop email fraud, for example, Spam filters are taught in most introductory ML courses. However, attackers have far-outpaced existing email security. Nearly every organization from local governments, manufacturing, energy companies, technology companies, to individuals are targeted and many are successfully breached every day.</p><p>Why is it hard to prevent these attacks?</p><ol><li>The text in email attacks is often indistinguishable from legitimate communication. It’s been carefully designed to fool both the recipient and security software.</li><li>Attackers are actively attempting to avoid ML systems, and using their own ML systems to thwart detection (for example, we found spear-phishing A/B testing software for sale on the dark web)</li><li>Attackers may launch attacks from compromised accounts making them even harder to identify from regular email.</li></ol><p>Before Abnormal Security, I worked at Twitter Cortex bringing deep learning models to many areas of the Twitter product. One particular problem I worked on was abuse detection: How do we identify harassment, bullying, and hate speech in Tweet conversations? We found that a combination of modern NLP (embeddings and LSTMs etc.) alongside features of the communication graph (who is tweeting at who, what communities are they in, what is their communication history etc.) was the crucial combination to build successful detection models.</p><p>These lessons learned from Twitter were helpful when approaching the problem of identifying email attacks: (1)is the content of the message suspicious? (2) are identity of parties in the communication often targeted? (3) what is the past communication patterns of the recipient and sender?</p><p>Interestingly, Twitter and Email are two of the only large technologies where anyone can contact anyone else without a prior connection and are therefore both ripe for abuse But, email breaches are more insidious due to how much access is linked to email accounts.</p><p>In this age of cloud identity providers, so much information and access sis linked to email accounts on Office 365 and Gmail: documents, voice chat, video, possible even desktop access.</p><h3>Why is this a hard ML problem?</h3><p><strong>A needle in a haystack </strong>— The first challenge is that the base rate is very low. Advanced attacks are rare in comparison to the overall volume of legitimate email:</p><ul><li>1 in 100,000 emails is advanced spear-phishing</li><li>less than 1 in 10,000,000 emails is advanced BEC (like invoice fraud) or lateral spear phishing (a compromised account phishing another employee)</li><li>(compare to spam, which accounts for 65 in every 100 emails)</li></ul><p>This means we have an extremely biased classification problem which raises all sorts of difficulties.</p><p><strong>Enormous amounts of data </strong>— At the same time, the data we have is large (many terabytes), messy, multi-modal, and difficult to collect and serve at low latency for a realtime system. For example, features that a ML system would want to evaluate include:</p><ul><li>Text of the email</li><li>Metadata and headers</li><li>History of communication for parties involved</li><li>Account sign-ins, mail filters, and other account activity</li><li>Identity of parties involved (is it the CEO’s name ? an accountant? etc.)</li><li>Attachment content</li><li>Links in attachments</li><li>Images in attachments</li><li>Links and body</li><li>Contents of linked landing page</li><li>Images in linked landing pages</li><li>Code in landing pages</li><li>Malware in attachments</li><li>…</li></ul><p>Turning all this data into useful features for a detection system is a huge challenge from a data engineering as well as ML point of view.</p><p><strong>Adversarial attackers — </strong>To make matters worse, attackers actively manipulate the data to make it hard on ML models:</p><ul><li>Attackers encode text with Unicode-lookalike text (e.g. 𝙼𝚒𝚌𝚛𝚘soft)</li><li>Attackers insert distracting text hidden in non-displayed HTML (to confused NLP models)</li><li>Attackers encode text in images (to prevent NLP without OCR)</li><li>Phishing pages render all content with javascript and require a CAPTCHA to access (to prevent automated crawling)</li><li>Attackers send innocuous emails to an organization for months to build up communication/reputation features</li><li>Attackers include text in password-protected PDF files attached to an email (to prevent automatic parsing of attachments)</li><li>Attackers sit on a compromised account for months waiting for the right moment. For example by inserting an illegitimate invoice into a conversation about payment at just the right time.</li></ul><p><strong>The precision must be very high — </strong>to build a product to prevent email attacks we must avoid false positives and disruption of legitimate business communications, but at the same time catch every attack. The<strong> false-positive rate needs to be as low as one in a million!</strong></p><h3>Successfully solving the problem</h3><p>At Abnormal we’ve built an effective solution that relies on good data engineering, data science, and robust scalable systems underneath powerful ML models.</p><p>The key to detecting malicious emails is through good representations and discriminative featurization of that data. At the end of the day, our detection system relies on three dimensions of an email:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*jQFDvi3_ichtTGxC8gxJqg.png" /></figure><p>All this data is pulled together and made available on the receipt of each email. Our ensemble of detection models use these data sources in various ways, and we have redundant detectors for various classes of particularly damaging attacks. The core engine of detection is a multi-modal ML model.</p><h3>Malicious Email Classifier</h3><p>When we first started solving this problem, we used simple GBDT models on top of basic text and communication-graph based features, which I highly recommend to get started on this, or any other, ML problem. Begin with the simplest models you can before going onto sophisticated deep learning approaches.</p><p>Eventually, we outgrew simple models, and have found deep learning architectures particularly useful, not only for their predictive power <strong>but also for the convenience of including multiple modalities of data inside the same model</strong>. For example, one of our most powerful models needs to consume text data of various forms alongside tabular data:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/990/1*ukVku9bYQksp3bWSBlyiKg.png" /></figure><p>The ability to easily combine and train models representing multiple dimensions of an email in this way has been extremely powerful and helps us generalize to never-before-seen attacks.</p><p><strong>Thresholding the model output</strong> is one of the hardest problems. Since the precision must be so high, we must be very careful that the model performs well autonomously and can handle distributional shifts.</p><p>(I discuss difficulties around thresholding more in a <a href="https://medium.com/@nojeshua/model-calibration-when-subsampling-negatives-548eb8790223">previous post</a>)</p><h3>Some lessons</h3><ol><li>Study the attacks, trends, and false negatives. Build your data pipelines and features to represent what attackers might try next as well as variations on what you have seen.</li><li>Use human experts to create heuristics! Heuristics features can be some of the most powerful inputs into a model even if they are not sufficiently precise to be standalone rules.</li><li>Build a portfolio of detection models, heuristics, and signatures. There can never be too much redundancy in a detection stack.</li><li>Ensure each sub-model is representing its sub-problem well before trying to combine them into a larger network, or you will never make progress.</li><li>Always baseline and iterate: for example when building a text model, start simple and add complexity only when you can show it is better: (1) try heuristic phrases (2) try bag of words (3) try canned embeddings like fasttext (4) try fine-tuning your embeddings (5) try state-of-the-art techniques like BERT</li></ol><h4>Bringing it all together</h4><p>For this whole detection system to work successfully, we must ingest terabytes of data a day — all the incoming emails and other signals we have for an organization — and maintain sophisticated aggregated feature stores to keep track of the communication patterns in realtime. Online we must process every incoming email at low latency, extract and join data, possibly even crawl links and process attachments, apply NLP models and apply featurization. Then we must pass the data through classification models, and combine results of all models for a final decision on whether the email is malicious. All this must be done at latencies of less than a second and maintaining an extremely low false-positive rate. This is a difficult engineering and data science problem.</p><p>We’ve built a powerful detection system at Abnormal Security that can prevent the most advanced targeting phishing, business email compromise, lateral phishing and account compromise. But the problem is ever-changing as attackers learn to thwart these systems, so our work is never done.</p><p>Some (of many) major challenges we are continually improving</p><ul><li>How can we detect invoice fraud better? To do so we must deeply understand the natural language and images in an invoice to identify Abnormal patterns.</li><li>How can we detect phishing sites with higher accuracy? For an AI system to understand the content of the page we must render that page and use computer vision and NLP to identify malicious intent.</li><li>How can we better identify account takeovers? This is a difficult anomaly detection problem with enormous volumes of data, what constitutes unusual usage behavior and emails from a compromised account?</li></ul><h4>Acknowledgments</h4><p>All this work at Abnormal wouldn’t have been possible without the amazing team, especially those working closely on building this detection engine from the ground up: Dmitry Chechik, Kevin Lau, Sanny Liao, Yu Zhou Lee, Abhijit Bagri, Carlos Gasperi, James Yeh, Sanjay Jeyakumar, and the rest of the team.</p><p>And yes, we’re hiring! <a href="https://www.abnormalsecurity.com/careers">abnormalsecurity.com/careers</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RXrEu39P5-ZiR3cUhdyO9Q.jpeg" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7d593250989c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/abnormal-security-engineering-blog/lessons-from-building-ai-to-stop-cyberattacks-7d593250989c">Lessons from building AI to Stop Cyberattacks</a> was originally published in <a href="https://medium.com/abnormal-security-engineering-blog">Abnormal Security Engineering Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>