<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>emre şahin's digital garden 🍃 - optimization</title>
    <link>https://emresahin.net/tags/optimization/</link>
    <description>Posts in the optimization tag</description>
    <language>en</language>
    <managingEditor>contact@emresahin.net (Emre Şahin)</managingEditor>
    <lastBuildDate>Tue, 15 Sep 2026 19:46:32 +0000</lastBuildDate>
    <atom:link href="https://emresahin.net/tags/optimization/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>Premature Caching is the Root of All Evil</title>
      <published>2021-12-22T20:32:35+00:00</published>
      <updated>2021-12-22T20:32:35+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Wed, 22 Dec 2021 20:32:35 +0000</pubDate>
      <link>https://emresahin.net/premature-caching/</link>
      <guid isPermaLink="true">https://emresahin.net/premature-caching/</guid>
      <description>I’m writing a Rust command line app in my spare time to learn the language. It involves some file system checks where I use fs::metadata . As everyone knows , accessing the disk is an expensive operation and must be kept to a minimum. I was thinking of using a HashMap::&lt;Path, Metadata&gt; to cache t...</description>
      <category>Development</category>
      <category>Software Engineering</category>
      <category>rust</category>
      <category>caching</category>
      <category>xvc</category>
      <category>optimization</category>
      <category>performance</category>
      <content:encoded><![CDATA[<p>I’m writing a Rust command line app in my spare time to learn the language. It
involves some file system checks where I use <code>fs::metadata</code>. As <em>everyone
knows</em>, accessing the disk is an <em>expensive</em> operation and must be kept to a
minimum. I was thinking of using a <code>HashMap::&lt;Path, Metadata&gt;</code> to cache the
results for paths.</p>
<p>I then came across the <a href="https://crates.io/cached">cached</a> crate. It caches the results of functions for
memoization. <em>This is exactly what I need</em>, I thought. Internally, it does what I
was planning to do.</p>
<p>Later, I noticed the possible bugs that could arise. I’m thinking of using the
function in a short-running process, so the metadata is not expected to change
during the run. For some reason, suppose the runtime of the process began to
get longer, or I decided to add a web server on top of it. At that time,
probably many moons from now, I’ll have forgotten the decision I made about
caches and my assumption that the metadata won’t change during the run. It
will cause some weird bugs when file timestamp changes aren’t detected.</p>
<p>No one will notice that I’m fixing bugs if they never appear, but I believe this
is the best kind of software engineering.</p>
<h2 id="commentary-2022-08-01">Commentary (2022-08-01)</h2>
<ul>
<li>It looks like my assumption that RAM is <em>significantly faster</em> than disk access may also be wrong.
SSDs are fast, and for parallel access, they may perform as fast as RAM.</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Coursera Deep Learning Specialization Notes</title>
      <published>2018-10-29T21:25:17+00:00</published>
      <updated>2018-10-29T21:25:17+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Mon, 29 Oct 2018 21:25:17 +0000</pubDate>
      <link>https://emresahin.net/coursera-deep-learning-14336-24273/</link>
      <guid isPermaLink="true">https://emresahin.net/coursera-deep-learning-14336-24273/</guid>
      <description>Per the Honor Code, these notes do not contain answers to quizzes or assignments. If you are looking for those, please look elsewhere. Binary Classification Given an image, classify it as cat or non-cat. The result is $\hat{y} = P(y=1 | x)$. In other words, given $x$, we calculate the probability...</description>
      <category>Deep Learning</category>
      <category>Coursera</category>
      <category>Neural Networks</category>
      <category>Optimization</category>
      <category>CNN</category>
      <category>RNN</category>
      <category>YOLO</category>
      <category>Machine Learning</category>
      <category>Backpropagation</category>
      <category>Activation Functions</category>
      <content:encoded><![CDATA[<p><strong>Per the Honor Code, these notes do not contain answers to quizzes or assignments. If you are looking for those, please look elsewhere.</strong></p>
<h2 id="binary-classification">Binary Classification</h2>
<p>Given an image, classify it as <em>cat</em> or <em>non-cat.</em> The result is $\hat{y} = P(y=1 | x)$. In other words, given $x$, we calculate the probability that this data represents a cat.</p>
<h2 id="feature-vector-from-image">Feature Vector from Image</h2>
<p>We convert an image, e.g., a (64, 64, 3) image, into a (64 * 64 * 3, 1) feature vector.</p>
<h2 id="sigmoid">Sigmoid</h2>
<p>$$\hat{y} = \sigma(w^Tx + b)$$</p>
<p>$w$ represents the weights, $w^T$ is the transpose of $w$, $x$ is the input, and $b$ is the bias.</p>
<h2 id="loss-function">Loss Function</h2>
<p>The loss function measures the error between the real value of $y$ and our prediction $\hat{y}$ for a <em>single training example.</em></p>
<p>$$ L(\hat{y}, y) = \frac{1}{2}(\hat{y}-y)^2 $$</p>
<h2 id="cost-function">Cost Function</h2>
<p>The average of the <em>loss</em> across all training examples.</p>
<h2 id="learning-rate">Learning Rate</h2>
<p>The learning rate $\alpha$ is the coefficient applied to update weights:</p>
<p>$$w’ = w - \alpha \frac{dd(w)}{dw}$$</p>
<p>If it is too small, learning occurs slowly; if it is too large, it may overshoot the optimum point. Thus, it should be selected wisely.</p>
<h3 id="idea-can-we-use-a-vector-instead-of-a-single-value-for-the-learning-rate">IDEA: Can we use a vector instead of a single value for the learning rate?</h3>
<p>For Leaky ReLU activation functions, this seems possible, though likely overkill. Using $\alpha$ as a vector adds a layer of complexity and requires more computation to adjust (allowing some features to update more slowly than others).</p>
<h2 id="the-feature-vector">The Feature Vector</h2>
<p>$X$ is a feature matrix with $m$ columns, each representing a different training example. Each example has $n$ features. So, <code>X.shape = (n, m)</code>.</p>
<p><code>Y.shape = (1, m)</code>.</p>
<h2 id="the-computation-graph">The Computation Graph</h2>
<p>Any formula can be converted into a graph where operands are vertices and operations are edges.</p>
<figure><img src="https://emresahin.net/images/computation-graph.jpg" alt="" style="width: 300px"></figure>
<p>In neural networks, computation flows forward from inputs to output, while the derivatives are calculated from output back to input.</p>
<h2 id="the-notation-for-layers-and-training-examples">The Notation for Layers and Training Examples</h2>
<p>$X^{(i)}$ refers to the $i^{th}$ training example.</p>
<p>$z^{[i]}$ refers to the $z$ values in the $i^{th}$ layer.</p>
<p>$z^{[1]}$ is the $z$ value for layer 1.</p>
<p>$a^{[2]}$ is the $a$ value for layer 2.</p>
<p>$a^{[1]} = [a^{[1]}_1, a^{[1]}_2, a^{[1]}_3, a^{[1]}_4]^T$ for a neural net having 4 nodes in hidden layer 1.</p>
<figure><img src="https://emresahin.net/images/2-layer-nn.jpg" alt="" width="300"></figure>
<h2 id="steps-of-computation">Steps of Computation</h2>
<p>There are two steps of computation:</p>
<ol>
<li>$z^{[1]} = w^{[1]T}x + b^{[1]}$</li>
<li>$a^{[1]} = \sigma(z^{[1]})$</li>
</ol>
<p>In step 1, weights and inputs are dot-multiplied and the bias is added. In step 2, an activation function is applied to this result. While $\sigma$ is used here, other functions can also serve this purpose.</p>
<h2 id="backpropagation-algorithm">Backpropagation Algorithm</h2>
<p>This is the fundamental algorithm that updates weights to find a solution.</p>
<p>In the forward pass, the cost function $L(\hat{y}, y)$ is computed.</p>
<p>In backpropagation, weights and biases are adjusted based on their derivatives multiplied by the learning factor $\alpha$.</p>
<p>While the actual formulas can be complex, the general idea is to calculate derivatives from the last layer back to the first and adjust weights accordingly.</p>
<h2 id="vectorization-notation">Vectorization Notation</h2>
<p>Multiple training examples are denoted by the superscript $(i)$.</p>
<p>The vectorized representation of the $Z$ matrix for multiple inputs and multiple layers is:</p>
<p>$$Z = \begin{pmatrix}
z^{<a href="1">1</a>} &amp; z^{<a href="2">1</a>} &amp; z^{<a href="3">1</a>} &amp; \dots &amp; z^{<a href="m">1</a>} \
z^{<a href="1">2</a>} &amp; z^{<a href="2">2</a>} &amp; z^{<a href="3">2</a>} &amp; \dots &amp; z^{<a href="m">2</a>} \
z^{<a href="1">3</a>} &amp; z^{<a href="2">3</a>} &amp; z^{<a href="3">3</a>} &amp; \dots &amp; z^{<a href="m">3</a>} \
\dots      &amp; \dots      &amp; \dots      &amp; \dots &amp; \dots      \
z^{<a href="1">n</a>} &amp; z^{<a href="2">n</a>} &amp; z^{<a href="3">n</a>} &amp; \dots &amp; z^{<a href="m">n</a>} \
\end{pmatrix}$$</p>
<p>The $A$ matrix is structured similarly.</p>
<p>Since $w^{[i]T}x + b^{[i]}$ is a column vector, we concatenate these column vectors for multiple inputs.</p>
<h2 id="activation-functions">Activation Functions</h2>
<p>There are roughly four types of activation functions:</p>
<h3 id="sigmoid-1">Sigmoid</h3>
<p>This is the historic default. There is generally no need to use it except in the final output layer for binary classification (0 or 1).</p>
<h3 id="tanh">Tanh</h3>
<p>It is generally superior to the sigmoid function. It is asymptotic between 1 and -1, which often leads to better training behavior.</p>
<h3 id="relu">ReLU</h3>
<p>A simple function, $r = \max(0, x)$, which has become very popular.</p>
<h3 id="leaky-relu">Leaky ReLU</h3>
<p>Since ReLU is not differentiable for $x &lt; 0$, this version adds a small slope ($r = \max(0.01x, x)$) for negative values.</p>
<h2 id="training-set-and-test-set">Training Set and Test Set</h2>
<p>Traditionally, with datasets of 100 to 10,000 elements, splits like 70/30% or 60/20/20% were common.</p>
<p>However, in the era of Big Data™, where datasets may contain 10,000,000 elements, such percentages are unnecessary. It is more reasonable to keep a fixed number, such as 10,000 elements, for the dev and test sets to speed up development.</p>
<p>Crucially, this data should come from the same distribution. Dev and test sets are used to check for overfitting and evaluate real-world performance.</p>
<h2 id="bias-and-variance">Bias and Variance</h2>
<p><em>High bias</em> indicates the model is <em>underfitting.</em>
<em>High variance</em> indicates the model is <em>overfitting.</em></p>
<h3 id="high-bias">High Bias</h3>
<p>Example: Train Set Error Rate: 15%, Dev Set Error Rate: 16%.
The model is too simple to learn the data.
Solutions: Use a larger network, train longer, or change the NN architecture.</p>
<h3 id="high-variance">High Variance</h3>
<p>Example: Train Set Error Rate: 1%, Dev Set Error Rate: 14%.
The model overfits the training data and fails to generalize.
Solutions: Get more data, use regularization, or change the NN structure.</p>
<h3 id="high-bias-and-high-variance">High Bias and High Variance</h3>
<p>While classical models often face a bias/variance tradeoff, Deep Learning models can suffer from both simultaneously (e.g., 15% Train Set error and 30% Dev Set error).
Solutions: Larger network, more data, regularization, and architecture changes.</p>
<h2 id="regularization">Regularization</h2>
<p>Used to decrease variance and prevent overfitting.
Two main types: <em>L2 Regularization</em> (adds a factor to the weights) and <em>Dropout Regularization</em> (randomly sets some weights to zero).</p>
<h3 id="l2-regularization">L2 Regularization</h3>
<p>Without regularization: $$w^{[l]} \leftarrow w^{[l]} - \alpha (dw^{[l]})$$
With regularization, we add a decay factor: $$ -\alpha (\frac{\lambda}{2m} w^{[l]}) $$
The full formula becomes: $$w^{[l]} \leftarrow (1 - \alpha \frac{\lambda}{2m}) w^{[l]} - \alpha dw^{[l]}$$
This is called <em>weight decay</em> because it pulls $w$ closer to zero, effectively making the network “smaller.”</p>
<h3 id="dropout">Dropout</h3>
<p>Dropout is a technique where the algorithm randomly “knocks out” nodes during training. These nodes are temporarily ignored during weight updates.</p>
<p>In each iteration, a random subset of nodes is removed based on a <code>keep-prob</code>. For example, a <code>keep-prob</code> of 0.5 means roughly half the nodes are ignored.</p>
<h3 id="data-augmentation">Data Augmentation</h3>
<p>Generating variations of existing images (e.g., flipping, rotating, adding noise) is also a form of regularization.
Note: Changes shouldn’t alter the image’s meaning (e.g., a flipped “4” might not be a “4”).</p>
<h3 id="early-stopping">Early Stopping</h3>
<p>As training progresses, the cost function $J$ for the training set continues to decrease, but the test set $J$ eventually begins to increase, indicating overfitting. We can stop training at that inflection point.</p>
<h2 id="normalization">Normalization</h2>
<p>Normalization involves bringing all feature values $X$ into a similar range. If $x_1$ is between 1 and 1000 and $x_2$ is between 0 and 1, the network may struggle.
A common approach is $x_i = \frac{x_i - \mu_i}{\sigma_i}$, where $\mu_i$ is the mean and $\sigma_i$ is the standard deviation.</p>
<h2 id="exploding-and-vanishing-gradients">Exploding and Vanishing Gradients</h2>
<p>In deep networks, weight values may exponentially increase or decrease. If all weights are 2, the final activation in an $l$-layer network becomes $2^l$, leading to exploding gradients. Conversely, weights less than 1 can lead to vanishing gradients where the network fails to learn.</p>
<h2 id="weight-initialization-to-alleviate-explodingvanishing-gradients">Weight Initialization to Alleviate Exploding/Vanishing Gradients</h2>
<figure><img src="https://emresahin.net/images/node-weights.jpg" alt="" width="300"></figure>
<p>To prevent these issues, it is best to initialize weights with a variance of $\frac{1}{n}$, where $n$ is the number of nodes in a layer.</p>
<p>For ReLU:</p>
<pre><code class="language-python">W[i] = np.random.randn(shape) * np.sqrt(2 / n[i-1])
</code></pre>
<p>For <code>tanh</code>:</p>
<pre><code class="language-python">W[i] = np.random.randn(shape) * np.sqrt(1 / n[i-1])
</code></pre>
<p>Another option is <em>Xavier</em> initialization:</p>
<pre><code class="language-python">W[i] = np.random.randn(shape) * np.sqrt(2 / (n[i] + n[i-1]))
</code></pre>
<h3 id="initialization-by-zero">Initialization by Zero</h3>
<p>Initializing weights to all zeros fails to break symmetry, and the network will not learn. However, it is perfectly fine to initialize <em>biases</em> to zero.</p>
<h3 id="initialization-with-random-numbers">Initialization with Random Numbers</h3>
<pre><code class="language-python">W[i] = np.random.randn(layer_dim[l], layer_dim[l-1]) * FACTOR
</code></pre>
<p>If <code>FACTOR</code> is too large (e.g., 10), the network may converge slowly or suffer from exploding gradients.
Using <code>np.sqrt(2 / layer_dim[l-1])</code> is known as <em>He</em> initialization, while <code>np.sqrt(1 / layer_dim[l-1])</code> is <em>Xavier</em> initialization.</p>
<h2 id="mini-batches">Mini-Batches</h2>
<p>When dealing with massive datasets (e.g., 10 million images), we cannot process them all at once. Instead, we divide them into <em>mini-batches.</em></p>
<ul>
<li><strong>Stochastic Gradient Descent:</strong> Batch size of 1.</li>
<li><strong>Batch Gradient Descent:</strong> Batch size equals the entire training set.</li>
<li><strong>Mini-Batch Gradient Descent:</strong> Sizes typically range from 32 to 512.</li>
</ul>
<h2 id="optimization-momentum">Optimization: Momentum</h2>
<p>When training with mini-batches, it helps to track previous gradients to smooth out updates. A hyperparameter $\beta$ determines the influence of past gradients.</p>
<h2 id="optimization-rmsprop">Optimization: RMSprop</h2>
<p>Instead of simple updates, RMSprop uses the squared gradients to scale the updates:</p>
<p>$$s_{dW} \leftarrow \beta_2 s_{dW} - (1 - \beta_2) (dW)^2$$
$$ W \leftarrow W - \alpha \frac{dW}{\sqrt{s_{dW} + \epsilon}} $$</p>
<p>This reduces oscillations and speeds up convergence.</p>
<h2 id="optimization-adam">Optimization: Adam</h2>
<p>Adam combines Momentum and RMSprop. It uses two hyperparameters, $\beta_1$ and $\beta_2$, and is generally the most effective optimization algorithm, converging much faster than others.</p>
<h2 id="learning-rate-decay">Learning Rate Decay</h2>
<p>A fixed learning rate $\alpha$ can make convergence difficult. We can decay the learning rate over time:
$\alpha = \frac{1}{1 + d * t} \alpha_0$, where $d$ is the decay rate and $t$ is the epoch number.</p>
<h1 id="hyperparameter-tuning">Hyperparameter Tuning</h1>
<p>Key hyperparameters include the learning rate $\alpha$, optimization coefficients $\beta_1$ and $\beta_2$, number of layers, units per layer, activation functions, and mini-batch sizes.</p>
<p>Heuristics:</p>
<ul>
<li>Random search is often better than a uniform grid.</li>
<li>Search on a logarithmic scale for parameters like $\alpha$ or $\beta$ (e.g., searching $1-10^r$ for $\beta$).</li>
</ul>
<h1 id="batch-normalization">Batch Normalization</h1>
<p>Batch normalization normalizes layer activations using two learnable parameters, $\beta$ and $\gamma$. It helps information flow to deeper layers and makes the network less sensitive to initial weight scales.</p>
<h1 id="softmax-activation">Softmax Activation</h1>
<p>For multi-class classification, the final layer uses a <em>softmax</em> function to output a probability vector:
$$a_i^{[l]} = \frac{e^{z_i^{[l]}}}{\sum_{j=1}^C e^{z_j^{[l]}}}$$
where $C$ is the number of classes.</p>
<h1 id="metrics">Metrics</h1>
<p>Single-number metrics like F1 Score or mAP make evaluation much easier.</p>
<ul>
<li><strong>Optimizing Metric:</strong> The primary number you try to improve.</li>
<li><strong>Satisficing Metric:</strong> A threshold that must be met (e.g., running time &lt; 100ms).</li>
</ul>
<h1 id="error-analysis">Error Analysis</h1>
<p>Regularly inspect a subset of misclassified examples to understand where the model is failing.</p>
<h1 id="data-mismatch">Data Mismatch</h1>
<p>If your training and test data come from different distributions, use a <em>training-dev</em> set to identify if performance drops are due to the model failing to generalize or a fundamental difference in data.</p>
<h1 id="transfer-learning">Transfer Learning</h1>
<p>You can take a model trained on task A and repurpose it for task B. This is especially useful when task B has limited data.</p>
<h1 id="multi-task-learning">Multi-Task Learning</h1>
<p>One network can be trained to perform multiple tasks simultaneously (e.g., detecting pedestrians AND traffic signs), provided the network is large enough.</p>
<h1 id="end-to-end-learning">End-to-End Learning</h1>
<p>In end-to-end learning, the network maps raw input directly to the final output, bypassing traditional hand-engineered feature extraction steps. This requires significant amounts of data to be effective.</p>
<h1 id="convolutional-neural-networks-cnns">Convolutional Neural Networks (CNNs)</h1>
<p>CNNs are the standard for image processing. They apply filters (kernels) to images to extract features. The resulting matrix size is determined by the input size $n$ and filter size $f$ (result size: $n-f+1$).</p>
<h2 id="padding">Padding</h2>
<p>Padding adds a border of pixels (usually zeros) around the input to prevent the image from shrinking after each convolution layer.</p>
<h1 id="classic-networks">Classic Networks</h1>
<h2 id="lenet-5">LeNet-5</h2>
<p>A 1998 network designed for digit recognition (32x32x1). It is small (60k parameters) but foundational.</p>
<h2 id="alexnet-and-vgg-16">AlexNet and VGG-16</h2>
<p>AlexNet (2012) popularized Deep Learning. VGG-16 (138M parameters) used a very consistent architecture of 3x3 filters and max-pooling.</p>
<h1 id="resnets">ResNets</h1>
<p>Residual Networks use “shortcuts” or “skip connections” to allow gradients to flow through very deep networks (100+ layers) without vanishing.</p>
<h1 id="1x1-convolutions">1x1 Convolutions</h1>
<p>1x1 convolutions are used to reduce or increase the number of channels (depth) in a volume while adding non-linearity.</p>
<h1 id="inception-network">Inception Network</h1>
<p>Inception modules apply 1x1, 3x3, 5x5 convolutions and pooling in parallel, then concatenate the results.</p>
<h1 id="object-detection">Object Detection</h1>
<h2 id="yolo-algorithm">YOLO Algorithm</h2>
<p>“You Only Look Once” divides an image into a grid (e.g., 19x19) and predicts bounding boxes and class probabilities for each cell simultaneously.</p>
<h2 id="anchor-boxes">Anchor Boxes</h2>
<p>Anchor boxes allow a single grid cell to detect multiple objects (e.g., a person standing in front of a car).</p>
<h2 id="non-max-suppression">Non-Max Suppression</h2>
<p>NMS filters out overlapping bounding boxes, keeping only the most confident ones.</p>
<h1 id="face-recognition">Face Recognition</h1>
<h2 id="one-shot-learning">One-Shot Learning</h2>
<p>Learning to recognize a person from just one image. This is often solved using a Siamese network that learns a similarity metric.</p>
<h2 id="similarity-metric">Similarity Metric</h2>
<p>A function $f(A)$ that maps an image to a feature vector. The distance $d(A, B) = ||f(A) - f(B)||^2$ tells us how similar two faces are.</p>
<h1 id="visual-style-transfer">Visual Style Transfer</h1>
<p>Style transfer creates a new image $G$ that combines the content of image $C$ with the artistic style of image $S$. This is achieved by minimizing a cost function with both content and style components.</p>
<h1 id="word-embeddings">Word Embeddings</h1>
<p>Word embeddings represent words as dense vectors where similar words have similar vectors.</p>
<ul>
<li><strong>Analogies:</strong> $e_{king} - e_{man} + e_{woman} \approx e_{queen}$.</li>
<li><strong>Cosine Similarity:</strong> A common measure of vector similarity.</li>
</ul>
<h2 id="word2vec">word2vec</h2>
<p>A popular algorithm for learning word embeddings by predicting a word from its neighbors (or vice versa).</p>]]></content:encoded>
    </item>
  </channel>
</rss>
