<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Learning Journey</title>
	<atom:link href="https://tamersalama.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://tamersalama.com</link>
	<description></description>
	<lastBuildDate>Mon, 22 Jan 2024 00:36:03 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>Starting MLflow with FastAI (v2)</title>
		<link>https://tamersalama.com/2021/06/21/starting-mlflow-with-fastai-v2/</link>
					<comments>https://tamersalama.com/2021/06/21/starting-mlflow-with-fastai-v2/#respond</comments>
		
		<dc:creator><![CDATA[Tamer Salama]]></dc:creator>
		<pubDate>Mon, 21 Jun 2021 05:12:14 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[data science]]></category>
		<guid isPermaLink="false">https://tamersalama.com/2021/06/21/starting-mlflow-with-fastai-v2/</guid>

					<description><![CDATA[This is not meant as a comprehensive guide, rather just a place to start and get things up and running. Read further below for a background and explanation. Create a custom callback   ## Tracking Classfrom mlflow.tracking import MlflowClientfrom mlflow.entities.run import Runfrom typing import Listclass MLFlowTracking(Callback): "A `LearnerCallback` that tracks the loss and other metrics into MLFlow" def __init__(self,&#46;&#46;&#46;]]></description>
										<content:encoded><![CDATA[
<pre class="wp-block-code"><code></code></pre>


<p>This is not meant as a comprehensive guide, rather just a place to start and get things up and running. Read further below for a background and explanation.</p>
<ol>
<li>Create a custom callback</li>
</ol>
<p> </p>
<figure class="kg-card kg-code-card">
<pre><code class="language-python">## Tracking Classfrom mlflow.tracking import MlflowClientfrom mlflow.entities.run import Runfrom typing import Listclass MLFlowTracking(Callback):    "A `LearnerCallback` that tracks the loss and other metrics into MLFlow"    def __init__(self, metric_names:List[str], client:MlflowClient, run_id:Run):        self.client = client        self.run_id = run_id        self.metric_names = metric_names                def after_epoch(self):        "Compare the last value to the best up to now"        for metric_name in self.metric_names:            m_idx = list(self.recorder.metric_names[1:]).index(metric_name)            if len(self.recorder.values) &gt; 0:                val = self.recorder.values[-1][m_idx]                self.client.log_metric(self.run_id, metric_name, np.float(val))</code></pre>
<figcaption>Custom Callback Class</figcaption>
</figure>
<p>2. Initialize the MLflow Experiment, Client and Run</p>
<figure class="kg-card kg-code-card">
<pre><code class="language-Python"># Make sure to install mlflow using pip, conda or your favourite package managerimport mlflowfrom mlflow.tracking import MlflowClientTRACKING_URL = "&lt;full url, e.g: http://example.com:5000&gt;"EXPERIMENT_NAME = "example_experiment"# Create the Clientmlfclient = mlflow.tracking.MlflowClient(tracking_uri= TRACKING_URL)# Check if the experiment already exists, or create itmlfexp = mlfclient.get_experiment_by_name(EXPERIMENT_NAME)if mlfexp is None:    mlfexp_id = mlfclient.create_experiment(EXPERIMENT_NAME)    mlfexp = mlfclient.get_experiment_by_name(EXPERIMENT_NAME)    mlrun = mlfclient.create_run(experiment_id= mlfexp.experiment_id)</code></pre>
<figcaption>Initialize the MLflow Runner and Client</figcaption>
</figure>
<p>3. Log the experiment&#8217;s hyperparameters</p>
<figure class="kg-card kg-code-card">
<pre><code class="language-python"># setup up a params dictionaryparams = {    'crop_size': 250,    'epochs': 20}# log each of the params items to MLflow (for that experiment's run)for k, v in params.items():    mlfclient.log_param(run_id=mlrun.info.run_uuid, key=k, value=v)    # Make sure to use params in your data loader and experiments</code></pre>
<figcaption>Hyperparameter logging</figcaption>
</figure>
<p>4. Add the custom callback to the learner</p>
<figure class="kg-card kg-code-card">
<pre><code class="language-python"># Assuming dataloaders is already setup learn = cnn_learner(dls, resnet18, metrics=error_rate, cbs=[MLFlowTracking(metric_names=['valid_loss', 'train_loss', 'error_rate'], client=mlfclient, run_id=mlrun.info.run_uuid)])# This should start logging the metrics and losses in your environment as well as MLflowlearn.fit(params['epochs'])</code></pre>
<figcaption>Custom Callback and Metrics</figcaption>
</figure>
<p><a href="https://docs.fast.ai/">FastAI</a> is a powerful library with a set of good features to make ML fun. One of the things I was struggling with is losing track of my experiment&#8217;s configuration and to the metrics and losses they generated.</p>
<p><a href="https://mlflow.org/">MLflow</a> seemed like a good fit at least for what I was trying to accomplish. Most documentations around setting up MLflow and fastai are stale (covering v1). MLflow does have fast.ai <a href="https://www.mlflow.org/docs/latest/python_api/mlflow.fastai.html">autolog feature</a> but, as per the documentations (and trials), looks like it works only for version fast.ai 1.0.61 or earlier.</p>
<p>The above setup, although very crude, works for the simple setup I have. It assumes access to an MLflow server with accessible URI (TRACKING_URI). One caveat is that metric values tend to be empty for the first couple of epochs and, with more understanding of fastai Callbacks and recorder, I might be able to track down.</p>
<p>Happy Deep Learning</p>


<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="## Tracking Classfrom mlflow.tracking 
import MlflowClient from mlflow.entities.run 
import Run from typing 
import List

class MLFlowTracking(Callback):
  &quot;A `LearnerCallback` that tracks the loss and other metrics into MLFlow&quot;
  
  def __init__(self, metric_names:List[str], client:MlflowClient, run_id:Run):
    self.client = client
    self.run_id = run_id
    self.metric_names = metric_names
    
  def after_epoch(self):
    &quot;Compare the last value to the best up to now&quot; 
    for metric_name in self.metric_names: 
      m_idx = list(self.recorder.metric_names[1:]).index(metric_name) 
      if len(self.recorder.values) &gt; 0: 
        val = self.recorder.values[-1][m_idx]
        self.client.log_metric(self.run_id, metric_name, np.float(val))" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">## </span><span style="color: #D8DEE9">Tracking</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Classfrom</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mlflow</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">tracking</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">MlflowClient</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">mlflow</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">entities</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">run</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Run</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">typing</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">List</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">class</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">MLFlowTracking</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">Callback</span><span style="color: #D8DEE9FF">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">A `LearnerCallback` that tracks the loss and other metrics into MLFlow</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">__init__</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">self</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">metric_names</span><span style="color: #D8DEE9FF">:</span><span style="color: #8FBCBB">List</span><span style="color: #D8DEE9FF">[</span><span style="color: #8FBCBB">str</span><span style="color: #D8DEE9FF">]</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">client</span><span style="color: #D8DEE9FF">:</span><span style="color: #8FBCBB">MlflowClient</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">run_id</span><span style="color: #D8DEE9FF">:</span><span style="color: #8FBCBB">Run</span><span style="color: #D8DEE9FF">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">client</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">client</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">run_id</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">run_id</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">metric_names</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">metric_names</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">after_epoch</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">):</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Compare the last value to the best up to now</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">metric_name</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">metric_names</span><span style="color: #D8DEE9FF">: </span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #8FBCBB">m_idx</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">list</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">recorder</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">metric_names</span><span style="color: #D8DEE9FF">[1:]).</span><span style="color: #8FBCBB">index</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">metric_name</span><span style="color: #D8DEE9FF">) </span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #8FBCBB">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">len</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">recorder</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">values</span><span style="color: #D8DEE9FF">) &gt; 0: </span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">val</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">recorder</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">values</span><span style="color: #D8DEE9FF">[-1][</span><span style="color: #8FBCBB">m_idx</span><span style="color: #D8DEE9FF">]</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">client</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">log_metric</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">self</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">run_id</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">metric_name</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">np</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">float</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">val</span><span style="color: #D8DEE9FF">))</span></span></code></pre></div>



<pre class="wp-block-code"><code></code></pre>



<pre class="wp-block-code"><code></code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://tamersalama.com/2021/06/21/starting-mlflow-with-fastai-v2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Data Pipeline Visualization &#8211; Making it Interesting</title>
		<link>https://tamersalama.com/2021/02/02/data-pipeline-making-it-interesting/</link>
					<comments>https://tamersalama.com/2021/02/02/data-pipeline-making-it-interesting/#respond</comments>
		
		<dc:creator><![CDATA[Tamer Salama]]></dc:creator>
		<pubDate>Tue, 02 Feb 2021 05:29:11 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[data science]]></category>
		<guid isPermaLink="false">https://tamersalama.com/2021/02/02/data-pipeline-making-it-interesting/</guid>

					<description><![CDATA[Data pipelines are generally hard to explain and aren&#8217;t as interesting to those not directly involved in data analytics. How to make this more interesting and engaging? Simple. Make it in 3D. Animated. Interactive. Click &#38; Drag. Middle mouse to zoom. Press 1 through 9 for animations. The above is a data pipeline animation for one of my recent&#46;&#46;&#46;]]></description>
										<content:encoded><![CDATA[<p>Data pipelines are generally hard to explain and aren&#8217;t as interesting to those not directly involved in data analytics.</p>
<p>How to make this more interesting and engaging? Simple. Make it in 3D. Animated. Interactive.</p>
<p><!--kg-card-begin: html--></p>
<div><em><b>Click &amp; Drag. Middle mouse to zoom. Press 1 through 9 for animations.</b></em></div>
<p><!--kg-card-end: html--><!--kg-card-begin: html--><iframe src="https://my.spline.design/pipelineproject-328745c8be4111b0a32e9bec6d065268/" width="100%" height="600px;" frameborder="0"></iframe><!--kg-card-end: html--></p>
<p>The above is a data pipeline animation for one of my recent projects.</p>
<p>I started out looking into ways, beyond just visio, diagrams or graphviz, that would demonstrate the data flow in a simple and interesting way. Animation was a natural choice, yet the available toolsets had an associated steep learning curve.</p>
<p>I then came across <a href="https://threejs.org/">three.js</a> which seemed like an achiveable setup and medium. However, coding all three.js objects by hand felt like an endless task.</p>
<p>After a bit of digging I came across <a href="https://spline.design">spline.design</a> tool &#8211; an awesome 3D and Animation editor, for the web, that leverages three.js and <a href="https://animejs.com/">anime.js</a> (do check it out).</p>
<p>Some feedback I got: &nbsp;&#8220;This looks cool&#8221;, &#8220;I like it&#8221;, &#8220;It&#8217;s like watching a domino chain project&#8221;.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tamersalama.com/2021/02/02/data-pipeline-making-it-interesting/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Non-tech companies and the Data Science challenges</title>
		<link>https://tamersalama.com/2020/02/01/non-tech-companies-and-data-science-challenges/</link>
					<comments>https://tamersalama.com/2020/02/01/non-tech-companies-and-data-science-challenges/#respond</comments>
		
		<dc:creator><![CDATA[Tamer Salama]]></dc:creator>
		<pubDate>Sat, 01 Feb 2020 02:00:00 +0000</pubDate>
				<category><![CDATA[Leadership]]></category>
		<category><![CDATA[data science]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[tech leadership]]></category>
		<guid isPermaLink="false">https://tamersalama.com/2020/02/01/non-tech-companies-and-data-science-challenges/</guid>

					<description><![CDATA[I recently came across ‘Can Data Scientists spell Sustainability?’ by Yogi Schulz The article portrays the opposing views held by data science and information system departments and how each side view their responsibilities:  “Data scientists see only throw-away software that will be discarded once the breakthrough insights have been actioned by management. The [information systems] department sees only thoroughly&#46;&#46;&#46;]]></description>
										<content:encoded><![CDATA[<p>I recently came across ‘<a href="https://www.itworldcanada.com/blog/data-scientists-cant-spell-sustainability/425288">Can Data Scientists spell Sustainability?</a>’ by Yogi Schulz</p>
<p>The article portrays the opposing views held by data science and information system departments and how each side view their responsibilities:  “Data scientists see only throw-away software that will be discarded once the breakthrough insights have been actioned by management. The [information systems] department sees only thoroughly designed and tested software that will be used in production-quality applications.”</p>
<figure class="kg-card kg-image-card"><img decoding="async" src="https://imgs.xkcd.com/comics/duty_calls.png" class="kg-image" alt="Someone is wrong on the internet"></figure>
<p>While I acknowledge the challenges, I don’t think that pinning data science against information system (technology services) departments, or as presented, sustainability against flexibility, tells the full story.</p>
<p>I personally can’t imagine a situation in which data scientists at Netflix, YouTube or Tesla are blamed for not delivering on sustainability or for their ‘information systems’ counterparts are blamed for being rigid.</p>
<h2 id="data-science-projects">Data science projects</h2>
<p>In a nutshell, data science projects are in essence, solutions development projects. Data scientists use data, tools and code to deliver a digital solution. Those solutions are, in turn, used to help make better business decisions or optimize certain functions.</p>
<p>They can be as simple as a stand-alone script that generates frequent reports. Or as complex as a multi-year, multi-million dollar solution intended to create a <a href="https://youtu.be/Ucp0TTmvqOE?t=6709">self-driving vehicle</a>.</p>
<figure class="kg-card kg-image-card"><img decoding="async" src="/content/images/2021/02/people-coffee-meeting-team-7096.jpg" class="kg-image" alt="Team" srcset="/content/images/size/w600/2021/02/people-coffee-meeting-team-7096.jpg 600w, /content/images/2021/02/people-coffee-meeting-team-7096.jpg 795w" sizes="(min-width: 720px) 720px"></figure>
<p>From a personnel perspective, data science projects are cross functional and involve multiple roles. On a smaller scale, those roles can be assumed by a single person (a data scientist/unicorn?). On a larger scale, it’s a cross functional team with business owners, product owners, data scientists, front-end developers, back-end developers, data engineers, and more.</p>
<p>From a solutions perspective, data science project results and outcomes must be seamlessly embedded within business workflows. Data science project results that are not easily used in making business decisions remain largely experimental and gimmicky.</p>
<h2 id="technology-services">Technology Services</h2>
<p>So &#8211; why does the introduction or growth of data science practices feel challenging? Why do data scientists feel constrained and perhaps isolated with push back from their technology services departments?</p>
<p>In my opinion, this might just be a secondary symptom of how less-equipped technology services departments have become.</p>
<p>Many technology services departments have chosen, or were forced, to become cost centers that are responsible for commodity hardware or off-the-shelf services, not the business partners needed to move the business forward.</p>
<p>In the process of <a href="https://en.wikipedia.org/wiki/IT_service_management">standardizing their services</a>, some might have shed their technical talent in favor of managerial or business one.</p>
<p>Their ability to develop and implement technical solutions ended up with third parties at the expense of adaptability and agility and with costs that far exceed the effort.</p>
<p>In this type of environment, data scientists with their need to develop technical solutions or integrate their work in the larger technological landscape, face repeated pushbacks.</p>
<p>Access to complementing tools or talent become entangled in process and budgetary discussions, and simple technical requests become missions to mars. A ripe environment for <a href="https://en.wikipedia.org/wiki/Shadow_IT">Shadow IT</a>.</p>
<figure class="kg-card kg-image-card"><img decoding="async" src="/content/images/2021/02/evstratov-InsHJ5sg2vc-unsplash.jpg" class="kg-image" alt="Shadow IT" srcset="/content/images/size/w600/2021/02/evstratov-InsHJ5sg2vc-unsplash.jpg 600w, /content/images/2021/02/evstratov-InsHJ5sg2vc-unsplash.jpg 795w" sizes="(min-width: 720px) 720px"></figure>
<h2 id="data-science-within-non-tech-organizations">Data Science within Non-Tech Organizations</h2>
<p>I would like to think of the challenge as an organizational responsibility rather than an A-against-B argument.</p>
<p>Organizations serious about adopting data science as a competitive advantage, or even as an investment attractor, should also consider themselves as technology creators rather than just technology consumers.</p>
<p>Some of the things that organizations can do to promote and encourage the development of technical solutions (rather than ‘data-science projects’) are:</p>
<ul>
<li>Promote and encourage ways to <a href="https://en.wikipedia.org/wiki/Systems_development_life_cycle">properly deliver digital solutions</a>, rather than just isolated ‘data-science projects’.</li>
<li><a href="https://agilemanifesto.org/">Embrace principles</a> that value people, collaboration, flexibility and working solutions.</li>
<li><a href="https://en.wikipedia.org/wiki/Software_development_process">Adopt processes</a> to manage knowledge projects as well as minimize the risk during delivery.</li>
<li><a href="https://en.wikipedia.org/wiki/Lean_startup">Implement methodologies</a> to better understand the target [internal] market and measure traction.</li>
<li>Develop <a href="https://new.siemens.com/global/en/company/stories/research-technologies/artificial-intelligence/artificial-intelligence-optimizing-industrial-operations.html">technical capabilities</a> to improve their overall competitiveness and offer services or products unmatched by their peers.</li>
</ul>
<p>For many years, those principles, strategies, processes and methodologies have been battle-tested at technically inclined organizations. What it took is a realization, direction, learning and will.</p>
<p><strong>Acknowledgment</strong></p>
<p>Thanks to <a href="https://brettwiens.com/">Brett Wiens</a> and <a href="https://www.linkedin.com/in/marc-boulet-5bb87023/?originalSubdomain=ca">Marc Boulet</a> for the first read and feedback!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tamersalama.com/2020/02/01/non-tech-companies-and-data-science-challenges/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Software Engineering for Professionals</title>
		<link>https://tamersalama.com/2020/01/02/software_engineering_for_professionals/</link>
					<comments>https://tamersalama.com/2020/01/02/software_engineering_for_professionals/#respond</comments>
		
		<dc:creator><![CDATA[Tamer Salama]]></dc:creator>
		<pubDate>Thu, 02 Jan 2020 18:00:00 +0000</pubDate>
				<category><![CDATA[Leadership]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[tech leadership]]></category>
		<guid isPermaLink="false">https://tamersalama.com/2020/01/02/software_engineering_for_professionals/</guid>

					<description><![CDATA[I was invited by my friends at Untapped Energy to speak about Software Engineering. I’ve been lately seeing a lot of professionals (Engineers, Geologists, Accountants, Analysts, etc…) venturing into data analytics and have consequently been working with software and various technical components that proved challenging for some. I was motivated to provide some guidance around the main components used&#46;&#46;&#46;]]></description>
										<content:encoded><![CDATA[<p>I was invited by my friends at <a href="https://www.untappedenergy.ca/">Untapped Energy</a> to speak about Software Engineering.</p>
<p>I’ve been lately seeing a lot of professionals (Engineers, Geologists, Accountants, Analysts, etc…) venturing into data analytics and have consequently been working with software and various technical components that proved challenging for some. I was motivated to provide some guidance around the main components used in solutions development, the associated development processes and methodologies, as well as some common trade tools.</p>
<p>I gave the talk below at the Untapped Energy June 2019 meetup and very much liked the energy of the crowd during the Q&amp;A. I hope you don’t mind a cold start.</p>
<figure class="kg-card kg-embed-card"><iframe width="560" height="315" src="https://www.youtube.com/embed/QosEcJW1ZeA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://tamersalama.com/2020/01/02/software_engineering_for_professionals/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Blog revived</title>
		<link>https://tamersalama.com/2020/01/01/blog-revived/</link>
					<comments>https://tamersalama.com/2020/01/01/blog-revived/#respond</comments>
		
		<dc:creator><![CDATA[Tamer Salama]]></dc:creator>
		<pubDate>Wed, 01 Jan 2020 18:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[personal]]></category>
		<category><![CDATA[tech leadership]]></category>
		<guid isPermaLink="false">https://tamersalama.com/2020/01/01/blog-revived/</guid>

					<description><![CDATA[It has been a while since I added contents to the website. I started out this blog in 2004, back when blogging was the social media of the day. Inspired by professionals who I admired, I tried to track my own professional and personal journey. However, in 2016 I failed to renew my hosting plan which took down all&#46;&#46;&#46;]]></description>
										<content:encoded><![CDATA[<p>It has been a while since I added contents to the website.</p>
<p>I started out this blog in 2004, back when blogging was the social media of the day. Inspired by <a href="https://raibledesigns.com/">professionals</a> <a href="https://m.signalvnoise.com/">who I admired</a>, I tried to track my own professional and personal journey.</p>
<p>However, in 2016 I failed to renew my hosting plan which took down all the website’s content as well as my motivation to create new ones. There were no offsite backups of the website (Yes I know). I resorted to <a href="https://twitter.com/tamersalama">twitter</a> for short-form publishing and consumption and reviving the website was put on the back-burner.</p>
<p>I now feel the urge to create medium and long-form content. I also feel what I published from 2004 onwards speak to who I am professionally and personally.</p>
<p>Over the 2019 Christmas holidays I spent a bit of time in putting a publishing mechanism in place using <a href="https://jekyllrb.com/">Jekyll</a>, and migrating the contents over using <a href="https://web.archive.org/web/2019*/tamersalama.com">WayBack Machine’s snapshots</a>.</p>
<p>So here we are, the new and improved tamersalama.com with [most of] the original contents.</p>
<p>Happy new year.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tamersalama.com/2020/01/01/blog-revived/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>RubyMotion – PullToRefresh</title>
		<link>https://tamersalama.com/2013/04/15/rubymotion-pulltorefresh/</link>
					<comments>https://tamersalama.com/2013/04/15/rubymotion-pulltorefresh/#respond</comments>
		
		<dc:creator><![CDATA[Tamer Salama]]></dc:creator>
		<pubDate>Mon, 15 Apr 2013 00:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubymotion]]></category>
		<guid isPermaLink="false">https://tamersalama.com/2013/04/15/rubymotion-pulltorefresh/</guid>

					<description><![CDATA[To add Sam Vermette’s SVPullToRefresh to your RubyMotion project: Add the SVPullToRefresh pod Add the Quartz Framework # RakefileMotion::Project::App.setup do &#124;app&#124; # … app.frameworks += [‘QuartzCore’] app.pods do pod ‘SVPullToRefresh’ # … endend # Then in your controller def viewDidLoad # …. tableView.addPullToRefreshWithActionHandler Proc.new { loadMagicalData(tableView) # do some other magic # then don’t forget to: tableView.pullToRefreshView.stopAnimating }# …]]></description>
										<content:encoded><![CDATA[<p>To add Sam Vermette’s <a href="https://github.com/samvermette/SVPullToRefresh">SVPullToRefresh</a> to your RubyMotion project:</p>
<ol>
<li>Add the SVPullToRefresh pod</li>
<li>Add the Quartz Framework</li>
</ol>
<pre><code class="language-ruby"># RakefileMotion::Project::App.setup do |app| 	# … app.frameworks += [‘QuartzCore’]	app.pods do pod ‘SVPullToRefresh’ # … endend # Then in your controller def viewDidLoad 	# …. tableView.addPullToRefreshWithActionHandler    Proc.new {        loadMagicalData(tableView)        # do some other magic        # then don’t forget to:        tableView.pullToRefreshView.stopAnimating    }# …</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://tamersalama.com/2013/04/15/rubymotion-pulltorefresh/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Using NUI with RubyMotion</title>
		<link>https://tamersalama.com/2013/03/18/using-nui-with-rubymotion/</link>
					<comments>https://tamersalama.com/2013/03/18/using-nui-with-rubymotion/#respond</comments>
		
		<dc:creator><![CDATA[Tamer Salama]]></dc:creator>
		<pubDate>Mon, 18 Mar 2013 00:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubymotion]]></category>
		<guid isPermaLink="false">https://tamersalama.com/2013/03/18/using-nui-with-rubymotion/</guid>

					<description><![CDATA[NUI is an open-source library that allows you to style your iOS applications using CSS-like files and syntax. In my opinion, NUI carries few benefits over its commercial, KickStart backed, competitor Pixate. First; NUI allows you to style your application on the fly while it’s running in the simulator. And Second; NUI styled-elements are not masked/wrapped in their special&#46;&#46;&#46;]]></description>
										<content:encoded><![CDATA[<p><a href="https://github.com/tombenner/nui">NUI</a> is an open-source library that allows you to style your iOS applications using CSS-like files and syntax. In my opinion, NUI carries few benefits over its commercial, KickStart backed, competitor <a href="http://www.pixate.com/">Pixate</a>. First; NUI allows you to style your application on the fly while it’s running in the simulator. And Second; NUI styled-elements are not masked/wrapped in their special classes (like those PX* classes with pixate), rather, they remain as their original iOS declarations. The second point makes debugging the simulated application and tracking ons-creen objects (using cmd-hover) much easier.</p>
<p><strong>Installation:</strong><br /> In your RubyMotion application’s Rakefile: {% highlight ruby %} Motion::Project::App.setup do |app| #… app.pods do # … pod ‘NUI’ end end {% endhighlight %} Then run `</p>
<p>&#8220; `</p>
<p><strong>Usage:</strong><br /> Create a theme.nss file (which will include your application’s stylesheet). Then in your &#8220;{% highlight ruby %} class AppDelegate</p>
<p>@@nui_settings = NUISettings.init @@nui_settings.setAutoUpdatePath(“/absolute/path/to/project/and/theme.nss”)</p>
<p>def application(application, didFinishLaunchingWithOptions:launchOptions)</p>
<pre><code>12@nui = NUIAppearance.init# ...   end</code></pre>
<p>end {% endhighlight %}</p>
<p>Run `</p>
<p><code>` and check your application in the simulator. Now, any changes to the &lt;ts_code&gt;</code>&lt;/ts_code&gt; file will be reflected right away to the running application in the simulator. Happy styling</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tamersalama.com/2013/03/18/using-nui-with-rubymotion/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Consultancy Masterclass</title>
		<link>https://tamersalama.com/2013/03/18/consultancy-masterclass/</link>
					<comments>https://tamersalama.com/2013/03/18/consultancy-masterclass/#respond</comments>
		
		<dc:creator><![CDATA[Tamer Salama]]></dc:creator>
		<pubDate>Mon, 18 Mar 2013 00:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tech leadership]]></category>
		<guid isPermaLink="false">https://tamersalama.com/2013/03/18/consultancy-masterclass/</guid>

					<description><![CDATA[Last weekend, I sat through the two-day Consultancy Masterlcass by Brennan Dunn &#38; Obie Fernandez. Both Brennan and Obie have extensive experience building their own successful consultancy firms. The class was insightful and full of those ‘from the trenches’ experiences. What was of significant value is the knowledge transparently shared by students and alumni. All of whom are of&#46;&#46;&#46;]]></description>
										<content:encoded><![CDATA[<p>Last weekend, I sat through the two-day <a href="http://doubleyourfreelancingrate.com/build-a-consultancy">Consultancy Masterlcass</a> by <a href="http://doubleyourfreelancingrate.com/">Brennan Dunn</a> &amp; <a href="http://obiefernandez.com/">Obie Fernandez</a>. Both Brennan and Obie have extensive experience building their own successful consultancy firms. The class was insightful and full of those ‘from the trenches’ experiences. What was of significant value is the knowledge transparently shared by students and alumni. All of whom are of similar mindsets and are taking their steps in establishing their own names in the consultancy world. I look forward to being part of a great community.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tamersalama.com/2013/03/18/consultancy-masterclass/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Thoughts on building vs growing</title>
		<link>https://tamersalama.com/2012/11/09/thoughts-on-building-vs-growing/</link>
					<comments>https://tamersalama.com/2012/11/09/thoughts-on-building-vs-growing/#respond</comments>
		
		<dc:creator><![CDATA[Tamer Salama]]></dc:creator>
		<pubDate>Fri, 09 Nov 2012 00:00:00 +0000</pubDate>
				<category><![CDATA[Leadership]]></category>
		<category><![CDATA[general]]></category>
		<category><![CDATA[tech leadership]]></category>
		<guid isPermaLink="false">https://tamersalama.com/2012/11/09/thoughts-on-building-vs-growing/</guid>

					<description><![CDATA[Many times I’ve heard professionals talk and plan out building software applications. Great ideas they’d like seen implemented, and how it could make things better. Though might not seem obvious – software applications, at least the good, are never built. Applications are grown.[1] There’s quite the range of differences between building an application and growing one, but I’ll focus&#46;&#46;&#46;]]></description>
										<content:encoded><![CDATA[<p>Many times I’ve heard professionals talk and plan out building software applications. Great ideas they’d like seen implemented, and how it could make things better. Though might not seem obvious – software applications, at least the good, are never built.</p>
<p>Applications are grown.[1]</p>
<p>There’s quite the range of differences between building an application and growing one, but I’ll focus here on few main ones.</p>
<p>Building something is associated with a resulting rigid structure and components. It takes effort to put together, but once build – it’s static. All what’s left is usage, admiration &amp; maintenance.</p>
<p>On the other hand, growing something is an organic process. It rarely stops. It requires a continuous labour of love. You can reap benefits but as you do, you always have to give back, care and nurture.</p>
<p>Growing is more appropriate to the act of developing software. Applications doesn’t (or shouldn’t) reach a static rigid state, they always benefit from continuous assessment, reevaluation and changes. They adjust to surroundings. They evolve, transform and get bigger (but not necessarily more complex).</p>
<p>So – next time you’re discussing new applications – try to see how close the word ‘growing’ is to everyone.</p>
<p>[1] I wish I could remember where first I heard that or who said it.</p>
<blockquote><p>Migrated Comment &#8211; Steven: That’s a good way of putting it. I’m currently in the process of “weeding” an application.</p></blockquote>
<blockquote><p>Migrated Comment &#8211; Tamer Salama:<br />@steven Weed: verb ?”	/w?d/	”<br />Remove an inferior or unwanted component of a group or collection</p></blockquote>
<blockquote><p>I bet that’s exactly what you’re doing <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p></blockquote>
]]></content:encoded>
					
					<wfw:commentRss>https://tamersalama.com/2012/11/09/thoughts-on-building-vs-growing/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Rails and inner query choices</title>
		<link>https://tamersalama.com/2012/11/08/rails-and-inner-query-choice/</link>
					<comments>https://tamersalama.com/2012/11/08/rails-and-inner-query-choice/#respond</comments>
		
		<dc:creator><![CDATA[Tamer Salama]]></dc:creator>
		<pubDate>Thu, 08 Nov 2012 00:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://tamersalama.com/2012/11/08/rails-and-inner-query-choice/</guid>

					<description><![CDATA[Consider that we have two models; Well and SurveryPoints . A Well represent an oil/gas/water well, each with multiple SurveyPoints. A SurveyPoint represent the well’s coordinate at a certain depth. class Well &#60; ActiveRecord::Base has_many :survey_pointsendclass SurveyPoint &#60; ActiveRecord::Base belongs_to :wellend Say, we’d like to implement a filtration mechanism that allows us to query the wells – and for&#46;&#46;&#46;]]></description>
										<content:encoded><![CDATA[<p>Consider that we have two models; <code>Well</code> and <code>SurveryPoints</code> . A Well represent an oil/gas/water well, each with multiple SurveyPoints. A SurveyPoint represent the well’s coordinate at a certain depth.</p>
<pre><code class="language-ruby">class Well &lt; ActiveRecord::Base	has_many :survey_pointsendclass SurveyPoint &lt; ActiveRecord::Base	belongs_to :wellend</code></pre>
<p>Say, we’d like to implement a filtration mechanism that allows us to query the wells – and for those set of wells we’d like to conditionally present the set of <code>survey_points</code> for those set of filtered wells.</p>
<p>A method <code>find_for_wells</code> would returns the set of wells we’re interested in ( &#8220; )</p>
<p>Using the power of AREL chaining, we could then conditionally extract the <code>SurveyPoints</code> using the following:</p>
<pre><code class="language-ruby">def SurveyPoint.find_for_wells(wells)	scope.where(:well_id =&gt; wells.select(:id))end </code></pre>
<p>This roughly translates into the query:</p>
<pre><code class="language-sql">SELECT * FROM SURVEY_POINTS WHERE WELL_ID IN (SELECT ID FROM WELLS WHERE ….)</code></pre>
<p>The challenge here is that if both results is large, depending on the cardinality – the database engine might not be able to make use of defined indexes and the outer query might not be optimizable.</p>
<p>Instead – if we use pluck instead of select:</p>
<pre><code class="language-ruby">def self.find_for_wells(wells)	scope.where(:well_id =&gt; wells.pluck(:id))end </code></pre>
<p>Rails would fire two queries instead of an inner one. Pluck would first extract the list of ids (val_1, val_2, …) in an array before passing it to the main query. This roughly translates into:</p>
<pre><code class="language-sql">SELECT * FROM SURVEY_POINTS WHERE WELL_ID IN (val_1, val_2, val_3, ….) </code></pre>
<p>No inner query is used in that case and the main one is easy to optimize.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tamersalama.com/2012/11/08/rails-and-inner-query-choice/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
