<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://weinajin.github.io/feed.xml" rel="self" type="application/atom+xml"/><link href="https://weinajin.github.io/" rel="alternate" type="text/html" hreflang="en"/><updated>2026-09-23T16:58:00+00:00</updated><id>https://weinajin.github.io/feed.xml</id><title type="html">blank</title><subtitle>A medical AI researcher with a critical, user-centered approach for the benefits of patients&apos; healthcare and society. </subtitle><entry><title type="html">Critical Technical Practice for Responsible Medical Image Analysis</title><link href="https://weinajin.github.io/ctp_mia" rel="alternate" type="text/html" title="Critical Technical Practice for Responsible Medical Image Analysis"/><published>2026-07-13T10:00:00+00:00</published><updated>2026-07-13T10:00:00+00:00</updated><id>https://weinajin.github.io/ctp_mia</id><content type="html" xml:base="https://weinajin.github.io/ctp_mia"><![CDATA[<h1 id="critical-technical-practice-for-responsible-medical-image-analysis">Critical Technical Practice for Responsible Medical Image Analysis</h1> <p>By Weina Jin (weinaj@sfu.ca)</p> <p>2026-07-13</p> <p><strong>TL;DR</strong>: Critical technical practice can safeguard our good intentions in medical image analysis against distortion and manipulation from unscientific and unethical assumptions and values, analogous to strengthening our technical immune systems.</p> <p>1-min promotional video for this tutorial, recorded for <a href="https://miccai-sb.github.io/materials.html">MICCAI Educational Challenge 2026</a>.</p> <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/A_fP4_E7dTk?si=rBM4h2k8wDTk6SYU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe> <p><strong>Abstract</strong>: In this article, I motivate the need for critical technical practice using my research experience in conducting AI technical research on explainable AI for medical image analysis. I summarize the different levels of approaches to conduct critical technical practice, and propose ways forward to collectively conduct critical technical practice to make our techniques more scientifically rigorous, ethical, and responsible.</p> <details open=""> <summary class="text-delta"> Table of contents </summary> <ol id="markdown-toc"> <li><a href="#critical-technical-practice-for-responsible-medical-image-analysis" id="markdown-toc-critical-technical-practice-for-responsible-medical-image-analysis">Critical Technical Practice for Responsible Medical Image Analysis</a> <ol> <li><a href="#does-good-intentions-of-tech-for-healthcare-guarantee-good-outcomes" id="markdown-toc-does-good-intentions-of-tech-for-healthcare-guarantee-good-outcomes">Does good intentions of tech for healthcare guarantee good outcomes?</a></li> <li><a href="#why-good-intentions-can-be-distorted-in-technical-development" id="markdown-toc-why-good-intentions-can-be-distorted-in-technical-development">Why good intentions can be distorted in technical development?</a></li> <li><a href="#critical-technical-practice-in-medical-image-analysis-a-preliminary-approach" id="markdown-toc-critical-technical-practice-in-medical-image-analysis-a-preliminary-approach">Critical technical practice in medical image analysis: a preliminary approach</a> <ol> <li><a href="#high-level-technical-practice" id="markdown-toc-high-level-technical-practice">High level technical practice</a></li> <li><a href="#middle-level-technical-practice" id="markdown-toc-middle-level-technical-practice">Middle level technical practice</a></li> <li><a href="#low-level-technical-practice" id="markdown-toc-low-level-technical-practice">Low level technical practice</a></li> </ol> </li> <li><a href="#the-anticipated-resistance" id="markdown-toc-the-anticipated-resistance">The anticipated resistance</a></li> <li><a href="#actionable-ideas-for-critical-technical-practice" id="markdown-toc-actionable-ideas-for-critical-technical-practice">Actionable ideas for critical technical practice</a></li> </ol> </li> </ol> </details> <h2 id="does-good-intentions-of-tech-for-healthcare-guarantee-good-outcomes">Does good intentions of tech for healthcare guarantee good outcomes?</h2> <p>For people working in the medical image analysis field, most of us are motivated by good intentions of using technologies to do good for health. I also have the same motivation when coming into the medical image analysis field: if I can develop techniques that help healthcare professionals and patients, that would be fantastic! How can it possibly go wrong?</p> <p>Well, it turns out that my initial assumption was wrong. Good intentions don’t guarantee good outcomes. “The road to hell is paved with good intentions,” which proverb I learned the hard way from my PhD research experience. The logic is simple: just as scientific outcomes are hard to achieve and can easily be distorted during the process, the same holds true for good outcomes. I was wrong in naively assuming that no distortion was the default; instead, distortion and manipulation of our well-meaning goals should be assumed to be the default to keep us <a href="https://www.dan.sperber.fr/wp-content/uploads/Epistemic-Vigilance-published.pdf">epistemically vigilant</a>. Given this, we need a strong technical immune system to protect our good intentions, mirroring the self-correcting mechanism of science. I call this immune system <strong>critical technical practice</strong>, which is to critically examine assumptions and justifications in common technical practices, and understand weaknesses, flaws, and boundaries of a technique.</p> <h2 id="why-good-intentions-can-be-distorted-in-technical-development">Why good intentions can be distorted in technical development?</h2> <p>I would like to share my research experience of how I realized my good intentions can be distorted in technical development. When I first started my PhD research in explainable AI (XAI) for medical image analysis, I aimed to conduct an evaluation of different XAI algorithms to test their clinical suitability. I surveyed XAI literature and found that one of the popular evaluation metric is plausibility, which measures the reasonableness of AI explanations according to human knowledge on the given task. Because it is a reasonable and popular metric, I used it in my first <a href="https://arxiv.org/abs/2107.05047">XAI paper</a>. Later, <a href="https://www.sciencedirect.com/science/article/abs/pii/S0933365723002658">when I had the opportunity to work with our clinical collaborator</a>, I clearly remember that the doctor mentioned that when he saw a plausible explanation, he would trust the AI system more; and when he saw an implausible explanation, he interpreted it as a good sign to enable him to see through the AI system to understand the flaws in it. The plausible explanation the doctor commented on, however, actually corresponds to an incorrect AI prediction. Just at that moment, I realized that there’s something wrong with the plausible metric in XAI: the use of the plausibility metric to evaluate and optimize XAI algorithms actually encourages the occurrence of misleading explanations, those that explain AI’s wrong predictions using seemingly plausible explanations.</p> <p>In <a href="https://www.sciencedirect.com/science/article/abs/pii/S1361841522003127">our final paper of this project</a>, we pointed out the problem with the plausibility metric, and used another criterion of informative plausibility instead, which means the correlation between explanation plausibility and AI prediction quality. After done all these things, I still felt that there’s something weird: If it’s not difficult to identify problems of the plausibility metric (like in my experience, I just showed doctor the AI explanation and found out its problem), then why the entire XAI community hasn’t found its problem and stopped using it as an XAI metric? To the contrary, plausibility is the most commonly used XAI metric <a href="https://dl.acm.org/doi/10.1145/3583558">according to a systematic review</a>. This is worrisome because <strong>anyone who uses XAI algorithms for good intentions such as making AI more transparent and explainable to clinical users, is likely to end up misleading and manipulating users by using the most popular XAI metric of plausibility,</strong> just like what I did in my first <a href="https://arxiv.org/abs/2107.05047">XAI paper</a>. In this plausibility case, the unethical consequence of misleading users cannot be attributed to any bad actors. Bad outcome comes exactly from ordinary technical practice by following technical conventions and common practices. “A bad system will beat a good person every time.” So the problem is in the social system of the technical community that sets wrong metric as XAI technical standards. Then why it is possible for a scientific community to make such an obvious mistake without self correcting it timely?</p> <p>For a while, I didn’t have a good answer to this question until I read two books that tell stories about how the big corporations can manipulate and distort scientific agendas can easily be manipulated by the for-profit powerful:</p> <p>In the book <em><a href="https://press.uchicago.edu/ucp/books/book/chicago/S/bo221451790.html">Soda Science: Making the World Safe for Coca-Cola</a></em>, anthropologist Susan Greenhalgh tells the story of how industry leader Coca-Cola collaborated with academia to conduct real scientific research that advocated exercise, not calorie restraint, as the priority solution for obesity. This distorted research agenda influenced public health policies on obesity and public understanding on diet and lifestyle in favor of the needs and profits of soda industry.</p> <p>In the book <em><a href="https://www.matteringpress.org/books/ghost-managed-medicine">Ghost-Managed Medicine: Big Pharma’s Invisible Hands</a></em>, Sergio Sismondo detailed how ordinary research activities can be shaped to server the private, not public, interests.</p> <blockquote> <p>“Pharmaceutical companies sustain large networks to gather, create, control and disseminate information. They provide the pathways that carry this information, and the energy that makes it move. Through bottlenecks and around curves, knowledge is created, given shape by the channels it navigates. Pharma companies create medical knowledge and move it to where it is most useful; much of it is perfectly ordinary knowledge that happens to support their marketing goals. But because of the companies’ resources, their interests and their levels of control, they become key shapers of almost all medical terrains.”</p> </blockquote> <p>It seems that big food, big pharma, and big tech corporations have the power to shape scientific communities according to their for-profit agendas. But how does the manipulation of scientific and medical agendas so successful? People in the scientific communities are researchers and scientists. Don’t they know they are being manipulated?</p> <p>There is another paragraph in <em><a href="https://www.matteringpress.org/books/ghost-managed-medicine">Ghost-Managed Medicine</a></em> that detail how the manipulation appears as a natural, inevitable, and scientific process:</p> <blockquote> <p>“Together, the many elements that pharmaceutical companies shape, adjust and assemble constitute markets. These markets are new creations, but because they draw together medical science and health needs they take on an appearance of necessity. They look like entities that have emerged whole from just below the social surface. The goal of pharma’s assemblage marketing is to establish conditions that make specific diagnoses, prescriptions and purchases as obvious and frequent as possible. Ideally, all of the elements of a market can be directed towards the same issues, claims and facts, so that the drugs sell themselves. Pharma companies can then recede into the background, and apply only minimal pressure when needed.”</p> </blockquote> <p>In <em><a href="https://firstmonday.org/ojs/index.php/fm/article/view/13636">The TESCREAL bundle: Eugenics and the promise of utopia through artificial general intelligence</a></em>, by foregrounding the underlying ideologies of the AGI agenda, Timnit Gebru and Émile P. Torres describe similar phenomenon of how the powerful parties set the mainstream agenda in the AI community that appears to be “a natural progression”:</p> <blockquote> <p>‘This investment has succeeded in legitimizing the AGI race such that many students and practitioners who may not be aligned with TESCREAL utopian ideals are working to advance the AGI agenda because it is presented as a natural progression in the field of AI. In the same way that first-wave eugenicists and race scientists sought and achieved academic legitimacy for their research (Saini, 2019), TESCREALists have created a veneer of scientific authority that makes their ideas more palatable to uncritical audiences, and thus have succeeded in influencing research and policy directions in the field of AI. First-wave eugenics proved to be ineffective and catastrophic. But as Jean Gayon and Daniel Jacobi signify with the term “eternal return of eugenics,” eugenic ideals keep on being repackaged in different forms [129]. The AGI race is yet another attempt, diverting resources and attention away from potentially useful research directions, and causing harm in the process of trying to achieve a techno-utopian ideal crafted by self appointed “vanguards” of humanity.’</p> </blockquote> <p>So the mechanism of how powerful corporations manipulate scientific agenda is more insidious and complicated than I assumed. Improving our technical immune system against the conventional formed dysfunctional and problematic practices means we need to understand the mechanisms at the roots, which is related to how power works in the sociotechnical system of scientific community. I wrote this paper <em><a href="https://arxiv.org/abs/2510.10588">Making Power Explicable in AI: Analyzing, Understanding, and Redirecting Power to Operationalize Ethics in AI Technical Practice</a></em> with my co-authors to detail such mechanisms, using the XAI field as a case study. In short, as the picture illustrates, if unjust power has penetrated and polluted the roots that makes the whole technical conduct appear to be natural, our technical immune system should also function in all the pathways from roots to leaves to defend against the pollution, by critically reflecting the taken-for-granted assumptions and setting preventative guardrails. Next, I will describe my proposed approach to achieve this goal.</p> <p><img src="../../assets/images/tree.jpg" alt="sociotechnical_system"/></p> <h2 id="critical-technical-practice-in-medical-image-analysis-a-preliminary-approach">Critical technical practice in medical image analysis: a preliminary approach</h2> <p>Here I would like to describe my current approach to critical technical practice in medical image analysis (MIA). I hope this can provide some concrete idea to inspire you to consider how to strengthen the technical immune system in your task or your own subfield in MIA. Note this is a constantly evolving and dynamic approach. Since strengthening our technical immune system is a systematic and collective effort, a key strategy along the way is to find allies and collaborators to work together toward this goal. This is the motivation for me to write this article.</p> <p>I categorize approaches that tackle the critical aspects in technical practice into three levels: the high level, middle level, and low level technical practice according to the scope of the problem. This can correspond to the roots, trunk/branches, and leaves in the above tree metaphor.</p> <h3 id="high-level-technical-practice">High level technical practice</h3> <p>Criticality in high level technical practice refers to questioning the overarching goals of technical development, to ask more “why” questions. As technical people, we probably ask more “how” questions than the “why” questions.The “how” questions enable us to solve problems with techniques, i.e, make better hammers, while the “why” questions challenge the fundamental motivation and the overall assumptions in the technical problem formulation, i.e, questioning if we treat everything as nails that can be solved by our hammer, or challenging the motivation for us to build hammer (e.g.: why not building screwdriver or other tools, or why do we need to build tools).</p> <p>For example, in our paper <em><a href="https://arxiv.org/abs/2503.08720">AI for Just Work: Constructing Diverse Imaginations of AI beyond “Replacing Humans”</a></em>, we urge the AI community to ask more “why” questions by pointing out limitations in the existing answers to the “why develop AI” question, including outperforming humans, improving efficiency, and freeing human labor from toil. Similarly for medical image analysis tasks, we can question the assumptions that motivate MIA techniques in the first place, such as improving clinical decision quality and efficiency, or reducing medical errors. For example, in “<em><a href="https://arxiv.org/abs/2508.09293">Ethical Medical Image Synthesis</a></em>”, we point out that the motivation of “overcoming human error” assumes that computational models can be epistemically more capable than healthcare professionals, which is a manifestation of <a href="https://academic.oup.com/book/32817">epistemic injustice</a>. This assumption influences the low level technical practice of how the evaluation paradigm of computational models is set: evaluation that emphasizes model strengths but ignores model weaknesses and limitations (<a href="https://arxiv.org/abs/2508.09293">v1, page 40-41</a>).</p> <p>We can also question the fundamental assumptions in the current healthcare systems. For example:</p> <ul> <li>Is improving efficiency really the optimal way to improve healthcare quality?</li> <li>Are there any other non-technical or less technical ways that may be more effective to improve healthcare quantity?</li> <li>In her book <em><a href="https://www.amazon.ca/Ordinary-Medicine-Extraordinary-Treatments-Longer/dp/0822358883">Ordinary Medicine</a></em>, Sharon R. Kaufman rethinks medical goals and questions the fundamental assumptions that drive healthcare innovation and services of “more is better”.</li> <li>In her book <em><a href="https://www.taylorfrancis.com/books/mono/10.4324/9780203927076/logic-care-annemarie-mol">The Logic of Care</a></em>, Annemarie Mol questions the fundamental concepts of “good care” and “patient choice”.</li> <li>In her book <em><a href="https://www.ubcpress.ca/the-impossible-clinic">The Impossible Clinic</a></em>, Ariane Hanemaayer provides a critical inspection of evidence-based medicine.</li> </ul> <p>These fundamental questions may be beyond the technical domain and more into the social and philosophical realm, and may not be easily answered. But the process of seeking answers to these big questions itself can be rewarding and intellectually fulfilling. More importantly, it enables us to foreground the underlying big picture, which may be set to appear as natural and inevitable but not necessarily so.</p> <h3 id="middle-level-technical-practice">Middle level technical practice</h3> <p>Middle level technical practice refers to the set of assumptions, problem formulations, and problem-solving paradigms that outline common technical approaches in a task or field. For example, in MIA field, regarding the most common research paradigm, it usually involves data-driven model building, with the pipeline of having a medical imaging problem to solve, a deep learning based model to design and train, and evaluation methods to test the model performance in comparison with benchmark or baseline models. Criticality in middle level technical practice means to critically reflect and examine the scientific rigor and responsibility in these practices regarding different MIA tasks such as image recognition, segmentation, and registration.</p> <p>As an example of criticality for middle level technical practice, in our paper <em><a href="https://arxiv.org/abs/2508.09293">Ethical Medical Image Synthesis</a></em>, we provide a critical reflection of the technical practice of the medical image synthesis task to make it more ethical and scientifically rigorous. The critical reflection focuses on the technical practice aspects of problem formation, model design assumption, model evaluation, and limitation analysis. This middle level critical reflection is based on our prior high level critical reflections in the <em><a href="https://arxiv.org/abs/2503.08720">AI for Just Work</a></em> paper.</p> <h3 id="low-level-technical-practice">Low level technical practice</h3> <p>Low level technical practice refers to the micro scope of the specific decisions and in technical conduct. Criticality in this level of technical practice concerns about, for example, whether the use of a common evaluation metrics is scientific rigor and responsible, the scientific flaws in a conventional formed practice. Examples of critical reflections of the low level technical practice can be:</p> <ul> <li>In the paper, <em><a href="https://www.nature.com/articles/s41592-023-02151-z">Metrics reloaded: recommendations for image analysis validation</a></em>, Maier-Hein et al. critically analyze the pros and cons of evaluation metrics for imaging tasks.</li> <li>The paper <em><a href="https://openreview.net/pdf?id=mPducS1MsEK">Are We Learning Yet? A Meta Review of Evaluation Failures Across Machine Learning</a></em> provides critique to the machine learning evaluation paradigm regarding internal and external validity.</li> <li>In my XAI plausibility case above, we conduct <a href="https://arxiv.org/abs/2303.17707">a critical examination of the plausibility metric for XAI algorithm evaluation and optimization</a>, and identify this evaluation practice as being unscientific and unethical.</li> </ul> <h2 id="the-anticipated-resistance">The anticipated resistance</h2> <p>The above different levels of approach hopefully can inspire you to think about how you can incorporate critical thinking and reflection into your current technical work to strengthen the technical immune system. In fact, I think medical image analysis is the ideal field to conduct critical technical practice, because the consequences of not conducting responsible and critical technical practice are huge. Despite the benefits of critical technical practice in the long run, currently, conducting critical technical practice is anticipated to receive many resistance and rejections, because the current technical culture priorities technical optimism (which emphasizes benefits and strengths of techniques) over scientific skepticism (which emphasizes weaknesses, limitations, flaws, and failure modes of techniques). Conducting critical technical practice may also put technical practitioners and researchers in a relatively vulnerable position. A well-known case is <a href="https://www.technologyreview.com/2020/12/04/1013294/google-ai-ethics-research-paper-forced-out-timnit-gebru/">Timnit Gebru got fired from Google</a>. That’s why we need collective efforts to support each other along the way. Knowing that resistance is normal in critical technical practice, we will be less likely to blame ourselves for failures and rejections. It also allows us to adjust expectations and shift our reward system from short-term external incentives, such as getting paper published, to long-term internal motivations, such as personal growth and the sense of feeling connected and supported towards a common goal.</p> <h2 id="actionable-ideas-for-critical-technical-practice">Actionable ideas for critical technical practice</h2> <p>If you feel motivated to conduct critical technical practice in your work, here are a few actionable ideas for you to consider:</p> <ul> <li>Do not easily let go of your doubts and skepticism during your work. Write them down and see if you can investigate them. Imagine yourself as a detective, and these doubts can be your initial clue to discover the hidden truth in technical work.</li> <li>From your skepticism, analyze its underlying assumptions and rationales for these assumptions, question the justifications, inspect the overall framing of the question, and identify the underlying philosophical worldviews and encoded values.</li> <li>Consider organizing a reading group or working group in your technical circle, to read more about related works on critical technical practice, discuss with peers, build your local critical technical practice community and support group, and see if you can collaboratively work something out to improve the scientific rigor, responsibility, and ethics of the technical work by understanding the root problems.</li> </ul>]]></content><author><name></name></author><category term="research"/><summary type="html"><![CDATA[Convolution is one of the most mysterious words for a novice deep learner. It is just a fancy operation of the weighted sum.]]></summary></entry><entry><title type="html">Nested cross validation explained</title><link href="https://weinajin.github.io/nested-cross-validation" rel="alternate" type="text/html" title="Nested cross validation explained"/><published>2018-08-25T17:00:00+00:00</published><updated>2018-08-25T17:00:00+00:00</updated><id>https://weinajin.github.io/nested-cross-validation</id><content type="html" xml:base="https://weinajin.github.io/nested-cross-validation"><![CDATA[<p>It is natural to come up with cross-validation (CV) when the dataset is relatively small. The basic idea of cross-validation is to train a new model on a subset of data, and validate the trained model on the remaining data. Repeat the process multiple times and average the validation error, we get an estimate of the generalization performance of the model. Since the test data is untouched during each training, we kind of use the whole dataset to estimate the generalization error, which will reduce the bias. However, since it will train multiple models instead of one, the drawback of CV is that quite computational expensive.</p> <p>It is necessary to make it clear that, the aim of CV is <strong>not to get one or multiple trained models for inference</strong>, but to <strong>estimate an unbiased generalization performance</strong>. This may be quite confusing at the beginning, since the outcome of the common train/validate/test split approach are a trained model with tuned hyperparameter (on train/validate set), plus a generalization estimation of performance (on trainval/test set).</p> <p>Why bother to have a validation set? Why not just use the test set for the two tasks of hyperparameter tuning(model selection) and estimation at once? The problem is, if we use the test set multiple times for different trained models, during our selection of the optimal model, the test set actually “leaks” information, and thus unpure. When we later apply the model to real-world data, the model will probably have a larger error than on the test set. That being said, when using the test set for both model selection and estimation, it tends to overfit the test data, and the estimation leads to an optimistic bias.</p> <p>(A side note: if we match the <code class="language-plaintext highlighter-rouge">test</code> set in above to the <code class="language-plaintext highlighter-rouge">test</code> set of many benchmark datasets, we will find the machine learning community is actually overfitting the benchmark. Since now we are using the results on the benchmark <code class="language-plaintext highlighter-rouge">test</code> dataset to select the best model, we are again mixing the model selection and performance estimation together by using the two tasks on the same benchmark <code class="language-plaintext highlighter-rouge">test</code> set.)</p> <p>When doing one round CV to evaluate the performance of different models, and select the best model based on the CV results, it is similar to the above case of using test set both for model selection and estimation. Thus, when we want to perform model selection and generalization error estimation, we have to separate the two tasks by using two test set for each task. That’s why we have the validation and test set, and the same version in CV is called nested or two-round cross validation.</p> <p>The nested CV has an inner loop CV nested in an outer CV. The inner loop is responsible for model selection/hyperparameter tuning (similar to validation set), while the outer loop is for error estimation (test set).</p> <div class="row mt-3"> <div class="col-sm mt-3 mt-md-0"> <figure> <picture> <source class="responsive-img-srcset" srcset="https://i.stack.imgur.com/vh1sZ-480.webp 480w,https://i.stack.imgur.com/vh1sZ-800.webp 800w,https://i.stack.imgur.com/vh1sZ-1400.webp 1400w," type="image/webp" sizes="95vw"/> <img src="https://i.stack.imgur.com/vh1sZ.png" class="img-fluid rounded z-depth-1" width="100%" height="auto" data-zoomable="" loading="lazy" onerror="this.onerror=null; document.querySelectorAll('.responsive-img-srcset').forEach(function (n) { n.remove(); });"/> </picture> </figure> </div> </div> <div class="caption"> Nested cross validation. <a>&lt;href = "https://stats.stackexchange.com/questions/292179/whats-the-meaning-of-nested-resampling" target="_blank"&gt;Image source: Cross Validated</a> </div> <p>The algorithm is as follows (adapted from Hastie et. al [1] and <a href="https://stats.stackexchange.com/questions/266225/step-by-step-explanation-of-k-fold-cross-validation-with-grid-search-to-optimise">this post</a>):</p> <p><strong>The nested cross validation</strong></p> <ol> <li> <p>Divide the dataset into \(K\) cross-validation folds at random.</p> </li> <li> <p>For each fold \(k=1,2,...,K\): <em>outer loop for evaluation of the model with selected hyperparameter</em></p> <p>2.1 Let <code class="language-plaintext highlighter-rouge">test</code> be fold \(k\)</p> <p>2.2 Let <code class="language-plaintext highlighter-rouge">trainval</code> be all the data except those in fold \(k\)</p> <p>2.3 Randomly split <code class="language-plaintext highlighter-rouge">trainval</code> into \(L\) folds</p> <p>2.4 For each fold \(l= 1,2,...L\): <em>inner loop for hyperparameter tuning</em></p> <p>2.4.1 Let <code class="language-plaintext highlighter-rouge">val</code> be fold \(l\)</p> <p>2.4.2 Let <code class="language-plaintext highlighter-rouge">train</code> be all the data except those in <code class="language-plaintext highlighter-rouge">test</code> or <code class="language-plaintext highlighter-rouge">val</code></p> <p>2.4.3 Train with each hyperparameter on <code class="language-plaintext highlighter-rouge">train</code>, and evaluate it on <code class="language-plaintext highlighter-rouge">val</code>. Keep track of the performance metrics</p> <p>2.5 For each hyperparameter setting, calculate the average metrics score over the \(L\) folds, and choose the best hyperparameter setting.</p> <p>2.6 Train a model with the best hyperparameter on <code class="language-plaintext highlighter-rouge">trainval</code>. Evaluate its performance on <code class="language-plaintext highlighter-rouge">test</code> and save the score for fold \(k\).</p> </li> <li> <p>Calculate the mean score over all \(K\) folds, and report as the generalization error.</p> </li> </ol> <p>As for the implementation, <a href="http://scikit-learn.org/stable/auto_examples/model_selection/plot_nested_cross_validation_iris.html">the scikit-learn documentation</a> points out: the inner loop can call scikit-learn’s <code class="language-plaintext highlighter-rouge">GridSearchCV</code> to achieve grid search of hyperparameter evaluated on the inner loop <code class="language-plaintext highlighter-rouge">val</code> set, and the outer loop can call <code class="language-plaintext highlighter-rouge">cross_val_score</code> for generalization error.</p> <h3 id="qa">Q&amp;A</h3> <ol> <li> <p>Can I apply the best hyperparameter selected in the first iteration of the outer fold, to build models for the remaining \(K-1\) outer loop? i.e. to save the search of the best hyperparameter in the next \(K-1 \times L \times M\) (where \(M\) is the number of hyperparameter combinations, if use grid search).</p> <p>I think the answer is no. The reason is that in this way, the <code class="language-plaintext highlighter-rouge">test</code> sets in the following loop are not “untouched” by the hyperparameter selection process. For example, in the outer loop # \(2\), the <code class="language-plaintext highlighter-rouge">test</code> set for evaluating the model performance was actually used in the outer loop # \(1\) for selecting the hyperparameter, then some data were used both for hyperparameter tuning and performance evaluation. This will cause overfitting.</p> </li> <li> <p>What if the \(K\) outer loop has distinct hyperparameter? How can I use the nested CV to build the best model?</p> <p>As I state in the beginning, CV is <strong>not a method to get one or multiple trained models for inference</strong>, but only a tool to <strong>estimate an unbiased generalization performance</strong>. CV will generate multiple models in each outer loop, but we can hardly estimate the performance of each individual model, since the number of the test set in each outer loop is small. However, if the model is stable (do not change much if the training data is perturbed), the hyperparameter found in each outer loop may be the same (using grid search) or similar to each other (using random search). A more in-depth explanation can be found <a href="https://stats.stackexchange.com/questions/65128/nested-cross-validation-for-model-selection">here</a>.</p> </li> </ol> <p>That’s all for what I would like to share of nested CV. This post reflects my current understanding of the cross validation. Please correct me if you identify any problems. Thanks!</p> <hr/> <h3 id="references">References</h3> <p>[1] T. Hastie, J. Friedman, and R. Tibshirani, “Model Assessment and Selection,” in The Elements of Statistical Learning: Data Mining, Inference, and Prediction, T. Hastie, J. Friedman, and R. Tibshirani, Eds. New York, NY: Springer New York, 2001, pp. 193–224.</p> <p>[2] G. C. Cawley and N. L. C. Talbot, “On Over-fitting in Model Selection and Subsequent Selection Bias in Performance Evaluation,” Journal of Machine Learning Research, vol. 11, no. Jul, pp. 2079–2107, 2010.</p>]]></content><author><name></name></author><category term="technical"/><summary type="html"><![CDATA[Using two-round cross validation for model selection and performance evaluation.]]></summary></entry><entry><title type="html">A friendly introduction to Convolutional in CNN</title><link href="https://weinajin.github.io/intro-conv" rel="alternate" type="text/html" title="A friendly introduction to Convolutional in CNN"/><published>2018-08-05T10:00:00+00:00</published><updated>2018-08-05T10:00:00+00:00</updated><id>https://weinajin.github.io/intro-conv</id><content type="html" xml:base="https://weinajin.github.io/intro-conv"><![CDATA[<p><a href="https://github.com/weinajin/ml_notes/blob/master/friendly_intro_to_convolution.ipynb">Notebook version</a></p> <h1 id="a-friendly-introduction-to-convolution-in-cnn">A friendly introduction to <em>convolution</em> in CNN</h1> <p>“Convolution” is one of the most mysterious words for a novice deep learner. The first time when I opened <a href="https://en.wikipedia.org/wiki/Convolution">wikipedia on convolution</a> and tried to make sense, I just got dizzy and lost. After a long time mingling with CNN and a bit with signal processing, I finally figure it out a little better. In my current understanding,</p> <h3 id="the-convolution-is-just-a-fancy-operation-of-the-weighted-sum">the convolution is just a fancy operation of the weighted sum.</h3> <p>And here is the whole story:</p> <h2 id="1-a-very-simple-version-of-weighted-sum">1. A very simple version of <em>weighted sum</em></h2> <p>To see what is a weighted sum, Let’s begin with the following expression, which may remind you of algebra in high school:</p> \[y = w_1 \times x_1 + w_2 \times x_2\] <p>Pretty easy, right? We give \(x_1\) and \(x_2\) different weights of \(w_1\) and \(w_2\), because in our mind, we value \(x_1\) and \(x_2\) differently. For example, if you want to calculate the final course score from the midterm and final exam, the weights reflect how important you think each exam is.</p> <p><strong>Weights reflect how important we think a variable is numerically</strong>, in a numerical perspective. Here, by injecting our thoughts, we are bringing in new perspectives into the original <em>flat</em> world (since the original weights are : \(w_1 = 1\), \(w_2 = 1\)).</p> <p>And <strong>sum is just an operation that condenses our deliberate thoughts on each variable into one final value</strong> (like the final course score).</p> <h2 id="2-the-weighted-sum-with-more-x">2. The <em>weighted sum</em> with more \(x\)</h2> <p>If we have more than two, say \(n\) number of \(x\), then the above formula can be written as:</p> \[y = w_1 \times x_1 + w_2 \times x_2 + w_3 \times x_3 + ... + w_n \times x_n\] <p>Or, a more condensed version:</p> \[y = \sum^n\_{i=1} w_i \times x_i\] <p>This works totally well when the number of \(x_i\) is small. But what if the number of \(x_i\) becomes large, say \(1,000,000\), or even infinite, how do we assign each \(x_i\) a weight wisely?</p> <p>Here is the trick:</p> <p>Instead of using a single number \(y\) to describe \(x\) sequence, now we use a group of numbers \(\vec{y}\). That’s because a single number compresses the information of \(x\) too much, so that it could not reflect its character very well.</p> <p>Now since we are dealing with a whole bunch of \(x\)s and \(y\)s, we will use \(\vec{x}\) and \(\vec{y}\) instead. Don’t be intimidated by the fancy new notation. They are called “vector”, which is merely a sequence of numbers grouped together.</p> <p>To generate a sequence of numbers \(\vec{y}\) out of \(\vec{x}\), there are some different approaches. Let’s explore one by one.</p> <h3 id="21-same-weight-for-all-x_i">2.1 Same weight for all \(x_i\)</h3> <p>The easiest approach is to assign a signal weight \(w\) to all \(x_i\). It is equal to \(\vec{y} = w \times \vec{x}\), where \(w\) is a single number.</p> <p>We will evaluate this approach from the following two aspects:</p> <table> <thead> <tr> <th style="text-align: left"> </th> <th style="text-align: left">Same weight for all \(x_i\)</th> </tr> </thead> <tbody> <tr> <td style="text-align: left">\(w\) is simple and compact</td> <td style="text-align: left">Yes</td> </tr> <tr> <td style="text-align: left">\(w\) adds information on how we value different value in \(\vec{x}\)</td> <td style="text-align: left">No</td> </tr> </tbody> </table> <p>\(w\) is quite simple: it is just a number. However, it adds little information from “our perspective”. It only scales the original \(\vec{x}\), and could not differentiate the fine details inside \(\vec{x}\).</p> <p>Here is an example:</p> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">import</span> <span class="n">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">sin</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="o">*</span> <span class="n">np</span><span class="p">.</span><span class="n">pi</span><span class="p">,</span> <span class="mi">2</span><span class="o">*</span><span class="n">np</span><span class="p">.</span><span class="n">pi</span><span class="p">,</span> <span class="mi">200</span><span class="p">))</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">ylim</span><span class="p">(</span><span class="o">-</span><span class="mf">2.5</span><span class="p">,</span> <span class="mf">2.5</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">xlabel</span><span class="p">(</span><span class="sh">"</span><span class="s">The sequence of x</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">ylabel</span><span class="p">(</span><span class="sh">"</span><span class="s">The value of x</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">show</span><span class="p">()</span>
</code></pre></div></div> <p><img src="/images/friendly_intro_to_convolution_files/friendly_intro_to_convolution_1_0.png" alt="png"/></p> <p>We draw \(\vec{x}\) as a sequence of numbers. Now if we multiply each \(x_i\) with a weight, say \(2\), then the output \(\vec{y}\) will look like this:</p> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="c1">#plt.plot(2*np.ones(x.shape))
</span><span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">x</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">convolve</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">ylim</span><span class="p">(</span><span class="o">-</span><span class="mf">2.5</span><span class="p">,</span> <span class="mf">2.5</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">legend</span><span class="p">([</span><span class="sh">'</span><span class="s">x</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">w * x</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">convolve with 2</span><span class="sh">'</span><span class="p">],</span> <span class="n">bbox_to_anchor</span><span class="o">=</span><span class="p">(</span><span class="mf">1.05</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">loc</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">xlabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Sequence</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">ylabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Value</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">show</span><span class="p">()</span>
</code></pre></div></div> <p><img src="/images/friendly_intro_to_convolution_files/friendly_intro_to_convolution_3_0.png" alt="png"/></p> <p>As you can see, the green line \(\vec{y}\) has exactly the same “pattern”, i.e.: it has peaks and valleys in the same position as in \(\vec{x}\). It stretched \(\vec{x}\) but that’s it.</p> <p>You may notice I actually draw 3 lines. The graph only shows two lines because the lines of “multiply by 2” and “convolve with 2” are overlapped. I’ll talk about it later. But now you see we begin to touch <em>convolution</em> a little bit after a long reading!</p> <h3 id="22-distinct-weight-for-each-x_i">2.2 Distinct weight for each \(x_i\)</h3> <p>Another extreme is to assign each \(x_i\) with a distinct weight. For every resulting point \(y_i\), it is the product of \(w_i\) and \(x_i\).</p> \[y_i = w_i \times x_i\] <p>Now \(\vec{w}\) becomes a sequence of numbers with the same length as \(\vec{x}\). The weight \(\vec{w}\) reflects our thoughts on each \(x_i\) in much finer details. This is similar to what we do in the first example of calculating the final score of a course, but here we didn’t apply the summation.</p> <p>To take another example, here we assign the weight as a sequence of numbers on a straight line, as the orange line shown in the picture. When we multiply each \(w_i\) with \(x_i\), we get the resulting \(\vec{y}\) as the green line. Even with a very simple form of \(\vec{w}\), the resulting \(\vec{y}\) can do a very good job in incorporating the information from both \(\vec{w}\) and \(\vec{x}\).</p> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">sin</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">20</span><span class="o">*</span><span class="n">np</span><span class="p">.</span><span class="n">pi</span><span class="p">,</span> <span class="mi">400</span><span class="p">))</span>
<span class="n">w</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">arange</span><span class="p">(</span><span class="mi">400</span><span class="p">)</span><span class="o">/</span><span class="mi">400</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="n">w</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">multiply</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">w</span><span class="p">))</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">legend</span><span class="p">([</span><span class="sh">'</span><span class="s">x</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">w</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">y</span><span class="sh">'</span><span class="p">],</span> <span class="n">bbox_to_anchor</span><span class="o">=</span><span class="p">(</span><span class="mf">1.05</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">loc</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">xlabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Sequence</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">ylabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Value</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">show</span><span class="p">()</span>
</code></pre></div></div> <p><img src="/images/friendly_intro_to_convolution_files/friendly_intro_to_convolution_6_0.png" alt="png"/></p> <p>This approach has some real-world applications, such as <a href="https://en.wikipedia.org/wiki/Amplitude_modulation">Amplitude modulation</a>. Depending on the specific problems, if we want to apply this approach to identifying peaks and valleys, it will become unpractical, since we will need to deliberately design all the weight sequence according to all the domain of \(\vec{x}\). It is also redundant and costly to express and store \(\vec{w}\).</p> <table> <thead> <tr> <th style="text-align: left"> </th> <th style="text-align: center">Same weight for all \(x_i\)</th> <th style="text-align: center">Distinct weight for each \(x_i\)</th> </tr> </thead> <tbody> <tr> <td style="text-align: left">\(w\) is simple and compact</td> <td style="text-align: center">Yes</td> <td style="text-align: center">No</td> </tr> <tr> <td style="text-align: left">\(w\) adds information on how we value different value in \(\vec{x}\)</td> <td style="text-align: center">No</td> <td style="text-align: center">Yes</td> </tr> </tbody> </table> <h3 id="23-repetitive-weight">2.3 Repetitive weight</h3> <p>An improvement to the above approach, is to express \(\vec{w}\) in a repetitive manner, i.e.: to repeat a short sequence \(\vec{w}\) over \(\vec{x}\).</p> <p>In this way, the \(\vec{w}\) is expressed by a short sequence of numbers, meanwhile still carry out our thoughts over the raw data \(\vec{x}\).</p> <table> <thead> <tr> <th style="text-align: left"> </th> <th style="text-align: center">Same weight for all \(x_i\)</th> <th style="text-align: center">Distinct weight for each \(x_i\)</th> <th style="text-align: center">Repetitive weight</th> </tr> </thead> <tbody> <tr> <td style="text-align: left">\(w\) is simple and compact</td> <td style="text-align: center">Yes</td> <td style="text-align: center">No</td> <td style="text-align: center">Yes</td> </tr> <tr> <td style="text-align: left">\(w\) adds information on how we value different value in \(\vec{x}\)</td> <td style="text-align: center">No</td> <td style="text-align: center">Yes</td> <td style="text-align: center">Yes</td> </tr> </tbody> </table> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">n</span> <span class="o">=</span> <span class="mi">50</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">sin</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">20</span><span class="o">*</span><span class="n">np</span><span class="p">.</span><span class="n">pi</span><span class="p">,</span> <span class="mi">400</span><span class="p">))</span>
<span class="n">w</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">tile</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">concatenate</span><span class="p">((</span><span class="n">np</span><span class="p">.</span><span class="nf">arange</span><span class="p">(</span><span class="n">n</span><span class="p">),</span> <span class="n">np</span><span class="p">.</span><span class="nf">flip</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">arange</span><span class="p">(</span><span class="n">n</span><span class="p">),</span> <span class="n">axis</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)),</span> <span class="n">axis</span> <span class="o">=</span> <span class="mi">0</span><span class="p">),</span> <span class="nf">int</span><span class="p">(</span><span class="mi">200</span><span class="o">/</span><span class="n">n</span><span class="p">))</span><span class="o">/</span><span class="n">n</span><span class="o">/</span><span class="mi">2</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="n">w</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">plot</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">multiply</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">w</span><span class="p">))</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">legend</span><span class="p">([</span><span class="sh">'</span><span class="s">x</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">w</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">y</span><span class="sh">'</span><span class="p">],</span> <span class="n">bbox_to_anchor</span><span class="o">=</span><span class="p">(</span><span class="mf">1.05</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">loc</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">xlabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Sequence</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">ylabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Value</span><span class="sh">"</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="nf">show</span><span class="p">()</span>
</code></pre></div></div> <p><img src="/images/friendly_intro_to_convolution_files/friendly_intro_to_convolution_9_0.png" alt="png"/></p> <p>In this example, we repeat \(\vec{w}\) four times. We notice that \(\vec{y}\) (in green) has the largest peaks when the peaks of \(\vec{w}\) overlap with the one of \(\vec{x}\).</p> <p>However, in the above example, I set the length of \(\vec{w}\) deliberately to match the shape of \(\vec{x}\). Thus the interesting pattern of the \(\vec{w}\) can only fall on the specific segment of \(\vec{x}\). The real-world data are way more complex than the sinusoid. How to make \(\vec{w}\) cover the whole sequence of \(\vec{x}\) without missing any potential interesting combination of \(w \times x\)?</p> <h3 id="24-repetitive-weight-with-smaller-stepsize">2.4 Repetitive weight with smaller stepsize</h3> <p>The problem with the previous approach is that its step size is too large. It equals the length of \(\vec{w}\). We can solve the problem by shortening the stepsize. Let’s push the stepsize to another extreme, say \(1\) in case that \(x\) is discrete.</p> <p>Concretely, we iteratively use each number in \(\vec{w}\) as the start point, and periodically repeat \(\vec{w}\) to get the same length as \(\vec{x}\), then we multiply the two sequence element-wise.</p> <p>Wait a minute, in this way, since we repeat the process many times, we will get many \(\vec{y}\), how do we summarize the multiplied information.</p> <p>So far, we only discussed different scenarios of the <strong>weight</strong>, we still didn’t talk much about the <strong>sum</strong>. Now it’s time to let the <strong>sum</strong> shine!</p> <p>I thought about adding all the resulting \(\vec{y}\) element-wise, but then I realized the result equals to add all the elements of \(\vec{w}\) together, then multiply the number with \(\vec{x}\). It becomes the case in Section 2.1, which destroyed the information we extracted by shifting the start point of \(\vec{w}\).</p> <p>The real trick of <strong>convolution</strong> is:</p> <p>we <strong>sum</strong> over the sequence of \(\vec{w}\), right after multiplying \(\vec{w}\) with the corresponding \(x\) segment.</p> <p>The resulting output from the sum will be a single number \(y_n\):</p> \[y*n = \sum*{i=0}^{|w|} w*i \times x*{n + i}\] <p>where \(n\) is the start position of \(\vec{w}\) on \(\vec{x}\).</p> <p>After calculating all the \(y_n\) along the sequence of \(\vec{x}\), we just complete the convolution operation.</p> \[y(n) = (x \* w)(n) = \sum*{i=0}^{|w|} w_i \times x*{n + i}\] <p>where the \(\*\) symbol denotes the convolution operation, and \(y\) is denoted as a function of the sequence \(n\).</p> <p>Remember in the beginning, I mentioned <strong>sum is an operation that condenses our deliberate thoughts on each variable into one final value</strong>. Instead of summing over the whole sequence as above, the convolution sum over the area covered by the weight size. In this way, the sum operation won’t lose much information, and concisely represents the combined information from \(w\) and \(x\) patch. Moreover, since the weighted sum is actually the dot product of \(w\) and the local \(x\) patch, it is a similarity measure of the two, where a larger weighted sum represents a detected pattern on \(\vec{x}\) that corresponding to the pattern of \(\vec{w}\). Thus, we can design weights with the patterns we want and use them to detect if similar patterns exist on the target data \(\vec{x}\).</p> <p>The formula is similar to the one in <a href="https://en.wikipedia.org/wiki/Convolution#Discrete_convolution">Discrete convolution in Wikipedia</a>. Except for that in the wikipedia’s formula, it is \(x_{n - i}\) instead of \(x_{n + i}\). The minus sign used to confused me a lot, until I found out when we talk about <strong>convolution</strong> in CNN, we actually talk about <strong>cross-correlation</strong>, where it uses \(x_{n + i}\). The <strong>convolution</strong> in math uses \(x_{n - i}\), where the weight is flipped. The difference only matters when writing proofs, but as regarded to CNN implementation, people just use \(x_{n + i}\) and call it <strong>convolution</strong>. (<a href="https://www.deeplearningbook.org/contents/convnets.html">Ref: Deep Learning book p. 324</a>)</p> <p>That’s almost the whole story of <strong>convolution</strong>.</p> <p>But what does it to do with convolution and image, you may ask. The above story tells us how to calculate convolution with 1-dimensional data. The convolution in CNN for images is calculated exactly in the same way, we just extend the data and weights to 2 dimensions.</p> \[Y(m, n) = (X \* W)(m, n) = \sum*{i} \sum*{j} W*{i , j} \times X*{m + i, n + j}\] <p>That’s it!</p> <p>The convolution is really a smart, simple and powerful operation. It uses a small size of weight, which is easy to express. I’d like to think the weight as a searchlight that focuses on one small patch of \(X\) at a time. While the “light” shines on one image patch, it synthesizes the information of the image data with our values on different spatial location, by using the <strong>weighted sum</strong> operation. The convolved output is a group of such <strong>weighted sum</strong> aligned with the shape of input data \(X\). This is my intuition on the strength of convolution. More advantages of convolution include <strong>sparse interactions</strong>, <strong>parameter sharing</strong>, and <strong>equivariant representations</strong>. These contents are described in much details in <a href="https://www.deeplearningbook.org/contents/convnets.html">Ch 9.2 of Deep Learning book</a>.</p> <p>My next notebook will introduce the implementation and a variety of convolutions in CNN. See you later!</p> <hr/> <p>This article reflects my current understanding of <em>convolution</em> in CNN. Please let me know if you identified any errors or have any questions: <a href="https://twitter.com/weina_jin">@weina_jin</a> or by <a href="https://github.com/weinajin/ml_notes/issues/new">creating an issue</a>. Thanks for your reading 😎</p>]]></content><author><name></name></author><category term="technical"/><summary type="html"><![CDATA[Convolution is one of the most mysterious words for a novice deep learner. It is just a fancy operation of the weighted sum.]]></summary></entry></feed>