<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="https://www.w3.org/2005/Atom">
  <channel>
    <title>~dsalaj/com/</title>
    <description>Personal website of Darjan Salaj, a student of Graz University of Technology (TU Graz) and an employee of Institut für Informationssysteme und Computer Medien (IICM).
</description>
    <link>https://dsalaj.com///</link>
    <atom:link href="https://dsalaj.com///feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 05 Mar 2026 12:10:41 +0000</pubDate>
    <lastBuildDate>Thu, 05 Mar 2026 12:10:41 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Instead of more photos, make an audio album of your loved ones!</title>
        <description>&lt;p&gt;&lt;strong&gt;tl;dr:&lt;/strong&gt; &lt;em&gt;If you really want to capture a moment with someone you love, stop taking pictures and hit record on the voice memos app instead.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We are currently drowning in JPEGs. Every interesting moment results in a bunch of photos getting taken with our phones, synced to the cloud, and largely forgotten.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, photos are great for remembering what someone or something looked like at a specific point in time. But after a while, scrolling through them feels a bit hollow. You see the face, but you don’t necessarily feel the presence.&lt;/p&gt;

&lt;p&gt;If you want to capture your personal experience of someone you love, make candid audio recording with your phone.&lt;/p&gt;

&lt;h2 id=&quot;story-time&quot;&gt;Story time&lt;/h2&gt;

&lt;p&gt;🔈 I don’t know if it’s my proclivity for audio or what, but I had an intuition to start making random recordings of conversations with my grandma a couple of years before she passed away. Nothing formal, just her rambling about growing up, WW2 experiences, or even just her making random comments. I’d just set my phone on the table and let it run for twenty minutes.&lt;/p&gt;

&lt;p&gt;Now that she’s gone, I have many photos of her. But the things I treasure most are those crappy little &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ogg&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;When I look at a photo of her, I remember &lt;em&gt;that she existed&lt;/em&gt;. When I play one of those recordings, it’s like she’s back in the room with me. The effect is… visceral. It captures the cadence of her speech, the specific way she chuckled at her own stories, the little pauses. It transports you instantly back to that moment in a way a silent image never could.&lt;/p&gt;

&lt;p&gt;Audio is infinitely more intimate than video or photography. It forces you to focus on the personality and how the person &lt;strong&gt;“feels”&lt;/strong&gt; rather than the appearance. You think you will remember exactly what your dad sounds like when he’s explaining something, or the pitch of your kid’s laugh right now, but human acoustic memory is notoriously bad. You won’t remember unless hearing it again.&lt;/p&gt;

&lt;p&gt;So, start building an audio album. It doesn’t have to be high production value; phone microphones are amazingly good these days. Next time you’re sitting around with your parents, record a few minutes of the banter. Ask an older relative to tell you a story you’ve heard a dozens times and get it on tape. You can thank me later.&lt;/p&gt;

&lt;h2 id=&quot;a-necessary-warning&quot;&gt;A necessary warning&lt;/h2&gt;

&lt;p&gt;Treat these recordings like sensitive documents. The technology for AI voice cloning and deep fakes is accelerating at a terrifying pace. It already only takes a minute or two of clear audio to create a passable clone of someone’s voice. For obvious reasons, you do not want your loved one’s voice data floating around in easily accessible cloud storage or public social media platforms where it could eventually be scraped and weaponized for scams.&lt;/p&gt;

&lt;p&gt;Keep these files offline. Put them on an external hard drive, maybe even encrypt them. Keep them private. They are for you, not for the internet.
Here is the text formatted with minimal Markdown for easy copying and pasting.&lt;/p&gt;

</description>
        <pubDate>Wed, 14 Jan 2026 16:34:00 +0000</pubDate>
        <link>https://dsalaj.com///2026/01/14/audio-album.html</link>
        <guid isPermaLink="true">https://dsalaj.com///2026/01/14/audio-album.html</guid>
        
        
      </item>
    
      <item>
        <title>Similarity search and Deduplication at scale</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=33567123&quot;&gt;&lt;img src=&quot;https://hackerbadge.now.sh/api?id=33567123&quot; alt=&quot;Featured on Hacker News&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the increase in the application of large-scale data collection, analytics, and accompanying big data platforms over the past decade, the necessity for reliable &lt;strong&gt;entity matching&lt;/strong&gt; solutions is proportionately growing. The newly available data volumes need to be integrated, processed and made usable before further value can be generated.&lt;/p&gt;

&lt;p&gt;The fundamental problem of entity matching (also known as &lt;a href=&quot;https://en.wikipedia.org/wiki/Record_linkage&quot;&gt;record linkage&lt;/a&gt;, data linkage, reference reconciliation, data matching, &lt;a href=&quot;https://dl.acm.org/doi/10.14778/2367502.2367564&quot;&gt;entity resolution&lt;/a&gt; just to name a few) lies at the core of many commercial and enterprise applications such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Deduplication&lt;/li&gt;
  &lt;li&gt;Similarity search&lt;/li&gt;
  &lt;li&gt;Data integration (merging of different data sources)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;which cover many different domains of application like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Retail and logistics&lt;/li&gt;
  &lt;li&gt;Ecommerce&lt;/li&gt;
  &lt;li&gt;Medical and healthcare&lt;/li&gt;
  &lt;li&gt;Advertising&lt;/li&gt;
  &lt;li&gt;Knowledge management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given multiple collections of entity representations like tables, files or text, the entity matching problem is defined as identifying all sets of entity representations that reference the same entity. Most studies in the domain of entity matching work under the assumption that the collections of entity entries on which the algorithm is applied have homogeneous structures and similar schemas. It is also often assumed that the matching identifies only the uniquely identifiable representations, ignoring the partial matches and similarity ranks. Thus, a broader problem definition was introduced under the name of &lt;a href=&quot;https://arxiv.org/abs/2106.08455&quot;&gt;Generalized Entity Matching&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://doi.org/10.1145/3418896&quot;&gt;challenges of generalized entity matching&lt;/a&gt; in the Big Data context cover almost all the general challenges of big data solutions including dealing with data variety (heterogeneous data sources), velocity (the algorithms must be performant enough to process the data volume and provide the results at the required time by the use-case), and budget-aware processing (even if the data volume can be processed under the time restrictions, the compute-budget is usually a hard constraint for a solution to be profitable). In this post I will focus on understanding the most important challenges and aspects of deduplication and similarity search which are critical for developing an effective solution based on these methods.&lt;/p&gt;

&lt;p&gt;Deduplication, in broad terms, deals with data that is already available or processed into a single data source and groups the data entries into sets that represent the same entity. A natural extension, which is usually part of the deduplication solution, is a merge and resolution algorithm that can reduce the groups of semantically equal entries into a new single entry. Deduplication is usually deployed as a background ad-hoc process in an enterprise with a goal to significantly improve the data quality. It is often part of a larger restructuring process, which can be followed by other services that ensure future data quality and prevent the need for deduplication in the future. These types of solutions are either developed internally or are provided by a B2B service.&lt;/p&gt;

&lt;p&gt;Similarity search on the other hand can be seen as a subtask within a deduplication solution, finding the same or similar entries in a data source, given a query entry or a set of attributes. The application of similarity search is broader and can often be customer-facing (B2C) through features such as document search, recommender systems, and auto-completion in data entry systems.&lt;/p&gt;

&lt;h2 id=&quot;challenges-and-constraints&quot;&gt;Challenges and constraints&lt;/h2&gt;

&lt;p&gt;When designing an entity matching-based solution, we have to take into account different considerations and nuanced relations between the methodology used and the business impact. The main question that needs to be considered is: do we need the matches between entities to have 100% confidence or not (hard matches vs soft matches)? Just imagine the logistical hell if the result of deduplication leads to the merging of two unrelated products into a single entity or the legal consequences of merging two different people into a single entry.&lt;/p&gt;

&lt;p&gt;In practice, the different scenarios usually follow one of two patterns:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The solution is applied to the data relevant to the core business, so the matches need to be done with absolute certainty. As a consequence, we will find fewer matches because of the strict matching criteria. &lt;br /&gt;
→ There must be no false positives. Precision has to be 1.&lt;/li&gt;
  &lt;li&gt;The matches are not mission critical and are used in a recommender, auto-completion, search or similar system, both customer or internal facing. This allows for a more flexible definition of a match and we will find more matches overall. &lt;br /&gt;
→ Both precision and recall are maximized.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will keep these two scenarios in mind when discussing the different methodologies.&lt;/p&gt;

&lt;h2 id=&quot;heterogeneity-of-data-sources&quot;&gt;Heterogeneity of data sources&lt;/h2&gt;

&lt;p&gt;The datasets or the collections of entity entries can be represented in various data formats. We can categorize those as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Structured (tabular data, relational database)&lt;/li&gt;
  &lt;li&gt;Semi-structured (XML, JSON, graph, tagged document)&lt;/li&gt;
  &lt;li&gt;Unstructured (PDF, text, document)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the data format is the same we can further differentiate if the collections have the same schema or not by categorizing them to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Homogeneous&lt;/li&gt;
  &lt;li&gt;Heterogeneous&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Independently of the data formats and schemas, the entries in collections can contain multiple data types:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Text&lt;/li&gt;
  &lt;li&gt;Boolean flags&lt;/li&gt;
  &lt;li&gt;Enum - generalization of boolean&lt;/li&gt;
  &lt;li&gt;List/set - generalization of many enum attributes&lt;/li&gt;
  &lt;li&gt;Binary&lt;/li&gt;
  &lt;li&gt;Graph&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When developing an entity matching solution, the above properties of the specific datasets constrain the applicable methodologies we can use.&lt;/p&gt;

&lt;p&gt;For example, if working with an unstructured dataset, we can exclude the attribute-based matching and blocking algorithms. However, if we are confident that a majority of data in the unstructured dataset reliably contains certain information, we can exploit that knowledge and extract that knowledge into attributes, and then apply the standard attribute-based matching.&lt;/p&gt;

&lt;p&gt;Another example might be the case of working in a heterogeneous setting where we are matching semi-structured JSON data with a structured relational database. In this case, we can seek to flatten and normalize the JSON. If this is not possible we can use any of the matching and blocking methods applicable to semi-structured or unstructured datasets as we can always easily cast a more structured dataset to a less structured one.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2022-10-26-similarity-search-and-deduplication/image2.png&quot; alt=&quot;types of datasets&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;controlling-the-computational-cost&quot;&gt;Controlling the computational cost&lt;/h2&gt;

&lt;p&gt;During deduplication, the algorithm needs to consider all pairs of entries. It is obvious that a naive comparison of every pair of entities in the data would lead to the O(n²) run time. In the context of big data, such a solution is infeasible even on relatively small datasets. To overcome this limitation there exist many techniques such as &lt;a href=&quot;http://ceur-ws.org/Vol-789/paper14.pdf&quot;&gt;efficient indexing&lt;/a&gt;, &lt;a href=&quot;https://arxiv.org/ftp/arxiv/papers/1006/1006.5309.pdf&quot;&gt;blocking&lt;/a&gt; or &lt;a href=&quot;https://arxiv.org/ftp/arxiv/papers/1103/1103.2410.pdf&quot;&gt;message passing techniques&lt;/a&gt;. These techniques reduce the search space and facilitate parallelization of entity matching algorithms and deployment on the distributed computing platforms which can significantly increase the efficiency and reduce time to solution.&lt;/p&gt;

&lt;p&gt;Blocking is primarily used to prevent the unfeasible evaluation of the Cartesian product of all entities, but as a consequence, the reduced search space might also exclude some positive matches. Thus the question of reliability and other properties of the blocking index, such as pair completeness (recall), pair quality (precision), and reduction ratio, is important to consider within the specific problem context. Referencing back to the challenges and constraints section, let’s consider the two defined scenarios. In scenario 1, no false positives are tolerated due to implied business consequences. A lower recall and a number of false negatives can be tolerated to a degree. In scenario 2 however, a balance between precision and recall is desirable. Some minimum level of both precision and recall is needed (true positives should outnumber false positives and if possible false negatives) in order to have a useful result in the recommender system.&lt;/p&gt;

&lt;p&gt;The most important factor to consider when choosing the blocking index is the &lt;a href=&quot;https://rosap.ntl.bts.gov/view/dot/13855&quot;&gt;cost-benefit trade-off&lt;/a&gt;. In the case of products, if we choose a high-level product category as the blocking index, the resulting blocks will be large, which leads to many unnecessary comparisons between entity pairs, which in turn leads to more computational cost and longer time to solutions. In contrast, if the blocking index is too specific, like product manufacturer and color, the resulting blocks might be too small and miss some true matches between entities that are grouped in different blocks due to bad data quality.&lt;/p&gt;

&lt;p&gt;In an optimal case, we would already have a reliable blocking key (index) but these are mostly unavailable in heterogeneous datasets and are often unreliable with a single large homogenous data source (in the products-example above, the manufacturer attribute might have multiple different values with typos or other changes for the same manufacturer).&lt;/p&gt;

&lt;p&gt;In cases where no existing attributes are available within entities that can be used as a blocking index, a synthetic (blocking) index can be computed. A variety of algorithms are available for computing the synthetic blocking index including &lt;a href=&quot;https://openresearch-repository.anu.edu.au/handle/1885/40723&quot;&gt;Bigram Indexing&lt;/a&gt;, &lt;a href=&quot;https://link.springer.com/article/10.1023/A:1009761603038&quot;&gt;Sorted Neighborhood&lt;/a&gt;, and &lt;a href=&quot;https://dl.acm.org/doi/abs/10.1145/1142473.1142599&quot;&gt;Canopy Clustering&lt;/a&gt;. The same cost-benefit trade-off applies to the synthetic blocking indexes, which are even more prone to sensitivity loss (losing the positive matches) when applied as a black box solution.&lt;/p&gt;

&lt;p&gt;For more critical solutions, one often includes some domain knowledge about the data and attributes when computing the synthetic blocking index. For example, one might exploit unreliable partitioning keys (like product manufacturer) to increase the coverage confidence (by clustering manufacturer values and using cluster indices) while still significantly reducing the search space.&lt;/p&gt;

&lt;p&gt;When dealing with data that lack useful metadata or attributes for blocking, one might have to compute the blocking index based on the content of entities. For this case, there is a possibility of using (deep learning) embeddings of data entries as the input to the clustering algorithm for producing a more reliable blocking index or finding the n-nearest-neighbors for comparison.&lt;/p&gt;

&lt;p&gt;For even more demanding use cases like continuous entity matching, please refer to &lt;a href=&quot;https://link.springer.com/article/10.1007/s11390-020-0350-4&quot;&gt;these two&lt;/a&gt; comprehensive reviews of all available state-of-the-art blocking methods.&lt;/p&gt;

&lt;p&gt;After having the search space significantly reduced with blocking, it is still critical to exploit the possible parallelization of the matching process, especially in the case of deduplication or the partial pre-computation of similarities for similarity search. One consequence of parallel matching is that the result can contain overlapping groups, so an additional merging step needs to be introduced.&lt;/p&gt;

&lt;p&gt;Further optimizations can be performed on the level of query picking (sampling strategy) during the iterative deduplication process, but are costly and highly dataset-specific.&lt;/p&gt;

&lt;h2 id=&quot;identifier-based-matching&quot;&gt;Identifier based matching&lt;/h2&gt;

&lt;p&gt;An identifier within a data source is an attribute which already matches identical entities. Every identifier is only valid on a certain scope, which typically does not cover all the available data (otherwise the problem would be already solved). It is often the case that during entity matching one has to exploit available identifiers which are incomplete, partially available, or span different scopes of the data. For example, if the dataset consists of multiple data sources, each data source can have its own unique identifiers. Some identifiers can have scopes that cover multiple data sources but only partially.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2022-10-26-similarity-search-and-deduplication/image1.png&quot; alt=&quot;overlapping partial identifiers&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To exploit such overlapping partially-available identifiers, we can employ an iterative matching method to extend the scope of entity matching to the whole dataset. The main advantage of using available identifier is the 100% confidence in the matches as required for scenario 1 in the “Challenges and constraints” above (entity matching impacting the core business processes).&lt;/p&gt;

&lt;p&gt;Partially-available identifiers can also be used as labels for training the classifiers of attribute-based or deep learning-based matching approaches.&lt;/p&gt;

&lt;p&gt;Another very impactful methodology is using the identifiers (or attributes) as exclusion criteria. Those can be used in conjunction with matching criteria in the defined order of precedence to decide if the pair of representations is a true match. One can also take it a step further and integrate the exclusion criteria in the calculation of blocking index, where the search space can be reduced even further.&lt;/p&gt;

&lt;h2 id=&quot;attribute-based-matching&quot;&gt;Attribute-based matching&lt;/h2&gt;

&lt;p&gt;Entities in structured datasets have a multitude of attributes, whose relevance for entity matching is not always clear. The similarity between individual attributes of different entities can be computed but takes on a different form depending on the data type. The following figure shows examples of the data types, their features and similarity metrics that can be computed on them.&lt;/p&gt;

&lt;table&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;strong&gt;Data type&lt;/strong&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;strong&gt;Feature&lt;/strong&gt;
   &lt;/td&gt;
   &lt;td&gt;&lt;strong&gt;Similarity / Distance metric&lt;/strong&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;Boolean
   &lt;/td&gt;
   &lt;td&gt;Boolean
   &lt;/td&gt;
   &lt;td&gt;Equality
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;Int
   &lt;/td&gt;
   &lt;td&gt;Int
   &lt;/td&gt;
   &lt;td&gt;Equality
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;Float
   &lt;/td&gt;
   &lt;td&gt;Float
   &lt;/td&gt;
   &lt;td&gt;Difference
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;Enum
   &lt;/td&gt;
   &lt;td&gt;Enum
   &lt;/td&gt;
   &lt;td&gt;Equality
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;Set (of enums or strings)
   &lt;/td&gt;
   &lt;td&gt;Set
   &lt;/td&gt;
   &lt;td&gt;Overlapping fraction
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;Geo-Coordinates
   &lt;/td&gt;
   &lt;td&gt;Geo-Coordinates
   &lt;/td&gt;
   &lt;td&gt;Euclidean distance
&lt;br /&gt;
Tunnel distance
&lt;br /&gt;
Ellipsoidal-surface distance
&lt;br /&gt;
Road distance
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;String
   &lt;/td&gt;
   &lt;td&gt;Normalized String
   &lt;/td&gt;
   &lt;td&gt;Smith-Waterman Edit distance
&lt;br /&gt;
Q-gram distance
&lt;br /&gt;
Jaro-Winkler distance
&lt;br /&gt;
Monge-Elkan distance
&lt;br /&gt;
Extended Jaccard coefficient
&lt;br /&gt;
SoftTFIDF similarity
&lt;br /&gt;
Longest Common Substring similarity
&lt;br /&gt;
Bag distance
&lt;br /&gt;
Compression distance
&lt;br /&gt;
Editex similarity
&lt;br /&gt;
Syllable Alignment distance
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;String
   &lt;/td&gt;
   &lt;td&gt;Vector Embedding
   &lt;/td&gt;
   &lt;td&gt;Euclidean distance
&lt;br /&gt;
Cosine similarity
&lt;br /&gt;
Dot product
   &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;After the similarity scores of all attributes between the two entities are computed, they need to be combined into a single similarity metric. This can be done in different ways, from domain knowledge-driven manual weighing of individual similarity scores to automated data-based methods that require a labeled dataset. For the later variant, any type of classifier model can be trained. Depending on the properties of the available dataset, one usually has to apply one of the following two approaches:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Generating the dataset with manual labeling and &lt;a href=&quot;https://www.inovex.de/de/blog/intro-to-active-learning/&quot;&gt;active learning&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Exploiting the available unique identifiers as labels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unique identifiers that are valid on a substantial subset of data are optimal to reuse for generating a labeled data set. If the scope of the unique identifier is too small, then the labeled dataset it produces might be too biased and not directly useful for training. This however can be used as a starting point for the &lt;a href=&quot;https://www.inovex.de/de/blog/intro-to-active-learning/&quot;&gt;active learning&lt;/a&gt; approach which is still better than starting from scratch.&lt;/p&gt;

&lt;p&gt;If no partial identifiers are present that can be used as a labeled dataset, then the only available alternatives are the manual weighing of the similarity matrices. This is bound to produce suboptimal results but might be used as a baseline in cases there are no alternatives. The baseline can then be used as a starting point for active learning. &lt;a href=&quot;https://www.inovex.de/de/blog/intro-to-active-learning/&quot;&gt;Active learning methodology&lt;/a&gt; supports the manual labeling process to maximize the performance gains for every labeled sample (by picking the samples for labeling based on the highest uncertainty of the classifier model).&lt;/p&gt;

&lt;p&gt;Independently of the dataset quality and the classifier confidence, with attribute matching, we can never be 100% confident in the matches as required for scenario 1 in the introduction. The only way to really use the attribute-based matching for scenario 1 is to have a manual validation step after the match generation. However, the uncertainty of the attribute-based matching is not an issue for scenario 2 where the output of the matching is only used as a recommendation generator in a business process or a customer experience.&lt;/p&gt;

&lt;h2 id=&quot;deep-learning-approaches&quot;&gt;Deep learning approaches&lt;/h2&gt;

&lt;p&gt;Despite the ongoing research &lt;a href=&quot;https://ajph.aphapublications.org/doi/abs/10.2105/AJPH.36.12.1412&quot;&gt;since 1946&lt;/a&gt; in different aspects and domains of entity matching, the problem is still open and does not have a satisfactory solution. The requirements of intensive human involvement in feature engineering, tuning, manual labeling, and integrating domain knowledge into the entity matching solution largely remain. With the advances in deep learning, novel methods enable approaching the entity matching problem from a different perspective and potentially increasing the performance and reducing the need for human involvement in the development process.&lt;/p&gt;

&lt;p&gt;Promising deep learning concepts that enable a different type of entity matching are word and document encoders. These neural networks are trained to produce embeddings in latent space whose distance should be proportional to the similarity of the entities in the target domain. Such neural-network-based encoders come in different varieties and are suited for several domains. For example, using the distributed word representations with RNNs and LSTMs, the authors of &lt;a href=&quot;https://dl.acm.org/doi/abs/10.14778/3236187.3236198&quot;&gt;DeepER&lt;/a&gt; were able to develop a novel entity matching system with high accuracy and efficiency that requires less human effort. An overview of deep learning-based entity matching approaches can be found &lt;a href=&quot;https://dl.acm.org/doi/10.1145/3442200&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While the above methods improved multiple aspects of entity matching and set the new state-of-the-art benchmark on datasets, they still rely on having available large and good-quality labeled datasets which are mostly not available in a real-world setting. Thus, novel deep learning approaches have been developed to specifically tackle the low resource settings. For example, an architecture combining transfer learning and active learning, dubbed &lt;a href=&quot;https://arxiv.org/pdf/1906.08042.pdf&quot;&gt;Deep Transfer Active Learning&lt;/a&gt;, was developed and exploits the publicly available datasets to train a high-resource model and transfer-learn to a low-resource target setting with very efficient active learning labeling, minimizing the human effort while still retaining the high performance. Another innovative deep learning approach is the &lt;a href=&quot;https://arxiv.org/pdf/2004.00584.pdf&quot;&gt;Ditto architecture&lt;/a&gt; which enables direct entity matching on datasets with heterogeneous schemas.&lt;/p&gt;

&lt;p&gt;Methods that can completely overcome the need for labeled datasets are self-supervised learning approaches, like &lt;a href=&quot;https://arxiv.org/pdf/2108.08090.pdf&quot;&gt;CollaborER&lt;/a&gt; and &lt;a href=&quot;https://arxiv.org/pdf/2112.07887.pdf&quot;&gt;KRISS&lt;/a&gt;, which achieve state-of-the-art entity matching performance and can even outperform some supervised-learning-based methods.&lt;/p&gt;

&lt;p&gt;In the follow-up post, I will cover more advanced techniques and architectures in entity matching including federated entity resolution and real-time data entity matching.&lt;/p&gt;

</description>
        <pubDate>Tue, 25 Oct 2022 23:00:00 +0000</pubDate>
        <link>https://dsalaj.com///2022/10/25/similarity-search-and-deduplication.html</link>
        <guid isPermaLink="true">https://dsalaj.com///2022/10/25/similarity-search-and-deduplication.html</guid>
        
        
      </item>
    
      <item>
        <title>Pruning and Sparsification of Neural Networks</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;The pruning practice entails targeted removal of diseased, damaged, dead, non-productive, structurally unsound, or otherwise unwanted tissue from crop and landscape plants. [&lt;a href=&quot;https://en.wikipedia.org/wiki/Pruning&quot;&gt;Wikipedia&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just as the practice of pruning helps shape and direct the growth of trees and bushes, so does pruning of synaptic connections in the brain play a critical role in learning. The use of pruning in neural network models is gaining popularity due to the many benefits it offers.&lt;/p&gt;

&lt;p&gt;Artificial neural networks (ANNs) are traditionally dense and fit the current computing paradigm and architecture of GPUs well. This match between the available hardware and ANN architectures was the major factor that led to the exciting developments in AI within the last decade.&lt;/p&gt;

&lt;p&gt;In recent years, novel ANN models have been increasing in size and complexity to such an extent that the memory and computation costs have become a major issue and the focus of the research community [&lt;a href=&quot;https://ojs.aaai.org/index.php/AAAI/article/view/7123&quot;&gt;Strubell et al. 2020&lt;/a&gt;]. Another consequence is that large models are over-parametrized, which might cause issues with generalization, as the models get too sensitive to subtle input changes [&lt;a href=&quot;https://arxiv.org/abs/1912.03925&quot;&gt;Kohler and Krzyzak 2019&lt;/a&gt;, &lt;a href=&quot;https://arxiv.org/abs/2102.00554&quot;&gt;Hoefler et al. 2021&lt;/a&gt;]. These issues are usually worked around by using various methods during the training phase, such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;L1 or L2 weight regularization&lt;/li&gt;
  &lt;li&gt;Dropout regularization variants&lt;/li&gt;
  &lt;li&gt;Data Augmentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, none of these methods deals with the fundamental issues of over-parametrization: inefficient use of memory and computation.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2021-08-15-pruning-sparsification/pruning_1.png&quot; alt=&quot;/img/2021-08-15-pruning-sparsification/pruning_1.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Pruning or sparsification is a family of methods to produce sparse neural networks. Similar to other regularization methods, pruning often leads to a better generalization of the networks [&lt;a href=&quot;https://arxiv.org/abs/1906.03728&quot;&gt;Bartoldson et al. 2020&lt;/a&gt;]. Many recent works have also shown that sparse models tend to be more robust against adversarial attacks [&lt;a href=&quot;https://arxiv.org/abs/1912.02386&quot;&gt;Cosentino et al. 2019&lt;/a&gt;; &lt;a href=&quot;https://arxiv.org/abs/1803.03880&quot;&gt;Gopalakrishnanet al.2018&lt;/a&gt;; &lt;a href=&quot;https://papers.nips.cc/paper/2018/hash/4c5bde74a8f110656874902f07378009-Abstract.html&quot;&gt;Guo et al.2018&lt;/a&gt;; &lt;a href=&quot;https://arxiv.org/abs/1908.04355&quot;&gt;Madaan et al.2020&lt;/a&gt;; &lt;a href=&quot;https://dl.acm.org/doi/10.1145/3386263.3407651&quot;&gt;Rakin et al.2020&lt;/a&gt;; &lt;a href=&quot;https://arxiv.org/abs/2002.10509&quot;&gt;Sehwag et al.2020&lt;/a&gt;; &lt;a href=&quot;https://arxiv.org/abs/2006.00896&quot;&gt;Verdenius et al.2020&lt;/a&gt;]. Sparse models have also significantly lower memory and computation costs compared to dense counterparts (often in the range of 10-100x reduction). This is especially relevant for the training phase because the large and dense models are not only very expensive during inference, but often are prohibitively costly to train [&lt;a href=&quot;https://arxiv.org/abs/2005.14165&quot;&gt;Brown et al. 2020&lt;/a&gt;It is important to keep in mind that computation and memory efficiency depend largely on the implementation of the sparse data types and operations on them. Different hardware and different libraries offer a variety of features and support for sparse network models.]. Thus, the pruning methods that are applied during training are the most interesting and beneficial for reducing computational costs.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2021-08-15-pruning-sparsification/pruning_2.png&quot; alt=&quot;/img/2021-08-15-pruning-sparsification/prunig_2.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Typical test error vs. sparsity showing Occam’s hill (results: ResNet-50 on Top-1 ImageNet). Reproduction of Fig. 4 from [&lt;a href=&quot;https://arxiv.org/abs/2102.00554&quot;&gt;Hoefler et al. 2021&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;It is important to keep in mind that computation and memory efficiency depend largely on the implementation of the sparse data types and operations on them. Different hardware and different libraries offer a variety of features and support for sparse network models.&lt;/p&gt;

&lt;h2 id=&quot;types-of-sparsity&quot;&gt;Types of sparsity&lt;/h2&gt;

&lt;p&gt;Different pruning methods can be characterized by three main aspects:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;which parts of the model are pruned&lt;/li&gt;
  &lt;li&gt;when is the pruning applied&lt;/li&gt;
  &lt;li&gt;how is the pruning implemented&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The sparsification or pruning can be permanently applied to the model, also called structural pruning, or temporarily during computation, also called ephemeral sparsification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structural pruning&lt;/strong&gt; in its basic form relates to the fine-grained pruning of weights of a neural network, but can also be applied over larger building blocks of models such as neurons, convolutional filters, and attention heads. Neural architecture search (NAS) is a family of such block pruning methods that aim to automate the search for better deep learning architectures [&lt;a href=&quot;https://arxiv.org/abs/1808.05377&quot;&gt;Elsken et al. 2019&lt;/a&gt;]. The advantage of coarser element (block) style pruning is that the block and the architecture of the model stay dense and efficiently executable on common hardware. In contrast, fine-grained pruning of weights can result in unstructured layers which can result in computation and memory overhead depending on the specific architecture and data types used. Fine-grained pruning, however, is much more flexible and when paired with specialized hardware and sparse activations (like neuromorphic chips and spiking neural networks) can result in a much stronger reduction in computation and memory requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ephemeral sparsification&lt;/strong&gt; refers to the sparsification happening online, usually dependent on the current input data samples. This type of sparsification is very common in deep learning models and include sparse activations like ReLU, which clamp the output of a neuron to zero for input values below zero, and regularization methods such as Dropout which effectively clamp the output of a random sample of neurons to zero during training. Less common methods that belong to this category include sparsification of gradients during training and conditional computation.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2021-08-15-pruning-sparsification/pruning_3.png&quot; alt=&quot;/img/2021-08-15-pruning-sparsification/pruning_3.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Overview of neural network elements that can be pruned. Reproduction of Fig. 6 from [&lt;a href=&quot;https://arxiv.org/abs/2102.00554&quot;&gt;Hoefler et al. 2021&lt;/a&gt;].&lt;/p&gt;

&lt;h2 id=&quot;when-to-prune&quot;&gt;When to prune?&lt;/h2&gt;

&lt;p&gt;Pruning can also be applied at different points during the training of the neural networks. The most trivial and the least beneficial application of pruning is after the training. In this setting, the model is sparsified after the training, which usually results in significant performance degradation. It also means that the full dense model is trained, which is the most costly process in terms of memory and computation.&lt;/p&gt;

&lt;p&gt;A better approach is using a schedule of sparsification during training. This way training is started with a dense model which is gradually sparsified during the training procedure. Different pruning schedules and implementation details [&lt;a href=&quot;https://arxiv.org/abs/1906.00586&quot;&gt;Wortsmanet al. 2019&lt;/a&gt;; &lt;a href=&quot;https://arxiv.org/abs/2006.07253&quot;&gt;Lin et al. 2020&lt;/a&gt;] make this method very flexible. The advantage of this method is that sparsification can prevent overfitting gradually during training. But it can also make convergence more unstable.&lt;/p&gt;

&lt;p&gt;[&lt;a href=&quot;https://www.sciencedirect.com/science/article/abs/pii/S0925231296000549?via%3Dihub&quot;&gt;Prechelt 1997&lt;/a&gt;] used the generalization loss to quantify the amount of overfitting and adjust the pruning rate dynamically during training. [&lt;a href=&quot;https://arxiv.org/abs/1607.05423&quot;&gt;Jin et al. 2016&lt;/a&gt;] combined the dense and sparse training in a single schedule with a method called iterative hard thresholding (IHT). [&lt;a href=&quot;https://arxiv.org/abs/1607.04381&quot;&gt;Han et al. 2017&lt;/a&gt;] used a three-step schedule (dense training to convergence, magnitude-pruning followed by retraining, and dense training) and showed that this schedule leads to significantly higher generalization performance. A follow-up extension to this method is presented in [&lt;a href=&quot;https://ieeexplore.ieee.org/document/8578988&quot;&gt;Carreira-Perpinan and Idelbayev 2018&lt;/a&gt;]. A major downside to all these approaches is that they still start with dense models which need to be held in memory and thus do not enable the use of smaller-memory devices.&lt;/p&gt;

&lt;p&gt;The last category is a fully-sparse training, where training starts with an already sparse model and trains it in the sparse regime by adding and removing weights during training. These methods often have more hyperparameters, but enable very high-dimensional models to be trained on smaller memory hardware. There is a variety of pruning and regrowth techniques that can be combined to implement a fully-sparse training scheme. For example, [&lt;a href=&quot;https://arxiv.org/abs/1902.05967&quot;&gt;Mostafa and Wang 2019&lt;/a&gt;] use random regrowth and magnitude pruning to maintain sparsity throughout training.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2021-08-15-pruning-sparsification/pruning_4.png&quot; alt=&quot;/img/2021-08-15-pruning-sparsification/pruning_4.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Overview of structural sparsification schedules. Reproduction of Fig. 7 from [&lt;a href=&quot;https://arxiv.org/abs/2102.00554&quot;&gt;Hoefler et al. 2021&lt;/a&gt;].&lt;/p&gt;

&lt;h2 id=&quot;state-of-the-art&quot;&gt;State of the art&lt;/h2&gt;

&lt;p&gt;Using sparse evolutionary training approach [&lt;a href=&quot;https://www.nature.com/articles/s41467-018-04316-3?amp=1&quot;&gt;Mocanu et al., 2018&lt;/a&gt;] demonstrates training of sparsely initialized networks by dynamically changing the connectivity with a magnitude-based pruning and random growth strategy. A related method [&lt;a href=&quot;https://arxiv.org/abs/1711.05136&quot;&gt;Bellec et al., 2018&lt;/a&gt;] demonstrates the advantage of training sparse networks with stochastic parameter updates, by sampling the sparse connectivity pattern based on a posterior which is theoretically shown to converge to a stationary distribution.&lt;/p&gt;

&lt;p&gt;Authors of [&lt;a href=&quot;http://proceedings.mlr.press/v97/mostafa19a.html&quot;&gt;Mostafa &amp;amp; Wang, 2019&lt;/a&gt;] propose dynamic sparse parameterization to train sparse networks via adaptive threshold-based pruning. In [&lt;a href=&quot;https://arxiv.org/abs/1907.04840&quot;&gt;Dettmers &amp;amp; Zettlemoyer, 2019&lt;/a&gt;] authors develop a sparse learning method using momentum-based regrowth of pruned weights.&lt;/p&gt;

&lt;p&gt;More recently, with the rising concerns about the adversarial attacks, [&lt;a href=&quot;http://proceedings.mlr.press/v139/ozdenizci21a.html&quot;&gt;Özdenizci and Legenstein 2021&lt;/a&gt;] propose an intrinsically sparse rewiring approach based on Bayesian connectivity sampling to train neural networks by simultaneously optimizing the sparse connectivity structure and the robustness-accuracy trade-off.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;In conclusion, the pruning and sparsification of neural networks can provide the following benefits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;improved generalization&lt;/li&gt;
  &lt;li&gt;robustness to adversarial attacks&lt;/li&gt;
  &lt;li&gt;memory and compute efficiency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many popular deep learning libraries already provide many built-in pruning methods:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.tensorflow.org/model_optimization/guide/pruning&quot;&gt;TensorFlow&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pytorch.org/tutorials/intermediate/pruning_tutorial.html&quot;&gt;PyTorch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;A large part of the content of this article is based on [&lt;a href=&quot;https://arxiv.org/abs/2102.00554&quot;&gt;Hoefler et al. 2021&lt;/a&gt;] and [&lt;a href=&quot;http://proceedings.mlr.press/v139/ozdenizci21a.html&quot;&gt;Özdenizci and Legenstein 2021&lt;/a&gt;]. The figures are reproduced with written permission from Prof. Hoefler.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Sat, 14 Aug 2021 23:00:00 +0000</pubDate>
        <link>https://dsalaj.com///2021/08/14/pruning-sparsification.html</link>
        <guid isPermaLink="true">https://dsalaj.com///2021/08/14/pruning-sparsification.html</guid>
        
        
      </item>
    
      <item>
        <title>All about Positional Encoding</title>
        <description>&lt;p&gt;&lt;img src=&quot;/img/2021-03-03-all-about-positional-encoding/posenc.png&quot; alt=&quot;/img/2021-03-03-all-about-positional-encoding/posenc.png&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;what-is-positional-encoding&quot;&gt;What is positional encoding?&lt;/h3&gt;

&lt;p&gt;Positional encoding was originally mentioned as a part of the Transformer architecture in the landmark paper “Attention is all you need” [&lt;a href=&quot;https://papers.nips.cc/paper/2017/hash/3f5ee243547dee91fbd053c1c4a845aa-Abstract.html&quot;&gt;Vaswani et al., 2017&lt;/a&gt;]. This concept is first introduced under the name of position embedding in [&lt;a href=&quot;http://proceedings.mlr.press/v70/gehring17a.html&quot;&gt;Gehring et al., 2017&lt;/a&gt;] where it was used in the context of sequence modelling with convolutional architectures.&lt;/p&gt;

&lt;p&gt;In the Transformer architecture, positional encoding is used to give the order context to the non-recurrent architecture of multi-head attention. Let’s unpack that sentence a bit. When the recurrent networks are fed with sequence inputs, the sequential order (ordering of time-steps) is implicitly defined by the input. However, the Multi-Head Attention layer in the Transformer is a feed-forward layer and reads a whole sequence at once. As the attention is computed on each datapoint (time-step) independently, the context of ordering between datapoints is lost and the attention is invariant to the sequence order. The same is generally true for other non-recurrent architectures like convolutional layers where only a small sequential ordering context is present, limited by the size of the convolution kernel.&lt;/p&gt;

&lt;p&gt;To alleviate this problem, the concept of positional encoding is used. This is nothing more than adding a tensor (of the same shape as the input sequence) with specific properties to the input sequence. The positional encoding tensor should be such that the value difference of the specific steps in the sequence correlates to the distance of individual steps in time (sequence).&lt;/p&gt;

&lt;h3 id=&quot;what-is-absolute-positional-encoding&quot;&gt;What is Absolute Positional Encoding?&lt;/h3&gt;

&lt;p&gt;The simplest example of positional encoding is an ordered list of values, between 0 and 1, of a length equal to the input sequence length, which is then tiled to the same number of features as the network input and added to that input.&lt;/p&gt;

&lt;p&gt;Authors of [&lt;a href=&quot;https://papers.nips.cc/paper/2017/hash/3f5ee243547dee91fbd053c1c4a845aa-Abstract.html&quot;&gt;Vaswani et al., 2017&lt;/a&gt;] however proposed a different absolute positional encoding based on the sine and cosine functions:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2021-03-03-all-about-positional-encoding/absposenc.png&quot; alt=&quot;/img/2021-03-03-all-about-positional-encoding/absposenc.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;where &lt;em&gt;pos&lt;/em&gt; is the position in time, &lt;em&gt;dmodel&lt;/em&gt; is the number of dimensions and &lt;em&gt;i&lt;/em&gt; is the dimension index in the input tensor. This way each wavelength is a geometric progression from 2π to 2kπ. To make this more clear here is a code snippet that plots this positional encoding table for an imaginary input tensor with 200 time steps and 12 channels:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;seaborn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sns&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sinusoid_positional_encoding_ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dimensions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_position_angle_vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;power&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dimensions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dimensions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;PE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_position_angle_vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;PE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# dim 2i
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;PE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# dim 2i+1
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PE&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;pe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sinusoid_positional_encoding_ref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;figure.figsize&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heatmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;invert_yaxis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;input dimension&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;time step&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Sinusoid absolute positional encoding&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/img/2021-03-03-all-about-positional-encoding/Untitled.png&quot; alt=&quot;/img/2021-03-03-all-about-positional-encoding/Untitled.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The authors hypothesize that this type of absolute positional encoding supports models in learning to attend to relative positions, as any fixed offset &lt;em&gt;k&lt;/em&gt;, PE&lt;em&gt;pos+k&lt;/em&gt; is representable as a linear function of PE&lt;em&gt;pos&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But why not just use the one-hot encoding of position? Ideally, we want the attention mechanism to be able to generalize to the input sequences longer than the ones encountered in the training set. Using the one-hot position encoding, even if the dataset contained a uniform distribution of all input lengths that the model need to generalize to, the model would still be biased as it would learn the embedding of earlier positions much better because it would encounter them more often during training.&lt;/p&gt;

&lt;p&gt;If we think about this problem, we may conclude that the same bias might occur even with the sinusoid-based absolute positional encoding. This led to a follow-up study [&lt;a href=&quot;https://arxiv.org/pdf/1803.02155.pdf&quot;&gt;Shaw et al., 2018&lt;/a&gt;] where the issue of generalizing to arbitrary input lengths is tackled, and the relative positional encoding is introduced.&lt;/p&gt;

&lt;p&gt;Another variant of absolute positional encoding exists where the position embeddings are learned jointly with the network model during training. This method suffered from the same generalization issues as the fixed absolute positional encoding methods.&lt;/p&gt;

&lt;h3 id=&quot;what-is-relative-positional-encoding&quot;&gt;What is Relative Positional Encoding?&lt;/h3&gt;

&lt;p&gt;The paper “Self-Attention with Relative Position Representations” &lt;a href=&quot;https://arxiv.org/pdf/1803.02155.pdf&quot;&gt;[Shaw et al., 2018]&lt;/a&gt; introduces the concept of relative positional encoding. This concept incorporates the explicit representations of relative position in the self-attention mechanism which significantly improves the performance of the Transformer architecture.&lt;/p&gt;

&lt;p&gt;Conceptually the relative positional encoding allows the self-attention to consider arbitrary relations between any two elements in the input. The authors of &lt;a href=&quot;https://arxiv.org/pdf/1803.02155.pdf&quot;&gt;[Shaw et al., 2018]&lt;/a&gt; focused on the efficient implementation, and the change to the self-attention equations is minimal:&lt;/p&gt;

&lt;div class=&quot;twocols&quot;&gt;
$$\text{Self-Attention}\\
z_i = \sum_{j=1}^{n}\alpha_{ij}(x_jW^V)\\
\quad \\
\alpha_{ij}=\frac{\exp e_{ij}}{\sum_{k=1}^n\exp e_{ij}}\\
\quad \\
e_{ij}=\frac{x_iW^Q(x_jW^K)^T}{\sqrt{d_z}}$$

$$\text{Relation-aware Self-Attention}\\
z_i = \sum_{j=1}^{n}\alpha_{ij}(x_jW^V + a_{ij}^V)\\
\quad \\
\alpha_{ij}=\frac{\exp e_{ij}}{\sum_{k=1}^n\exp e_{ij}}\\
\quad \\
e_{ij}=\frac{x_iW^Q(x_jW^K + a_{ij}^K)^T}{\sqrt{d_z}}$$
&lt;/div&gt;

&lt;p&gt;As we can see the only change is in the addition of the new vector to the products of key and value matrices with the input. This new vector is trained jointly with the model and is supposed to learn the additive component which is going to augment the previously mentioned product xW with the relative position context. To make it clearer let’s look at how this vector is built.&lt;/p&gt;

\[a_{ij}^K=w^K_{\text{clip}(j-i, k)}\\
a_{ij}^V=w^V_{\text{clip}(j-i, k)}\\
\text{clip}(x,k) = \max(-k, \min(k, x))\]

&lt;p&gt;So the relative distance context this vector can represent is clipped to &lt;em&gt;k&lt;/em&gt; in both directions. For example, if we have &lt;em&gt;k=3&lt;/em&gt;, we learn only the relative position embeddings up to distance 3 between the tokens. When the distance between tokens is greater than 3, the embedding returns the same value as for distance equal to 3. Here is a visualisation of such an imaginary learned positional vector:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/2021-03-03-all-about-positional-encoding/Untitled%201.png&quot; alt=&quot;/img/2021-03-03-all-about-positional-encoding/Untitled%201.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The main advantage of this method is that the positional embedding depends only on the relative distance between the tokens, and not on their absolute position in the sequence. This should lead to a more robust generalization of the attention beyond the sequence lengths present in the training set. This has been demonstrated in &lt;a href=&quot;https://arxiv.org/pdf/1803.02155.pdf&quot;&gt;[Shaw et al., 2018]&lt;/a&gt; by achieving significantly better results than the models with absolute positional encoding. More methodical comparison of the two methods has been conducted in [&lt;a href=&quot;https://www-i6.informatik.rwth-aachen.de/publications/download/1132/RosendahlJanTranVietAnhKhoaWangWeiyueNeyHermann--AnalysisofPositionalEncodingsforNeuralMachineTranslation--2019.pdf&quot;&gt;Rosendahl et al., 2019&lt;/a&gt;] where it is again shown that the relative positional encoding is superior when translating sequences that are longer than any observed training sequence&lt;/p&gt;

&lt;h3 id=&quot;what-is-rnn-based-positional-encoding&quot;&gt;What is RNN based positional encoding?&lt;/h3&gt;

&lt;p&gt;Since recurrent layers have implicit information about the order of input sequence, these have often been used as a layer preceding the Transformer or any other attention mechanism to endow the input sequence with the order context. This type of RNN+Attention architecture was usually trained jointly which often leads to the result where RNN is able to perform a lot of the computation required for solving the task and not only give the positional embedding to the input.&lt;/p&gt;

&lt;p&gt;Transformers trained directly on the input sequences allow for easier interpretation, as the attention layers can be probed to reveal the learned relationships between elements in the input sequence. When an RNN is placed in front of the Transformer, the input gets convoluted which makes such interpretations impossible.&lt;/p&gt;

&lt;h3 id=&quot;positional-encoding-for-tree-structured-data&quot;&gt;Positional encoding for tree-structured data&lt;/h3&gt;

&lt;p&gt;So far we discussed positional encoding use for processing sequential data with attention based architecture. However there is a growing interest in applying the attention methods on the tree-structured data and tasks like programming language analysis, language parse trees translation, and semantic parsing like extracting a database query from a natural language request.&lt;/p&gt;

&lt;p&gt;The paper [&lt;a href=&quot;https://papers.nips.cc/paper/2019/file/6e0917469214d8fbd8c517dcdc6b8dcf-Paper.pdf&quot;&gt;Shiv and Quirk, 2019&lt;/a&gt;] introduces tree positional encoding using a stack-like encoding for tree positions. The authors demonstrate a significant increase in the performance of transformers using tree positional encodings for a multitude of tasks compared to the original sequence focused transformers.&lt;/p&gt;

&lt;h3 id=&quot;how-to-do-positional-encoding-for-irregularly-sampled-data&quot;&gt;How to do positional encoding for irregularly sampled data?&lt;/h3&gt;

&lt;p&gt;There are quite a few options for dealing with irregularly sampled data, or time-series data with non-equidistant timesteps. I discuss this in more details in a different post:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/2020/06/21/deep-learning-on-time-series.html&quot;&gt;Corrupt, sparse, irregular and ugly: Deep learning on time series&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 02 Mar 2021 23:00:00 +0000</pubDate>
        <link>https://dsalaj.com///2021/03/02/all-about-positional-encoding.html</link>
        <guid isPermaLink="true">https://dsalaj.com///2021/03/02/all-about-positional-encoding.html</guid>
        
        
      </item>
    
      <item>
        <title>How to migrate binary bloat out of git repository</title>
        <description>&lt;div class=&quot;page-body&quot;&gt;&lt;p id=&quot;907bc591-58b8-48fe-91c9-bfb7e0d06966&quot; class=&quot;&quot;&gt;&lt;strong&gt;The situation:&lt;/strong&gt; A project has several binaries that need to be tracked and versioned along with the code. The binaries are small enough and rarely change, so versioning them directly in git is appropriate.&lt;/p&gt;&lt;p id=&quot;2fee7b63-0896-4010-9121-a47da3d687af&quot; class=&quot;&quot;&gt;That was some months ago, and in the meantime, the project evolved, binaries grew and changed. Now you&apos;re left with a bloated repository of multiple gigabytes that takes a long time to clone. This is significantly slowing down the CI pipeline and it&apos;s time to fix it.&lt;/p&gt;&lt;h2 id=&quot;6a23a05c-f86a-44fc-8c27-1a6fd0debdec&quot; class=&quot;&quot;&gt;Dealing with symptoms directly&lt;/h2&gt;&lt;p id=&quot;4d799a62-5fcf-48b8-b398-24de358368ae&quot; class=&quot;&quot;&gt;There are many options to solve this problem, all with unique pros and cons. The simplest solution is dealing only with problematic symptoms like slow CI pipeline. This can be overcome with one of the following:&lt;/p&gt;&lt;ul id=&quot;a4d928e3-99ad-4c47-8e1e-00b7fe1b5ea9&quot; class=&quot;bulleted-list&quot;&gt;&lt;li&gt;Shallow clone &lt;code&gt;git clone --depth 1 URL&lt;/code&gt;: Limiting the depth of the clone means that the history is not pulled. &lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;bbad9cea-fc88-4976-bd08-5786bcaeb16e&quot; class=&quot;bulleted-list&quot;&gt;&lt;li&gt;Clone without binary files &lt;code&gt;git clone --filter=blob:none URL&lt;/code&gt;: The filter option is more powerful and can be used filter only specific files that meet specific criteria. See &lt;a href=&quot;https://github.com/git/git/blob/d98273ba77e1ab9ec755576bc86c716a97bf59d7/Documentation/rev-list-options.txt#L869&quot;&gt;docs&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;ac2c38f0-fc62-4ded-be0f-e3410dfb99c3&quot; class=&quot;bulleted-list&quot;&gt;&lt;li&gt;Finally, if the large binary file size is not your problem but the large number of files, you should look into &lt;code&gt;git sparse-checkout&lt;/code&gt;. See &lt;a href=&quot;https://git-scm.com/docs/git-sparse-checkout&quot;&gt;docs&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;42b388e0-b311-4a54-8629-847c1966834f&quot; class=&quot;&quot;&gt;But sometimes these workarounds are not enough and you need to rewrite the repo history. Below I will discuss the two solutions that should cover most of the usecases. The first option is  migrating to the &lt;code&gt;git lfs&lt;/code&gt;. The second option is pruning the binaries from the repo history using &lt;code&gt;git filter-repo&lt;/code&gt; and versioning the binaries in a separate versioning system.&lt;/p&gt;&lt;h2 id=&quot;95da721f-0685-4fd3-b43c-7862ef86cb85&quot; class=&quot;&quot;&gt;Migrating to &lt;code&gt;git lfs&lt;/code&gt;&lt;/h2&gt;&lt;p id=&quot;2f6b6dd0-0b0d-4183-bb39-00efca470d21&quot; class=&quot;&quot;&gt;The main advantage of the migration to &lt;code&gt;git lfs&lt;/code&gt; is that the repo history is left intact and no information is lost. This method is recommended when the binaries are really tightly coupled with the code. This is easily done with the following steps:&lt;/p&gt;&lt;ul id=&quot;7a4486db-1bb5-4f5e-bb14-8302fe5b5d7e&quot; class=&quot;bulleted-list&quot;&gt;&lt;li&gt;Install the git-lfs using this &lt;a href=&quot;https://github.com/git-lfs/git-lfs/wiki/Installation&quot;&gt;guide&lt;/a&gt; or in conda like so:
&lt;code&gt;conda install -c conda-forge git-lfs&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;136e92fe-b98f-40ec-990b-4c213d4a09cb&quot; class=&quot;bulleted-list&quot;&gt;&lt;li&gt;In your repo, run: &lt;code&gt;git lfs install&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul id=&quot;c37e7873-1352-4e38-9276-4ed2bfa38eb8&quot; class=&quot;bulleted-list&quot;&gt;&lt;li&gt;Rewrite history. For example migrating all bz2 files:
&lt;code&gt;git lfs migrate import --include-ref=master --include=&quot;*.bz2&quot;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p id=&quot;5f882e5c-d19d-459f-9677-eb3f7f128e09&quot; class=&quot;&quot;&gt;For more details on how to match your usecase see &lt;a href=&quot;https://github.com/git-lfs/git-lfs/wiki/Tutorial#migrating-existing-repository-data-to-lfs&quot;&gt;this guide&lt;/a&gt;.&lt;/p&gt;&lt;p id=&quot;6095bb85-e0ca-484d-82f8-869c3867f3e7&quot; class=&quot;&quot;&gt;The downside of using &lt;code&gt;git lfs&lt;/code&gt; is that it adds more complexity to the workflow of developers. Decisions need to be made: Which files are to be versioned with git and which with &lt;code&gt;git lfs&lt;/code&gt;? Do you decide based on the file size or the file format/extension? The &lt;code&gt;.gitattributes&lt;/code&gt; file needs to be maintained etc.&lt;/p&gt;&lt;p id=&quot;27da68da-cd07-4535-8c4f-60b5f5c71462&quot; class=&quot;&quot;&gt;You get the gist, there is overhead and nobody likes overhead. But if the binary files are really tightly coupled with the code and need to be version, this is the way to go.&lt;/p&gt;&lt;h2 id=&quot;3b7518d8-e554-4a14-a38b-93a34c4caaa9&quot; class=&quot;&quot;&gt;Pruning and migrating out of git&lt;/h2&gt;&lt;p id=&quot;fc89422d-550b-4a9a-9200-c6f9b104e10f&quot; class=&quot;&quot;&gt;When the binaries are not tightly coupled with the code there is another solution: simply prune away all the binary files from the repo history and version them in a separate, more appropriate system.&lt;/p&gt;&lt;p id=&quot;6d57c9d1-ebdf-4313-b89d-492fc83326a2&quot; class=&quot;&quot;&gt;The pruning part is simple thanks to the amazing &lt;a href=&quot;https://github.com/newren/git-filter-repo&quot;&gt;&lt;code&gt;git filter-repo&lt;/code&gt;&lt;/a&gt; tool. For example, pruning away all the binary files larger than 10 MB can be done using the &lt;a href=&quot;https://docs.gitlab.com/ee/user/project/repository/reducing_the_repo_size_using_git.html#repository-cleanup&quot;&gt;guide from GitLab&lt;/a&gt;. For more elaborate cases please refer to the official &lt;a href=&quot;https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES&quot;&gt;documentation with examples&lt;/a&gt;.&lt;/p&gt;&lt;p id=&quot;f4cc1de1-b07e-40c7-9ce7-61d0622baee9&quot; class=&quot;&quot;&gt;After the pruning, your repo should be very lean, and you are free to version or track the binaries outside of git. For example, in the project I was working on the &lt;a href=&quot;https://mlflow.org/&quot;&gt;&lt;code&gt;mlflow&lt;/code&gt;&lt;/a&gt; was the appropriate tool we decided on after some trial period. Using the &lt;code&gt;mlflow&lt;/code&gt; &lt;a href=&quot;https://mlflow.org/docs/latest/python_api/index.html&quot;&gt;Python API&lt;/a&gt; it was easy to track any artifacts and results along with the meta-data which matched the needs of the project well.&lt;/p&gt;&lt;p id=&quot;03957dad-c639-4d19-b6dd-c83bc9bd6390&quot; class=&quot;&quot;&gt;The obvious downside is that you lose the history of the binary files. This was the trade-off we were willing to take as the history of the binary files was not very valuable, and we still had access to it in the backups of the repo we made before the prune.&lt;/p&gt;&lt;p id=&quot;e8719630-30f4-47b2-8663-407561572c8d&quot; class=&quot;&quot;&gt;
&lt;/p&gt;&lt;p id=&quot;76ab4e36-2b97-4d4e-94dd-fd399c6d71a0&quot; class=&quot;&quot;&gt;Hope this was helpful and you were able to get some useful pointers and links that will help with your git endeavors. Let me know if you found a different solution. Cheers! 🍻&lt;/p&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 24 Oct 2020 23:00:00 +0000</pubDate>
        <link>https://dsalaj.com///2020/10/24/migrate-binary-bloat-out-of-git-repository.html</link>
        <guid isPermaLink="true">https://dsalaj.com///2020/10/24/migrate-binary-bloat-out-of-git-repository.html</guid>
        
        
      </item>
    
      <item>
        <title>Corrupt, sparse, irregular and ugly: Deep learning on time series</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=23591157&quot;&gt;&lt;img src=&quot;https://hackerbadge.now.sh/api?id=23591157&quot; alt=&quot;Featured on Hacker News&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Update 24.06.2020: Thanks to &lt;a href=&quot;https://news.ycombinator.com/user?id=BadInformatics&quot;&gt;BadInformatics&lt;/a&gt; for pointing me to ODE based models and other remarks. The content was extended accordingly. &lt;br /&gt;
Update 22.08.2020: Extended the details on missing values; Replaced the first figure with example and code; Added tip for Traces library. &lt;br /&gt;
Update 01.11.2021: Added Multi-Time Attention Nets and Neural Rough Differential Equations method&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How to train neural networks on time-series that are non-uniformly sampled / irregularly sampled / have non-equidistant timesteps / have missing or corrupt values? In the following post, I try to summarize and point to effective methods for dealing with such data.&lt;/p&gt;

&lt;h2 id=&quot;what-is-irregularly-sampled-data-or-sequence-of-non-equidistant-steps-&quot;&gt;What is irregularly sampled data or sequence of non-equidistant steps? 📊&lt;/h2&gt;

&lt;p&gt;Time series where the time between the individual steps/measurements is not constant is called non-uniform or irregularly sampled. Irregularly sampled data occurs in many fields:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Meteorological data&lt;/li&gt;
  &lt;li&gt;Astronomical data&lt;/li&gt;
  &lt;li&gt;Electronic health records (EHRs)&lt;/li&gt;
  &lt;li&gt;Turbulence data&lt;/li&gt;
  &lt;li&gt;Automotive data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is also common in cases where the data is multi-modal. &lt;strong&gt;Multi-modal&lt;/strong&gt; input means that the input is coming from multiple different sources which most likely operate and take measurements not synchronized with each other resulting in the non-uniform input data.&lt;/p&gt;

&lt;p&gt;Another source of the irregularity in sampling can be &lt;strong&gt;missing or corrupt values&lt;/strong&gt;. This is very common in both automotive and EHR data where sensors malfunction or procedures are interrupted or rescheduled.&lt;/p&gt;

&lt;h2 id=&quot;why-not-just-interpolate-&quot;&gt;Why not just interpolate? 💡&lt;/h2&gt;

&lt;p&gt;The first idea you might have is to interpolate and resample the time series data at hand. This will produce a uniformly sampled grid and allows for standard methods to be applied. However, this approach works under the strong assumption that the interpolated data behaves monotonically between the measurements. This assumption often does not hold which leads to undesired artifacts during feature transformation and in turn to a sub-par performance (sometimes worse than training on the raw data).&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;💡 If you are looking for help in transforming unevenly-spaced times series to evenly-spaced ones, check out the &lt;a href=&quot;https://traces.readthedocs.io/en/latest/index.html&quot;&gt;Traces python library&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another factor to consider before interpolating is the distribution of the sizes of timesteps. The easiest way to do this is to plot the histogram of &lt;strong&gt;dt&lt;/strong&gt;-s (time differences) between data points. If the values of &lt;strong&gt;dt&lt;/strong&gt; are relatively large, it is unlikely that the measurements in between the points behave monotonically. Furthermore, you should check the variance of &lt;strong&gt;dt&lt;/strong&gt; and decide whether it is “sufficiently” uniform to apply the classical methods or not, as sometimes it turns out that the data is “uniform enough” (see the &lt;a href=&quot;https://www.notion.so/Deep-learning-on-irregularly-sampled-data-887b823df439417bb8428a3474d939b3#9bd6dc2996184941bc37df30e6949047&quot;&gt;next section&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;An example of &lt;strong&gt;dt&lt;/strong&gt; distribution of a real world dataset (&lt;a href=&quot;https://gea.esac.esa.int/archive/&quot;&gt;Gaia European space mission Data Release 2&lt;/a&gt;) with irregular time series is shown in the plot below. The plot is generated using this &lt;a href=&quot;https://github.com/dsalaj/LombScargleSpectrogram/blob/master/Irregular_timeseries_dataset_example.ipynb&quot;&gt;python notebook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Ffa96d2de-8e28-413a-97a4-e2574c5efdce%2FUntitled.png?table=block&amp;amp;id=250e6804-0cff-4fb4-9258-ccffb1949b2b&amp;amp;width=1460&amp;amp;userId=&amp;amp;cache=v2&quot; alt=&quot;Figure showing distribution of dt in a dataset&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Another factor to consider is the computational and memory cost of interpolation which depends on both the size of your dataset (if you plan to do it offline) and the targeting granularity of the interpolation grid.&lt;/p&gt;

&lt;p&gt;However, if you have a sufficiently large amount of data where you could learn the underlying distributions, then it might be worth looking into the methods for data recovery and super-resolution which I describe in the &lt;a href=&quot;https://www.notion.so/Deep-learning-on-irregularly-sampled-data-887b823df439417bb8428a3474d939b3#f702f97d712f407eade4981b55b178a5&quot;&gt;section below&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;solving-the-problem-by-ignoring-the-problem-&quot;&gt;Solving the problem by ignoring the problem 🙈&lt;/h2&gt;

&lt;p&gt;There are cases when the variance in the &lt;strong&gt;dt&lt;/strong&gt;-s is small enough and the methods for regularly sampled data can produce surprisingly good results. I would highly suggest first creating a baseline with one such method. For example, you can use any STFT based spectrogram (like MFCC) or any other appropriate spectrogram and train the model using such input.&lt;/p&gt;

&lt;p&gt;Having a strong baseline is critical for evaluation of the more advanced input processing methods and the decision if they make sense for your specific setup.&lt;/p&gt;

&lt;h2 id=&quot;what-are-the-methods-for-working-with-irregular-or-sparse-time-series-️&quot;&gt;What are the methods for working with irregular or sparse time series? ⚗️&lt;/h2&gt;

&lt;p&gt;If the distribution of &lt;strong&gt;dt&lt;/strong&gt; is wide in your dataset, then there are several methods for directly dealing with irregularly/nonuniformly sampled data that are worth looking into:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.notion.so/Corrupt-sparse-irregular-and-ugly-Deep-learning-on-time-series-887b823df439417bb8428a3474d939b3#6a427f558ab54ee884324ba0fff50e47&quot;&gt;&lt;strong&gt;Lomb-Scargle&lt;/strong&gt; Periodogram&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Data modeling with &lt;strong&gt;&lt;a href=&quot;https://www.notion.so/Corrupt-sparse-irregular-and-ugly-Deep-learning-on-time-series-887b823df439417bb8428a3474d939b3#856d58ed133a4847ada94bb8f2790def&quot;&gt;Interpolation networks&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.notion.so/Corrupt-sparse-irregular-and-ugly-Deep-learning-on-time-series-887b823df439417bb8428a3474d939b3#7754c66cef074827813102ffe3f60f83&quot;&gt;Neural Ordinary Differential Equation&lt;/a&gt;&lt;/strong&gt; models ✨&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.notion.so/Corrupt-sparse-irregular-and-ugly-Deep-learning-on-time-series-887b823df439417bb8428a3474d939b3#42ecb5b5317747878a063835757cad18&quot;&gt;Add timing &lt;strong&gt;dt&lt;/strong&gt; to the input&lt;/a&gt; as an additional feature (or positional encoding)&lt;/li&gt;
  &lt;li&gt;Methods for &lt;a href=&quot;https://www.notion.so/Corrupt-sparse-irregular-and-ugly-Deep-learning-on-time-series-887b823df439417bb8428a3474d939b3#f702f97d712f407eade4981b55b178a5&quot;&gt;dealing with missing values&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;how-to-use-lomb-scargle-periodograms&quot;&gt;How to use Lomb-Scargle Periodograms?&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; Here is a &lt;a href=&quot;https://github.com/dsalaj/LombScargleSpectrogram/blob/master/Lomb-Scargle_spectrogram_example.ipynb&quot;&gt;&lt;strong&gt;python notebook&lt;/strong&gt;&lt;/a&gt; that shows how to compute a spectrogram of irregularly sampled data using Lomb-Scargle method.&lt;/p&gt;

&lt;p&gt;If one wants an actual spectral analysis of non-uniformly sampled signals, then &lt;strong&gt;Lomb-Scargle periodogram&lt;/strong&gt; is a classical method solving the problem. The method is similar to the Fourier Power Spectral Density (PSD), the most popular method for periodicity detection in uniformly/regularly sampled data. Lomb-Scargle Periodogram algorithm has been implemented in many libraries (&lt;a href=&quot;https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lombscargle.html&quot;&gt;scipy,&lt;/a&gt; &lt;a href=&quot;https://jakevdp.github.io/blog/2015/06/13/lomb-scargle-in-python/&quot;&gt;gatsby&lt;/a&gt;, &lt;a href=&quot;https://docs.astropy.org/en/stable/timeseries/lombscargle.html&quot;&gt;astropy&lt;/a&gt;, &lt;a href=&quot;https://www.mathworks.com/help/signal/examples/spectral-analysis-of-nonuniformly-sampled-signals.html&quot;&gt;matlab&lt;/a&gt;), out of which the &lt;a href=&quot;https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.lombscargle.html&quot;&gt;scipy&lt;/a&gt; version should be the most maintained one.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Lomb-Scargle periodogram was developed by Lomb [Lomb, N.R., 1976] and further extended by Scargle [Scargle, J.D., 1982] to find, and test the significance of weak periodic signals with uneven temporal sampling. [scipy docs]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A &lt;a href=&quot;https://en.wikipedia.org/wiki/Periodogram&quot;&gt;periodogram&lt;/a&gt; is an estimate of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Spectral_density&quot;&gt;spectral density&lt;/a&gt; of a signal. These libraries provide a method to compute a periodogram (spectral analysis) on a sequence of irregularly sampled values. However, for deep learning we usually need the spectrogram and not a single periodogram.&lt;/p&gt;

&lt;p&gt;A &lt;a href=&quot;https://en.wikipedia.org/wiki/Spectrogram&quot;&gt;spectrogram&lt;/a&gt; is a representation of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Spectral_density&quot;&gt;spectral density&lt;/a&gt; of &lt;a href=&quot;https://en.wikipedia.org/wiki/Frequencies&quot;&gt;frequencies&lt;/a&gt; of a signal over time. Thus, we can produce a spectrogram by computing the periodogram over time bins of a signal or time series. Example code on how to do this and that reproduces the figures below, can be found &lt;a href=&quot;https://github.com/dsalaj/LombScargleSpectrogram/blob/master/Lomb-Scargle_spectrogram_example.ipynb&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The figure below demonstrates the potential loss of information if we ignore the timing information about the irregular sampling of the data. The figure compares the Short-time Fourier Transform (STFT) based spectrogram (MFCC), which assumes regular sampling, with Lomb-Scargle based spectrogram, which takes &lt;strong&gt;dt&lt;/strong&gt; as additional input. In the top row, we see the signal plot over time-steps (left) and over time (right). This exaggerated synthetic example makes it obvious that the &lt;strong&gt;dt&lt;/strong&gt; can have a significant impact on the signal spectra and thus the spectrogram that does not take the &lt;strong&gt;dt&lt;/strong&gt; into account (bottom left plot) can not detect the true spectral representation of the signal. In the bottom right, the Lomb-Scargle spectrogram is able to capture the change in the signal well.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F273f45a6-327a-43c5-9a01-c57a2ee2c5bd%2Flscomp.png?table=block&amp;amp;id=3838b05d-a8cd-4794-b381-b26e61735064&amp;amp;width=1730&amp;amp;userId=8eb9d5ca-14ef-479b-b6f4-d6303eb1f8d1&amp;amp;cache=v2&quot; alt=&quot;Figure showing the difference between MFCC and Lomb-Scargle periodogram&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For further details and more advanced applications of Lomb-Scargle method refer to the following links:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/1703.09824&quot;&gt;Lomb-Scargle intuition and important practical considerations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/1502.01344&quot;&gt;Extension of Lomb-Scargle to multiband periodogram&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://ui.adsabs.harvard.edu/abs/2015A%26A...573A.101M/abstract&quot;&gt;Bayesian formalism for the generalised Lomb-Scargle periodogram&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;what-are-interpolation-networks&quot;&gt;What are interpolation networks?&lt;/h3&gt;

&lt;p&gt;Researchers dealing with time series data in EHRs are developing data modelling methods that can make use of extremely sparse and irregular data. These models are usually evaluated on classification or regression tasks like predicting the onset or probability of sepsis based on the physiological measurements of a patient.&lt;/p&gt;

&lt;p&gt;The common approach involves two stages where the first stage models the trajectories of the irregular and sparse physiological measurements, and the second stage is a common black box prediction neural network.&lt;/p&gt;

&lt;p&gt;For example, the first stage in [&lt;a href=&quot;https://arxiv.org/pdf/1909.07782.pdf&quot;&gt;Shukla and Marlin, 2019&lt;/a&gt;] uses a semi-parametric &lt;strong&gt;interpolation network&lt;/strong&gt; [&lt;a href=&quot;https://github.com/mlds-lab/interp-net&quot;&gt;github&lt;/a&gt;] to model the data by learning three distinct features: a smooth interpolation for slow trends in the signal, a short time-scale interpolation for transients, and an intensity function for local observation frequencies. An earlier work [&lt;a href=&quot;http://proceedings.mlr.press/v70/futoma17a.html&quot;&gt;Futoma et al., 2017&lt;/a&gt;] implements the first stage with &lt;strong&gt;multi-task Gaussian processes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These models attempt to recover the missing information from time-series but only in latent space as the models are trained end-to-end with the prediction neural network on top. However, if your time-series have missing data points, approaches outlined in the &lt;a href=&quot;https://www.notion.so/Corrupt-sparse-irregular-and-ugly-Deep-learning-on-time-series-887b823df439417bb8428a3474d939b3#f702f97d712f407eade4981b55b178a5&quot;&gt;section below&lt;/a&gt; should be more applicable.&lt;/p&gt;

&lt;p&gt;For the scenarios where you have different input channels operating at different frequencies (&lt;strong&gt;multi-rate multivariate time series&lt;/strong&gt;) you should look into [&lt;a href=&quot;http://proceedings.mlr.press/v80/che18a.html&quot;&gt;Che et al., 2018b&lt;/a&gt;] where the authors deal with this problem using the Multi-Rate Hierarchical Deep Markov Model (&lt;strong&gt;MR-HDMM&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;For working with physiological signals, it is common to use some form of CNN and/or RNN based architecture [&lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S0169260718301226?casa_token=rPpzFoZxdoMAAAAA:D5P_nzHX0cwVXk9LCy_RFqHnZPDMnmik8sucMtldxHwzZCnti4WFmlwX7O4ICoVE4SMNBXdZQZA&quot;&gt;Faust et al., 2018&lt;/a&gt;, &lt;a href=&quot;https://link.springer.com/article/10.1007/s10618-019-00619-1&quot;&gt;Fawaz et al., 2019&lt;/a&gt;] like 1-D &lt;strong&gt;ResNet&lt;/strong&gt; or architectures based on &lt;strong&gt;WaveNet&lt;/strong&gt; sometimes combined with &lt;strong&gt;LSTM&lt;/strong&gt; or other RNNs.&lt;/p&gt;

&lt;p&gt;For efficiently training on sparse, irregularly sampled, and multivariate data the new model called Multi-Time Attention Networks by [&lt;a href=&quot;https://openreview.net/forum?id=4c0J6lwQ4_&quot;&gt;Shukla and Marlin 2021&lt;/a&gt;] offers great results beating the SOTA benchmarks.&lt;/p&gt;

&lt;h3 id=&quot;what-are-neural-ordinary-differential-equation-models&quot;&gt;What are Neural Ordinary Differential Equation models?&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ODE-RNNs&lt;/strong&gt; [&lt;a href=&quot;http://papers.nips.cc/paper/8773-latent-ordinary-differential-equations-for-irregularly-sampled-time-series&quot;&gt;Rubanova et al., 2019&lt;/a&gt;] are a novel model that builds upon the original idea of NeuralODEs [&lt;a href=&quot;https://papers.nips.cc/paper/7892-neural-ordinary-differential-equations&quot;&gt;Chen et al., 2018&lt;/a&gt;] by generalizing the RNNs to have continuous-time hidden dynamics. In short, they are a natural fit to solve irregularly sampled time series data problems and outperform the RNN counterparts in that domain. This is best summarized in this excerpt from the paper abstract:&lt;/p&gt;

&lt;p&gt;“&lt;em&gt;Both ODE-RNNs and Latent ODEs can naturally handle arbitrary time gaps between observations, and can explicitly model the probability of observation times using Poisson processes. We show experimentally that these ODE-based models outperform their RNN-based counterparts on irregularly-sampled data.”&lt;/em&gt;
[&lt;a href=&quot;http://papers.nips.cc/paper/8773-latent-ordinary-differential-equations-for-irregularly-sampled-time-series&quot;&gt;Rubanova et al., 2019&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fc0199ff6-9d4c-4c72-b983-de233b3af074%2FUntitled.png?table=block&amp;amp;id=9259cff3-ad0d-4c65-b0bd-c4221c857357&amp;amp;width=380&amp;amp;userId=8eb9d5ca-14ef-479b-b6f4-d6303eb1f8d1&amp;amp;cache=v2&quot; alt=&quot;Figure 1 from Rubanova et al. 2019&quot; /&gt;&lt;/p&gt;
&lt;center&gt;Figure 1  [Rubanova et al., 2019]&lt;/center&gt;

&lt;p&gt;A downside of the ODE based models is that the solution to an ordinary differential equation is determined by its initial condition. The follow-up work [&lt;a href=&quot;https://arxiv.org/pdf/2005.08926.pdf&quot;&gt;Kidger et al., 2020&lt;/a&gt;] deals with this issue using the &lt;em&gt;controlled differential equations&lt;/em&gt; and set the new state-of-the-art. The newly introduced &lt;strong&gt;Neural CDE&lt;/strong&gt; outperforms ODE-RNNs and GRU-D models on CharacterTrajectories, PhysioNet, and Speech Commands dataset.&lt;/p&gt;

&lt;h3 id=&quot;how-to-make-an-input-feature-out-of-timestamps-️&quot;&gt;How to make an input feature out of timestamps? ⏱️&lt;/h3&gt;

&lt;p&gt;Usually, timseries data contains a timestamp for each data point. The first thing to do is to convert the timestamps to delta t-s (&lt;strong&gt;dt&lt;/strong&gt;s). Next, you will need to perform a cumulative sum on the &lt;strong&gt;dt&lt;/strong&gt; feature to get a monotonically increasing value. Finally, you might need to standardize the values (scale to the range [0, 1]) if your model always works with uniformly long sequences at the input.&lt;/p&gt;

&lt;p&gt;Depending on the problem, if your model is sometimes working on a subsequence of a much longer input stream and needs to be aware of the position in the stream, then computing a cumulative sum of &lt;strong&gt;dt&lt;/strong&gt;s beforehand might be required and the standardization needs to be omitted. Otherwise, the model would not receive the contextual information (position in the input stream) which could potentially have a significant impact on the performance of the model.&lt;/p&gt;

&lt;p&gt;Finally, the newly computed feature can be provided to the models as additional input.&lt;/p&gt;

&lt;p&gt;This method can also be seen as a form of &lt;strong&gt;positional encoding of the Transformer&lt;/strong&gt; to deal with irregularly sampled data. The added &lt;strong&gt;dt&lt;/strong&gt; based feature allows the attention layer to compute the similarity (distance) between the data points using the &lt;strong&gt;precise timing information&lt;/strong&gt; in addition to the other features.&lt;/p&gt;

&lt;h3 id=&quot;how-to-deal-with-missing-values-in-time-series-&quot;&gt;How to deal with missing values in time-series? 🔍&lt;/h3&gt;

&lt;p&gt;To effectively model the &lt;a href=&quot;https://en.wikipedia.org/wiki/Missing_data&quot;&gt;data with missing values&lt;/a&gt; it is important to understand the cause of the missing data. For example, if the data is missing at random, the rest of the data is still representative and well suited for modelling. However, if the missing values do not occur at random, the rest of the data will be biased. In statistics, different types of missing data are classified as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Missing completely at random (&lt;strong&gt;MCAR&lt;/strong&gt;)&lt;/li&gt;
  &lt;li&gt;Missing at random (&lt;strong&gt;MAR&lt;/strong&gt;)&lt;/li&gt;
  &lt;li&gt;Missing not at random (&lt;strong&gt;MNAR&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To minimize the work required to analyze, identify and deal with these different types of missing values, deep learning methods have been developed that can deal with these issues directly. Such models take the information about the missing values along with the available data and are trained end-to-end for a specific task, resulting in more accurate models that are aware of the statistics of the missing values.&lt;/p&gt;

&lt;p&gt;For dealing with missing values in multivariate time series the authors of [&lt;a href=&quot;https://www.nature.com/articles/s41598-018-24271-9&quot;&gt;Che et al., 2018a&lt;/a&gt;] propose the &lt;strong&gt;GRU-D&lt;/strong&gt; model which ingests the explicit representation of missing values (masking and time interval) and incorporates them into the architecture. This way the model can exploit not only the long-term temporal dependencies but also the patterns of missing values.&lt;/p&gt;

&lt;p&gt;Beware that &lt;strong&gt;ODE-RNNs&lt;/strong&gt; [&lt;a href=&quot;http://papers.nips.cc/paper/8773-latent-ordinary-differential-equations-for-irregularly-sampled-time-series&quot;&gt;Rubanova et al., 2019&lt;/a&gt;] outperform &lt;strong&gt;GRU-D&lt;/strong&gt; on some benchmarks.&lt;/p&gt;

&lt;p&gt;If you have a vast amount of data, it might also be fruitful to look into the methods for the reconstruction of irregularly and regularly missing data [[Chai et al.]](https://www.nature.com/articles/s41598-020-59801-x#Bib1). This is an analogous approach to the image and audio super-resolution networks. Using this approach you can learn the underlying distribution of your data which is usually a crucial factor in getting a high performing model.&lt;/p&gt;

&lt;h3 id=&quot;further-reading-&quot;&gt;Further reading 📚&lt;/h3&gt;

&lt;p&gt;If you wish for more references to papers dealing with this topic, I would highly recommend the related work section of [&lt;a href=&quot;http://papers.nips.cc/paper/8773-latent-ordinary-differential-equations-for-irregularly-sampled-time-series&quot;&gt;Rubanova et al., 2019&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;For a review on &lt;strong&gt;interpretability&lt;/strong&gt; of models for sequential data see [&lt;a href=&quot;https://arxiv.org/abs/2004.12524&quot;&gt;Shickel and Rashidi, 2020&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;For dealing with very long time series check out [&lt;a href=&quot;https://arxiv.org/abs/2009.08295&quot;&gt;Morrill et al. 2021&lt;/a&gt;] along with the code where the authors apply a unique ODE method to efficiently train RNNs on unfeasibly long time series.&lt;/p&gt;

&lt;h2 id=&quot;final-note-&quot;&gt;Final note 🎵&lt;/h2&gt;

&lt;p&gt;To choose the right approach for your specific case it is very important to analyze and understand your own data before getting lost in the rabbit hole of experimentation with all the different approaches that potentially might work. This is only one of the point from the &lt;a href=&quot;http://karpathy.github.io/2019/04/25/recipe/&quot;&gt;best practice guidelines&lt;/a&gt; for deep learning which you should religiously follow if you value your time.&lt;/p&gt;

&lt;p&gt;Hope this was helpful and you were able to get some useful pointers and links that will help with your deep learning endeavors. Cheers! 🍻&lt;/p&gt;

</description>
        <pubDate>Sat, 20 Jun 2020 23:00:00 +0000</pubDate>
        <link>https://dsalaj.com///2020/06/20/deep-learning-on-time-series.html</link>
        <guid isPermaLink="true">https://dsalaj.com///2020/06/20/deep-learning-on-time-series.html</guid>
        
        
      </item>
    
      <item>
        <title>Nips 2018 Plan And Notes</title>
        <description>
&lt;h1 id=&quot;nips-2018&quot;&gt;NIPS 2018&lt;/h1&gt;
&lt;p&gt;(=NeurIPS 2018)&lt;/p&gt;

&lt;p&gt;List of all posters &lt;a href=&quot;https://www.nips.cc/Conferences/2018/Schedule?type=Poster&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Registration Desk&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;7:00 am - 8 pm Sunday QR code required for check in&lt;/li&gt;
  &lt;li&gt;7:00 am - 7 pm Monday - Friday  QR code required for check in&lt;/li&gt;
  &lt;li&gt;7:00 am - noon Saturday QR code required for check in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Food:&lt;/em&gt;
Breakfast and lunch are not provided.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;6:30 pm Monday reception in Room 220 AB and 210 ABCDEFGH&lt;/li&gt;
  &lt;li&gt;6:30 pm Reception on Saturday evening reception in 220 ABCD and 210 ABCDEFGH&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;sunday-2122018--nips-expo&quot;&gt;Sunday, 2.12.2018  &lt;a href=&quot;https://nips.cc/Conferences/2018/ExpoSchedule&quot;&gt;NIPS EXPO&lt;/a&gt;&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;8:00 - 9:00 am Alibaba Group, Room 511E:  Video Understanding in Youku&lt;/li&gt;
  &lt;li&gt;9:00 - 10:00 am Capital One Services, Room 517D: Eno’s Deep Learning-Powered Natural Language Understanding&lt;/li&gt;
  &lt;li&gt;10:00 - 10:30 am Coffee break, Rooms 220A and 220B&lt;/li&gt;
  &lt;li&gt;10:30 - 11:30 am Alibaba Group, Room 517D: AI at Alibaba&lt;/li&gt;
  &lt;li&gt;11:30 - 12:30 am Ouster, Room 517D: Native Camera Imaging on LIDAR and Novel Deep Learning Enablement&lt;/li&gt;
  &lt;li&gt;12:30 - 2:00 pm Lunch on your own&lt;/li&gt;
  &lt;li&gt;2:00 - 3:00 pm (Facebook was full, NAVER I missed and got into wrong room) NETEASE, 511B:  Make reinforcement learning in touch with industry: An Efficient, Elastic and Extensive Reinforcement learning Framework&lt;/li&gt;
  &lt;li&gt;3:00 - 4:00 pm Hudson River Trading, Room 517D: Inside the Black Box: Machine Learning and Optimization at HRT&lt;/li&gt;
  &lt;li&gt;4:00 - 4:30 pm Coffee break, Rooms 220A and 220B&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;monday-3122018--tutorials&quot;&gt;Monday, 3.12.2018  &lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?day=0&quot;&gt;Tutorials&lt;/a&gt;&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Tutorials Session 1&lt;/strong&gt; Mon Dec 3rd 08:30 – 10:30 AM @ Room 220 CD&lt;br /&gt;
Adversarial Robustness: Theory and Practice&lt;/li&gt;
  &lt;li&gt;10:30 - 11:00 AM Coffee Break&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tutorials Session 2&lt;/strong&gt; Mon Dec 3rd 11:00 AM – 01:00 PM @ Room 220 CD&lt;br /&gt;
Unsupervised Deep Learning by &lt;strong&gt;Alex Graves&lt;/strong&gt; · Marc’Aurelio Ranzato&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tutorials Session 3&lt;/strong&gt; Mon Dec 3rd 02:30 – 04:30 PM @ Room 220 CD&lt;br /&gt;
Automatic Machine Learning by Frank Hutter · Joaquin Vanschoren&lt;/li&gt;
  &lt;li&gt;4:30 - 5:00 PM Coffee break&lt;/li&gt;
  &lt;li&gt;5:00 - 5:30 PM Opening Remarks&lt;/li&gt;
  &lt;li&gt;5:30 - 6:20 PM Invited Talk: Laura Gomez: Accountability and Algorithmic Bias: Why Diversity and Inclusion Matters&lt;/li&gt;
  &lt;li&gt;6:30 - 8:30 PM Opening Reception&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;tuesday-4122018--invited-talks-papers-and-demonstrations&quot;&gt;Tuesday, 4.12.2018  &lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?day=1&quot;&gt;Invited Talks, Papers and Demonstrations&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;8:30 - 9:20 Invited Talk: Ed Felten: Machine Learning Meets Public Policy: What to Expect and How to Cope&lt;br /&gt;
9:20 - 9:40 Test of Time Award&lt;br /&gt;
9:40 - 10:05 Coffee break&lt;br /&gt;
10:05 - 10:20 Parallel Tracks: On Neuronal Capacity  @ Room 220 CD&lt;br /&gt;
10:20 - 10:25 Parallel Tracks: Learning Overparameterized NNs via Stochastic GD on Structured Data @ Room 220 CD&lt;br /&gt;
10:25 - 10:30 Parallel Tracks: Size-Noise Tradeoffs in Generative Networks @ Room 220 CD&lt;br /&gt;
10:30 - 10:45 Parallel Tracks: A Retrieve-and-Edit Framework for Predicting Structured Outputs @ Room 220 E&lt;br /&gt;
10:45 - 12:45 Posters A and Demonstrations&lt;br /&gt;
12:45 - 2:15 Lunch on your own&lt;br /&gt;
1:15 - 2:15 Town Hall Meeting, Room 517 CD&lt;br /&gt;
2:15 - 3:05 Invited Talk: Michael Levin: What Bodies Think About: Bioelectric Computation Outside the Nervous System, Primitive Cognition, and Synthetic Morphology&lt;br /&gt;
3:05 - 3:30 Coffee Break&lt;br /&gt;
3:30 - 3:35 Parallel Tracks: Evolved Policy Gradients @ Room 220 E&lt;br /&gt;
3:35 - 3:40 Parallel Tracks: Answerer in Questioner’s Mind @ Room 220 CD&lt;br /&gt;
3:40 - 3:45 Parallel Tracks: Bayesian Model-Agnostic Meta-Learning @ Room 220 E&lt;br /&gt;
3:45 - 3:50 Parallel Tracks: Learning to Optimize Tensor Programs @ Room 220 CD&lt;br /&gt;
3:50 - 4:05 Parallel Tracks: Generalisation of structural knowledge in the hippocampal-entorhinal system @ Room 220 CD&lt;br /&gt;
4:05 - 4:25 Parallel Tracks: @ Room 220 CDE&lt;br /&gt;
4:25 - 4:40 Parallel Tracks: A probabilistic population code based on neural samples @ Room 220 CD&lt;br /&gt;
. . . . . . . Parallel Tracks: How Does Batch Normalization Help Optimization? @ Room 220 E&lt;br /&gt;
4:40 - 5:00 Parallel Tracks: @ Room 220 CDE and 517 CD&lt;br /&gt;
5:00 – 7:30 Posters B and Demonstrations&lt;/p&gt;

&lt;h2 id=&quot;wednesday-5122018--invited-talks-papers-and-demonstrations&quot;&gt;Wednesday, 5.12.2018  &lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?day=2&quot;&gt;Invited Talks, Papers and Demonstrations&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;8:30 - 9:20 Invited Talk:  Joelle Pineau&lt;br /&gt;
9:20 - 9:45 Coffee break&lt;br /&gt;
9:45 - 10:05 Parallel Tracks: @ Room 220 CDE and 517 CD&lt;br /&gt;
10:05 - 10:20 Parallel Tracks: Exploration in Structured Reinforcement Learning @ Room 220 CD  K
10:20 - 10:45 Parallel Tracks: @ Room 220 CDE and 517 CD&lt;br /&gt;
10:45 - 12:45 Posters A  and Demonstrations&lt;br /&gt;
12:45 - 2:15 Lunch on your own&lt;br /&gt;
2:15 - 3:05 Invited Talk: Ayanna Howard: Investigations into the Human-AI Trust Phenomenon&lt;br /&gt;
3:05 - 3:30 Coffee Break&lt;br /&gt;
3:30 - 5:00 Parallel Tracks: @ Room 220 CDE and 517 CD&lt;br /&gt;
3:50 - 4:05 Parallel Tracks: Policy Optimization via Importance Sampling @ Room 220 CD&lt;br /&gt;
4:05 - 5:00 Parallel Tracks: @ Room 220 CDE and 517 CD&lt;br /&gt;
5:00 – 7:30 Posters B (&lt;strong&gt;our slot!&lt;/strong&gt;) and Demonstrations&lt;/p&gt;

&lt;h2 id=&quot;thursday-6122018--invited-talks-papers-and-demonstrations&quot;&gt;Thursday, 6.12.2018  &lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?day=3&quot;&gt;Invited Talks, Papers and Demonstrations&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;8:30 - 9:20 Invited Talk: David Spiegelhalter: Making Algorithms Trustworthy&lt;br /&gt;
9:20 - 9:45 Coffee break &lt;br /&gt;
9:45 - 10:45 Parallel Tracks: @ Room 220 CDE and 517 CD&lt;br /&gt;
10:45 - 12:45 Posters A&lt;br /&gt;
12:45 - 2:15 Lunch on your own &lt;br /&gt;
2:15 - 3:05 Invited Talk: Kunle Olukotun: Designing Computer Systems for Software 2.0&lt;br /&gt;
3:05 - 3:30 Coffee Break&lt;br /&gt;
3:30 - 5:00 Parallel Tracks: @ Room 220 CDE and 517 CD&lt;br /&gt;
5:00 – 7:30 Posters B&lt;/p&gt;

&lt;h2 id=&quot;friday-7122018--workshops&quot;&gt;Friday, 7.12.2018  &lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?type=Workshop&quot;&gt;Workshops&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;All workshops are scheduled for: 08:00 AM – 06:30 PM&lt;br /&gt;
10:30 – 11:00 Coffee break&lt;br /&gt;
12:00 to 2:00  Lunch on your own&lt;br /&gt;
3:00 – 3:30 Coffee break&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10908&quot;&gt;Challenges and Opportunities for AI in Financial Services: the Impact of Fairness, Explainability, Accuracy, and Privacy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10937&quot;&gt;Visually grounded interaction and language&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10911&quot;&gt;Critiquing and Correcting Trends in Machine Learning&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10912&quot;&gt;Deep Reinforcement Learning&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10941&quot;&gt;NIPS 2018 workshop on Compact Deep Neural Networks with industrial applications&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10907&quot;&gt;Causal Learning&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10914&quot;&gt;Imitation Learning and its Challenges in Robotics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;saturday-8122018--workshops-full-schedule&quot;&gt;Saturday, 8.12.2018  Workshops (&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?type=Workshop&quot;&gt;full schedule&lt;/a&gt;)&lt;/h2&gt;

&lt;p&gt;All workshops are scheduled for: 08:00 AM – 06:30 PM 
10:30 – 11:00 Coffee break
12:00 to 2:00  Lunch on your own
3:00 – 3:30 Coffee break
6:30 - 10:30 Saturday night reception and dancing.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10938&quot;&gt;Wordplay: Reinforcement and Language Learning in Text-based Games&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10918&quot;&gt;Learning by Instruction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10932&quot;&gt;NIPS 2018 Workshop on Meta-Learning&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10917&quot;&gt;Interpretability and Robustness in Audio, Speech, and Language&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10922&quot;&gt;Machine Learning for Health (ML4H): Moving beyond supervised learning in healthcare&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nips.cc/Conferences/2018/Schedule?showEvent=10929&quot;&gt;Reinforcement Learning under Partial Observability&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 22 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://dsalaj.com///2018/11/22/nips-2018-plan-and-notes.html</link>
        <guid isPermaLink="true">https://dsalaj.com///2018/11/22/nips-2018-plan-and-notes.html</guid>
        
        
      </item>
    
      <item>
        <title>How to pip install from private github repository in Dockerfile</title>
        <description>&lt;p&gt;This is a short note on how to effectively pip install requirements that
contain private repositories in a Dockerfile.&lt;/p&gt;

&lt;p&gt;For the security reasons it is a good idea to generate an ssh key specificly
for the repository you want to pull with only read permissions. 
If you refuse to generate a new ssh key, you can transfer existing key through
local webserver and remove it after installing the requirements. Details of
this method can be read
&lt;a href=&quot;https://farazdagi.com/2016/using-ssh-private-keys-securely-when-building-docker-images/&quot;&gt;here&lt;/a&gt;.
Generating new key
(&lt;a href=&quot;https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#generating-a-new-ssh-key&quot;&gt;more details&lt;/a&gt;):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh-keygen &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; rsa &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; 4096 &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;your_email@example.com&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After generation add newly generated public key to github repository by going
to repository settings, &lt;em&gt;Deploy Keys&lt;/em&gt; sidebar, &lt;em&gt;Add deploy key&lt;/em&gt; button
(&lt;a href=&quot;https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys&quot;&gt;more details&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Since the key has only read rights, it is safe to push it to your repository.
Next adapt your Dockerfile to copy the keys from the repository:&lt;/p&gt;
&lt;div class=&quot;language-dockerfile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; /root&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; /.ssh
&lt;span class=&quot;k&quot;&gt;ADD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; local_repo/keys/repo-github-deploy-key /root/.ssh/repo-github-deploy-key&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ADD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; local_repo/keys/repo-github-deploy-key.pub /root/.ssh/repo-github-deploy-key.pub&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally start the ssh agent, add keys, and pip install like usual:&lt;/p&gt;
&lt;div class=&quot;language-dockerfile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; /code&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ADD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; local_repo/requirements_frozen.txt requirements.txt&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;  apt-get &lt;span class=&quot;nt&quot;&gt;-qy&lt;/span&gt; upgrade git openssh-client &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;  &lt;span class=&quot;nb&quot;&gt;chmod &lt;/span&gt;600 /root/.ssh/repo-github-deploy-key &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;  &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;ssh-agent&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Host github.com&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\t&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;StrictHostKeyChecking no&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /root/.ssh/config &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;  ssh-add /root/.ssh/repo-github-deploy-key &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;  ssh-keyscan github.com &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.ssh/known_hosts &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;  pip3 &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; requirements.txt &lt;span class=&quot;nt&quot;&gt;--src&lt;/span&gt; /usr/local/src
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is important to start the agent and add keys in the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RUN&lt;/code&gt; command,
otherwise it will fail.&lt;/p&gt;

&lt;p&gt;If you never added github repository to you requirements here is an example
&lt;em&gt;requirements.txt&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;language-markdown highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Django==1.10.6
django-allauth==0.24.1
&lt;span class=&quot;gh&quot;&gt;# ...&lt;/span&gt;
-e git+ssh://git@github.com/username/private-repo-name.git@c0m1th4sh#egg=app-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Wed, 04 Oct 2017 08:58:00 +0000</pubDate>
        <link>https://dsalaj.com///2017/10/04/how-to-pip-install-from-private-github-repo-in-dockerfile.html</link>
        <guid isPermaLink="true">https://dsalaj.com///2017/10/04/how-to-pip-install-from-private-github-repo-in-dockerfile.html</guid>
        
        
      </item>
    
      <item>
        <title>Quick Guide To Restoring Your Bootloader</title>
        <description>&lt;p&gt;So you installed a new operating system and suddenly your boot loader is gone.
In most cases the new OS is aggressive enough to make your computer boot directly
to it without even making an effort to give you options for you to boot
to your old OS. Worry no more, we are going to fix that now.&lt;/p&gt;

&lt;p&gt;I will assume that have installed some sort of Linux and Windows version together,
probably some newer Windows (very aggressive with BIOS boot time optimizations).
First question: To which of your installed operating systems can you boot now?&lt;/p&gt;

&lt;p&gt;Click on your answer to go to the next part:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#windows&quot;&gt;Windows&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#linux&quot;&gt;Linux&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#i-cant-boot-to-anything&quot;&gt;None!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;windows&quot;&gt;Windows&lt;/h2&gt;
&lt;p&gt;If you can boot to Windows next part is enabling the Windows bootloader and
extending it so it gives you the option to boot into other operating systems. To do
that we need to download a small bootloader modification tool called EasyBCD. You can
download it here: &lt;a href=&quot;https://neosmart.net/EasyBCD/&quot;&gt;https://neosmart.net/EasyBCD/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To add Linux to your Windows bootloader menu, do the following steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Download and install the EasyBCD software. After completing the installation
process run the program.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To add new operating system to your boot loader menu, you want to click on the
third button from the top &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add New Entry&lt;/code&gt;. A new options panel should
appear on the right side of the application window:&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/img/bootloader/win_2.png&quot; alt=&quot;Windows step 2&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;If you want to add a different Windows operating system to your boot menu, just
choose the correct version and the location of the operating system in the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Drive&lt;/code&gt; drop down menu. The same applies for adding the Mac operating system to
your windows boot menu.&lt;/p&gt;

    &lt;p&gt;For adding Linux operating system, click on the “Linux/BSD” tab and proceed to
the next step.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In the Linux tab we first need to select the correct bootloader &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Type&lt;/code&gt; in the
drop down menu.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/img/bootloader/win_3.png&quot; alt=&quot;Windows step 3&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;If you do not know exactly the type of your bootloader, chances
are that you installed some newer version of Linux that has GRUB 2 as its
default bootloader. So open up the drop down menu and select GRUB 2.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/img/bootloader/win_4.png&quot; alt=&quot;Windows step 3&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Do not forget to change the name of your Linux distribution. You probably
want to name it “Ubuntu” or “Linux Mint” or whatever you have installed instead
of the default name.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;For the GRUB 2 bootloader, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Drive&lt;/code&gt; location does not need to be specified
as we are presented with the option of “Automatically locate and load” the
GRUB 2 bootloader. This is very convenient as we don’t need to know or
remember the location of the bootloader or which of the operating systems we
installed first.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; If the situation is more complex and you have different Linux flavors
installed with each having different versions of bootloader then this option
may not work so smoothly&lt;/p&gt;

    &lt;p&gt;Click on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add Entry&lt;/code&gt; button and a success message on the bottom of the window
should appear:&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/img/bootloader/win_5.png&quot; alt=&quot;Windows step 4&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;At this point you can close the EasyBCD software and restart your computer.
Upon booting you should be presented with a boot menu looking like this:&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/img/bootloader/win_6.jpg&quot; alt=&quot;Windows step 5&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;As you see I have renamed my linux boot option appropriately to Linux Mint.&lt;/p&gt;

    &lt;p&gt;Do you like this Windows bootloader? If yes, you are finished! You now have a
functional bootloader and you can successfully boot into any of your operating
systems.&lt;/p&gt;

    &lt;p&gt;If you don’t like it and want your Grub (or any other) bootloader back,
just boot into your Linux system and proceed reading the next part.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;linux&quot;&gt;Linux&lt;/h2&gt;

&lt;p&gt;So you can boot into Linux, great! Now let us restore the bootloader and/or
insert the options for other operating systems to boot in.&lt;/p&gt;

&lt;p&gt;If you booted to Linux by going through Windows bootloader and you prefer the
GRUB as your primary bootloader, you need to restore GRUB by reinstalling it on
primary partition.&lt;/p&gt;

&lt;h3 id=&quot;reinstalling-grub-2&quot;&gt;Reinstalling GRUB 2&lt;/h3&gt;
&lt;p&gt;Run the following command from the terminal:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;grub-install /dev/sd?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;? is the drive letter on which you want GRUB to write the boot information.
Normally users should not include a partition number, which would produce an
error message as the command would attempt to write the information to a
partition.&lt;/p&gt;

&lt;p&gt;If you are using only one hard drive or the operating systems are located on the
first primary drive, you will probably use the command on drive “sda” like this:&lt;/p&gt;

&lt;p&gt;Example: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo grub-install /dev/sda&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will rewrite the MBR information to point to the current installation and
rewrite some GRUB 2 files (which are already working). Since it isn’t done
during execution of the previous command, running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo update-grub&lt;/code&gt; after the
install will ensure GRUB 2’s menu is up-to-date.&lt;/p&gt;

&lt;p&gt;After doing these steps your GRUB bootloader should appear first after
rebooting the computer.&lt;/p&gt;

&lt;h3 id=&quot;adding-other-operating-systems&quot;&gt;Adding other operating systems&lt;/h3&gt;
&lt;p&gt;If you are making GRUB your primary boot loader, you probably want to add all
other available operating systems to the boot menu.&lt;/p&gt;

&lt;p&gt;This part is easy as it does not require downloading or using any additional
tools. Only thing that we need is a text editor and your grub configuration file
path which is by default: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/grub/grub.cfg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open up the grub.cfg file in any text editor (like gedit) and find the “menuentry”
part. Because I have Linux Mint installed, on my machine it looks like this:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;menuentry &lt;span class=&quot;s1&quot;&gt;&apos;Linux Mint 15 Cinnamon 64-bit, 3.8.0-19-generic (/dev/sda1)&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--class&lt;/span&gt; linuxmint &lt;span class=&quot;nt&quot;&gt;--class&lt;/span&gt; gnu-linux &lt;span class=&quot;nt&quot;&gt;--class&lt;/span&gt; gnu &lt;span class=&quot;nt&quot;&gt;--class&lt;/span&gt; os &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	recordfail
	gfxmode &lt;span class=&quot;nv&quot;&gt;$linux_gfx_mode&lt;/span&gt;
	insmod gzio
	insmod part_msdos
	insmod ext2
	&lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hd0,msdos1&apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; x&lt;span class=&quot;nv&quot;&gt;$feature_platform_search_hint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; xy &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	  &lt;/span&gt;search &lt;span class=&quot;nt&quot;&gt;--no-floppy&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--fs-uuid&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;root &lt;span class=&quot;nt&quot;&gt;--hint-bios&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;hd0,msdos1 &lt;span class=&quot;nt&quot;&gt;--hint-efi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;hd0,msdos1 &lt;span class=&quot;nt&quot;&gt;--hint-baremetal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ahci0,msdos1  77a4962b-fb54-4054-ae57-c2292a4fae45
	&lt;span class=&quot;k&quot;&gt;else
	  &lt;/span&gt;search &lt;span class=&quot;nt&quot;&gt;--no-floppy&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--fs-uuid&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;root 77a4962b-fb54-4054-ae57-c2292a4fae45
	&lt;span class=&quot;k&quot;&gt;fi
	&lt;/span&gt;linux	/boot/vmlinuz-3.8.0-19-generic &lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;77a4962b-fb54-4054-ae57-c2292a4fae45 ro   quiet splash &lt;span class=&quot;nv&quot;&gt;$vt_handoff&lt;/span&gt;
	initrd	/boot/initrd.img-3.8.0-19-generic
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To manually add a Windows boot option you want to add the following text to your
file just after the previous part:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;menuentry &lt;span class=&quot;s2&quot;&gt;&quot;Windows 8&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;hd0,3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
	chainloader +1
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you see I have added a menu entry named “Windows 8” and the very important
part here is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set root=(hd0,3)&lt;/code&gt; which means to boot the windows operating
system from the hard drive 0 (which is the first and only one I have on my notebook)
and that it is located at the third(3) partition. For more understanding here is
how my disk looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/bootloader/lin_1.png&quot; alt=&quot;Linux grub&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For example if you need to boot your windows XP which is located on the second
hard drive, on the first partition you would want to add to grub.cfg something
like this:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;menuentry &lt;span class=&quot;s2&quot;&gt;&quot;Windows XP&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;hd1,1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
	chainloader +1
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After adding the new entry in the grub.cfg file, don’t forget to save it!
Next time I booted my computer I was presented with boot menu looking like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/bootloader/lin_2.jpg&quot; alt=&quot;Linux boot menu&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;disabling-the-grub-boot-menu&quot;&gt;Disabling the GRUB boot menu&lt;/h3&gt;

&lt;p&gt;If you want to use windows bootloader as your primary boot menu, you probably
don’t want the GRUB bootloader appearing right after you choose Linux in your
Windows bootloader. To disable the GRUB boot menu, do the following steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/default/grub&lt;/code&gt; with text editor with elevated rights.
You can do that by opening the terminal (Ctrl+Alt+T) and executing:
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;gedit /etc/default/grub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Find the line that contains the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB_TIMEOUT&lt;/code&gt; variable
and set its value to zero. It should look like:
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;GRUB_TIMEOUT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Do not forget to save the changes!
Next you need to open the terminal once again and execute the following command:&lt;/p&gt;
    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;update-grub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;This should apply the changes and completely disable the display of the
bootloader menu.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;disabling-the-windows-boot-menu&quot;&gt;Disabling the Windows boot menu&lt;/h3&gt;

&lt;p&gt;By deciding to have GRUB as your primary boot loader, you probably want to
skip the windows bootloader after selecting the windows in the GRUB boot menu.
In the process of restoring your GRUB bootloader you may have needed to enable
the windows bootloader but now when you got what you wanted, the appearing
of the unnecessary windows bootloader is just plain annoying. Disabling it is
quite easy. Just follow the steps below:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Boot into your Windows and run the EasyBCD software once again. This time
click on the “Edit Boot Menu” button.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The following menu should appear on the right:&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/img/bootloader/dw.png&quot; alt=&quot;Edit windows boot menu in EasyBCD&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;To completely skip the windows bootloader menu select the “Skip the boot menu”
in the “Timeout Options” list under the list of menu entries. Additionally you
may want to delete the unnecessary entries in the list by selecting them and
clicking on “Delete” button.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally just click the “Save Setting” button and you are all done!&lt;/p&gt;

&lt;p&gt;After restarting there should be no more windows bootloader menu.&lt;/p&gt;

&lt;h2 id=&quot;i-cant-boot-to-anything&quot;&gt;I can’t boot to anything&lt;/h2&gt;

&lt;p&gt;In this case it is advisable to make yourself a bootable Linux USB drive (I
recommend &lt;a href=&quot;https://grml.org/&quot;&gt;https://grml.org/&lt;/a&gt; but Ubuntu will work fine) and boot into a live
Linux on your computer. Then you could try to fix your GRUB bootloader as
described in the &lt;a href=&quot;#linux&quot;&gt;Linux&lt;/a&gt; section above.&lt;/p&gt;

</description>
        <pubDate>Sat, 12 Jul 2014 21:55:00 +0000</pubDate>
        <link>https://dsalaj.com///2014/07/12/bootloader.html</link>
        <guid isPermaLink="true">https://dsalaj.com///2014/07/12/bootloader.html</guid>
        
        
      </item>
    
  </channel>
</rss>
