<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lawson Dong</title>
    <description>The latest articles on DEV Community by Lawson Dong (@lawson_dong).</description>
    <link>https://dev.to/lawson_dong</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4176324%2F95ff2a68-bdb3-464c-a7fa-297056859771.jpg</url>
      <title>DEV Community: Lawson Dong</title>
      <link>https://dev.to/lawson_dong</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lawson_dong"/>
    <language>en</language>
    <item>
      <title>Managing My First AI Experiment: Checkpoints, Logs, and Python Virtual Environments</title>
      <dc:creator>Lawson Dong</dc:creator>
      <pubDate>Sun, 11 Oct 2026 20:46:07 +0000</pubDate>
      <link>https://dev.to/lawson_dong/managing-my-first-ai-experiment-checkpoints-logs-and-python-virtual-environments-2fk</link>
      <guid>https://dev.to/lawson_dong/managing-my-first-ai-experiment-checkpoints-logs-and-python-virtual-environments-2fk</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/lawson_dong/training-my-first-neural-network-on-windows-with-wsl-2-and-pytorch-3him"&gt;previous note&lt;/a&gt;, I set up Ubuntu with WSL 2, created a Python virtual environment, trained a small XOR neural network with PyTorch, and saved its parameters.&lt;/p&gt;

&lt;p&gt;This time, I wanted to make that experiment easier to manage: organize the model files, save the training output, and understand what actually changes when I activate a virtual environment.&lt;/p&gt;

&lt;p&gt;This is a hands-on continuation using the same project, &lt;code&gt;~/research/first-neural-network&lt;/code&gt;. You will need the existing &lt;code&gt;train.py&lt;/code&gt;, &lt;code&gt;.venv&lt;/code&gt;, and &lt;code&gt;xor_model.pth&lt;/code&gt; from the previous tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Open Ubuntu and return to the project
&lt;/h2&gt;

&lt;p&gt;Start a new Windows Command Prompt. It may initially look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8r5hycxalam2h5twmj4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8r5hycxalam2h5twmj4y.png" alt="A new Windows Command Prompt" width="217" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wsl &lt;span class="nt"&gt;-d&lt;/span&gt; Ubuntu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prompt now belongs to Ubuntu:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0mwytxtmhp3um1qlxgsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0mwytxtmhp3um1qlxgsp.png" alt="Ubuntu shell after entering WSL" width="407" height="37"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that WSL may initially open in a mounted Windows directory, such as &lt;code&gt;/mnt/c/Users/linxi&lt;/code&gt;. Navigate to the Linux project explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/research/first-neural-network
&lt;span class="nb"&gt;pwd
ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cd&lt;/code&gt; changes the current working directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pwd&lt;/code&gt; prints its absolute path.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ls -la&lt;/code&gt; lists the directory contents in detail, including hidden entries such as &lt;code&gt;.venv&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcslgx7ng2uui4hupsh8l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcslgx7ng2uui4hupsh8l.png" alt="Project directory containing the virtual environment, training script, and saved model" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Organize the model files
&lt;/h2&gt;

&lt;p&gt;I wanted to separate the Python environment, model parameters, and training logs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7ymos0g5aiq5i9e1dvf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7ymos0g5aiq5i9e1dvf6.png" alt="The project organized into a training script, Python environment, checkpoints, and logs" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create two directories and copy the existing model file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; checkpoints logs      &lt;span class="c"&gt;# Create both directories if they do not exist&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;xor_model.pth checkpoints/  &lt;span class="c"&gt;# Copy the saved parameters into checkpoints/&lt;/span&gt;
&lt;span class="nb"&gt;ls &lt;/span&gt;checkpoints                &lt;span class="c"&gt;# List the files in checkpoints/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvr6y5kaboypslf5707jr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvr6y5kaboypslf5707jr.png" alt="The copied xor_model.pth file listed inside checkpoints" width="800" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seeing &lt;code&gt;xor_model.pth&lt;/code&gt; in the output confirms that the file is present in &lt;code&gt;checkpoints/&lt;/code&gt;. In this project, it stores the trained model's parameters, including weights and biases, saved by PyTorch. The &lt;code&gt;.pth&lt;/code&gt; extension alone does not tell us what every PyTorch file contains; that depends on what the training script saved.&lt;/p&gt;

&lt;p&gt;Because I used &lt;code&gt;cp&lt;/code&gt;, the original file is still in the project root:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0z1p9np3cdiibtflz6gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0z1p9np3cdiibtflz6gy.png" alt="The original model file and its separate copy in checkpoints" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are two separate files. If &lt;code&gt;train.py&lt;/code&gt; saves a new &lt;code&gt;xor_model.pth&lt;/code&gt; in the project root later, the copy in &lt;code&gt;checkpoints/&lt;/code&gt; will not update automatically. For now, that copy is a snapshot of the earlier run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspect the file sizes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-lh&lt;/span&gt; xor_model.pth checkpoints/xor_model.pth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can write &lt;code&gt;-lh&lt;/code&gt; as &lt;code&gt;-l -h&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-l&lt;/code&gt; uses the long listing format, showing permissions, owner, size, modification time, and filename.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-h&lt;/code&gt; displays sizes in human-readable units, such as K, M, and G.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frwi8swogcyhbleznmz8i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frwi8swogcyhbleznmz8i.png" alt="Explanation of ls, the long-listing option, and human-readable file sizes" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The size is one field in a longer line of file information:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fabsd108zb12up6nz64dp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fabsd108zb12up6nz64dp.png" alt="How to find a model file's size in an ls long listing" width="800" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are the two files side by side:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvqttjfaj9mza2aa5ajfd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvqttjfaj9mza2aa5ajfd.png" alt="The original and copied model files have the same displayed size" width="800" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Matching displayed sizes are a useful quick check, although they do not prove that two files have identical contents.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Activate the Python environment
&lt;/h2&gt;

&lt;p&gt;Before running the training script, activate the project's existing environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;source&lt;/code&gt; executes the activation script in the current shell. Activation puts &lt;code&gt;.venv/bin&lt;/code&gt; at the beginning of the shell's &lt;code&gt;PATH&lt;/code&gt;, so commands such as &lt;code&gt;python&lt;/code&gt; and &lt;code&gt;pip&lt;/code&gt; use the project's environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmqq81u2s6mo1cqse9gn2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmqq81u2s6mo1cqse9gn2.png" alt="The structure and meaning of source .venv/bin/activate" width="799" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install NumPy if the project needs it
&lt;/h3&gt;

&lt;p&gt;NumPy is a Python package, not a separate environment. To install it into this virtual environment and check its version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;numpy
python &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import numpy; print(numpy.__version__)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The version attribute is &lt;code&gt;__version__&lt;/code&gt;, with &lt;strong&gt;two underscores on each side&lt;/strong&gt;. Using &lt;code&gt;python -m pip&lt;/code&gt; runs pip with the same Python interpreter selected by &lt;code&gt;python&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Installing NumPy may resolve a missing-NumPy warning from PyTorch, but &lt;strong&gt;NumPy is not required to read a text log&lt;/strong&gt;. We will use Linux commands for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Save the training output to a log
&lt;/h2&gt;

&lt;p&gt;Run the training script and capture its output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python train.py &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; logs/training.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6o5ttza3pc3b7y7xrm2q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6o5ttza3pc3b7y7xrm2q.png" alt="The training command broken into Python, script, output redirection, and error redirection" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two main output streams:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Standard output (&lt;code&gt;stdout&lt;/code&gt;, descriptor &lt;code&gt;1&lt;/code&gt;)&lt;/strong&gt;: ordinary output, such as printed epoch numbers and losses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standard error (&lt;code&gt;stderr&lt;/code&gt;, descriptor &lt;code&gt;2&lt;/code&gt;)&lt;/strong&gt;: errors, warnings, and other diagnostic output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&amp;gt; logs/training.log&lt;/code&gt; sends standard output to the file. Then &lt;code&gt;2&amp;gt;&amp;amp;1&lt;/code&gt; sends standard error to the same destination as standard output. The order matters: redirect standard output first, then make standard error follow it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7h69c3hb29sm3tnnyyxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7h69c3hb29sm3tnnyyxg.png" alt="How stdout and stderr are captured with and without 2 greater-than ampersand 1" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The terminal may appear quiet while training runs because the output is going into the file. The command returns to the shell prompt when the script finishes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Each run with &lt;code&gt;&amp;gt;&lt;/code&gt; overwrites the existing log.&lt;/strong&gt; To append instead, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python train.py &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; logs/training.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A log records what the program writes; it does not automatically save the trained model. Model saving still depends on the code in &lt;code&gt;train.py&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Read and monitor the training log
&lt;/h2&gt;

&lt;p&gt;After training finishes, display the log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;logs/training.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;cat&lt;/code&gt; is short for &lt;em&gt;concatenate&lt;/em&gt;. It can combine files, and when given a single file, it prints that file's contents directly in the terminal.&lt;/p&gt;

&lt;p&gt;For longer logs, these commands are useful:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgcw1hxvctambiftcs88w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgcw1hxvctambiftcs88w.png" alt="Commands for displaying, browsing, and monitoring text files" width="800" height="295"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;head &lt;/span&gt;logs/training.log       &lt;span class="c"&gt;# Show the first 10 lines&lt;/span&gt;
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 5 logs/training.log &lt;span class="c"&gt;# Show the last 5 lines&lt;/span&gt;
less logs/training.log       &lt;span class="c"&gt;# Browse the file interactively; press q to quit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a screenshot from my session, showing a NumPy installation followed by the training log:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqhh8iup6rab93vscx101.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqhh8iup6rab93vscx101.png" alt="Installing NumPy and displaying the recorded training output" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Installing a package after a run does not change a warning already recorded in that run's log. To capture a new run with the updated environment, run the training command again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow a longer training run
&lt;/h3&gt;

&lt;p&gt;For a long experiment, use a second terminal to watch new log lines arrive.&lt;/p&gt;

&lt;p&gt;In the first terminal, start training with unbuffered Python output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/research/first-neural-network
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
python &lt;span class="nt"&gt;-u&lt;/span&gt; train.py &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; logs/training.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-u&lt;/code&gt; makes Python's output unbuffered, which helps printed progress appear promptly in a redirected log.&lt;/p&gt;

&lt;p&gt;In a second Windows Command Prompt, enter Ubuntu and follow the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wsl &lt;span class="nt"&gt;-d&lt;/span&gt; Ubuntu
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/research/first-neural-network
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; logs/training.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tail -f&lt;/code&gt; displays the last 10 lines and continues showing newly appended content. Press &lt;strong&gt;Ctrl+C in the monitoring terminal&lt;/strong&gt; to stop following the log; training in the first terminal continues.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Understand the virtual environment and the file system
&lt;/h2&gt;

&lt;p&gt;A Python virtual environment gives a project its own installed packages and access to a Python interpreter through the environment's executables. In this project, &lt;code&gt;.venv&lt;/code&gt; is simply a directory inside &lt;code&gt;first-neural-network&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The important paths are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.venv/bin/python&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Python interpreter executable, which may be a copy or symbolic link&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.venv/bin/pip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Python package installer entry point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.venv/bin/activate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shell script used to activate the environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.venv/lib/pythonX.Y/site-packages/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Installed Python packages; &lt;code&gt;X.Y&lt;/code&gt; depends on the Python version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;train.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Neural network training script&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;xor_model.pth&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Model parameter file originally saved in the project root&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;checkpoints/xor_model.pth&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Separate copy of that parameter file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;logs/training.log&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Recorded training output&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Activating &lt;code&gt;.venv&lt;/code&gt; does not change your working directory or prevent Python and the shell from accessing the rest of the project. It is not a separate Linux file system or a file-access sandbox.&lt;/p&gt;

&lt;h3&gt;
  
  
  Experiment: check what activation changes
&lt;/h3&gt;

&lt;p&gt;Start with a fresh Ubuntu shell, or run &lt;code&gt;deactivate&lt;/code&gt; first if the environment is already active. Then execute this block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Step 1: Navigate to the project directory&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/research/first-neural-network

&lt;span class="c"&gt;# Step 2: Check the current directory and Python executable&lt;/span&gt;
&lt;span class="nb"&gt;pwd
&lt;/span&gt;which python3

&lt;span class="c"&gt;# Step 3: Activate the virtual environment&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate

&lt;span class="c"&gt;# Step 4: Check the directory, Python executable, and model file again&lt;/span&gt;
&lt;span class="nb"&gt;pwd
&lt;/span&gt;which python
&lt;span class="nb"&gt;ls &lt;/span&gt;xor_model.pth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp850a9yft40l68dbv0y5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp850a9yft40l68dbv0y5.png" alt="Before and after activation: unchanged working directory, a different Python executable path, and an accessible model file" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pwd&lt;/code&gt; prints the same path before and after activation, showing that the current working directory has not changed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;which python&lt;/code&gt; now points to the executable inside the project's &lt;code&gt;.venv/bin/&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ls xor_model.pth&lt;/code&gt; still finds the model file in the project root.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; Activating a Python virtual environment changes which Python executable and project packages are used. It does not create a separate Linux file system or change the current working directory.&lt;/p&gt;

&lt;p&gt;To exit the environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deactivate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project files and saved logs remain where they were.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/lawson_dong/training-my-first-neural-network-on-windows-with-wsl-2-and-pytorch-3him"&gt;Previous tutorial: Training My First Neural Network on Windows with WSL 2 and PyTorch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/venv.html" rel="noopener noreferrer"&gt;Python documentation: venv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/software/bash/manual/html_node/Redirections.html" rel="noopener noreferrer"&gt;Bash manual: redirections&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>python</category>
    </item>
    <item>
      <title>Training My First Neural Network on Windows with WSL 2 and PyTorch</title>
      <dc:creator>Lawson Dong</dc:creator>
      <pubDate>Sun, 11 Oct 2026 05:13:48 +0000</pubDate>
      <link>https://dev.to/lawson_dong/training-my-first-neural-network-on-windows-with-wsl-2-and-pytorch-3him</link>
      <guid>https://dev.to/lawson_dong/training-my-first-neural-network-on-windows-with-wsl-2-and-pytorch-3him</guid>
      <description>&lt;p&gt;As a physics undergraduate beginning to explore AI research, I wanted to understand the practical workflow behind a neural network experiment: where the code lives, how the environment works, how to run training, and what gets saved afterward.&lt;/p&gt;

&lt;p&gt;This tutorial brings together my setup notes and first PyTorch experiment. We will build a small network for XOR, starting from a Windows computer and ending with a saved model file. The focus is on getting the workflow running; the mathematics can come later.&lt;/p&gt;

&lt;p&gt;You need a supported Windows 10 or Windows 11 installation, permission to install WSL, and an internet connection. A GPU is unnecessary for this four-example experiment.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understand the tools before installing them
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhpjlx151lcdwboigdwj6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhpjlx151lcdwboigdwj6.png" alt="Overview of the local Windows-to-PyTorch training workflow" width="800" height="822"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The workflow is &lt;strong&gt;Windows terminal → WSL 2 → Ubuntu → project folder → Python virtual environment → PyTorch → training results&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Role in this experiment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CMD / PowerShell&lt;/td&gt;
&lt;td&gt;Launches WSL from Windows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WSL 2&lt;/td&gt;
&lt;td&gt;Runs a Linux kernel using lightweight virtualization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ubuntu&lt;/td&gt;
&lt;td&gt;Provides the Linux operating environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;APT&lt;/td&gt;
&lt;td&gt;Installs Ubuntu system packages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Executes our training script&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;venv&lt;/td&gt;
&lt;td&gt;Isolates the project's Python dependencies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pip&lt;/td&gt;
&lt;td&gt;Installs packages inside that environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PyTorch&lt;/td&gt;
&lt;td&gt;Provides tensors, neural network layers, and automatic differentiation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Docker is an optional next step for packaging environments. Ordinary Ubuntu and PyTorch development works without Docker Desktop running.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Install and launch Ubuntu
&lt;/h2&gt;

&lt;p&gt;Run these commands in &lt;strong&gt;Windows CMD or PowerShell&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On my machine, the only listed distribution was initially &lt;code&gt;docker-desktop&lt;/code&gt;. That did not mean I already had an Ubuntu development environment.&lt;/p&gt;

&lt;p&gt;To install Ubuntu, open &lt;strong&gt;PowerShell as administrator&lt;/strong&gt; and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart Windows if prompted. On Ubuntu's first launch, create a Linux username and password. The password input displays no characters or asterisks.&lt;/p&gt;

&lt;p&gt;Check the installation from Windows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm that Ubuntu is listed with &lt;code&gt;VERSION 2&lt;/code&gt;. If it uses version 1, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--set-version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optionally make Ubuntu the default, then launch it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--set-default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For installation requirements and troubleshooting, see &lt;a href="https://learn.microsoft.com/en-us/windows/wsl/install" rel="noopener noreferrer"&gt;Microsoft's WSL installation guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Find your Linux home directory
&lt;/h2&gt;

&lt;p&gt;From this point onward, commands run &lt;strong&gt;inside Ubuntu&lt;/strong&gt;, unless explicitly labeled otherwise.&lt;/p&gt;

&lt;p&gt;A terminal prompt might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lawson@computer:~$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;lawson&lt;/code&gt; is the Linux username, &lt;code&gt;computer&lt;/code&gt; is the hostname, and &lt;code&gt;~&lt;/code&gt; means the user's home directory. Do not copy the prompt itself when running commands.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6q7twc92s5mkk2rzzlzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6q7twc92s5mkk2rzzlzv.png" alt="Linux file system structure, including the user's home directory" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your Linux home directory is typically &lt;code&gt;/home/&amp;lt;username&amp;gt;&lt;/code&gt;. Windows drives are accessible through paths such as &lt;code&gt;/mnt/c/&lt;/code&gt;. For this experiment, keep the project in your Linux home directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;span class="nb"&gt;pwd
ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pwd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prints the current working directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ls&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lists directory contents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Changes directories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mkdir&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates directories&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;touch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates an empty file or updates its timestamps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Displays or combines file contents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sudo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Runs a command as another user, usually root&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Install system tools with APT
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F43wvb6fd7mimnv36k7el.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F43wvb6fd7mimnv36k7el.png" alt="APT installs system packages from Ubuntu software repositories" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;APT manages Ubuntu packages. Refresh its package information and install the tools we need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; git python3 python3-pip python3-venv nano
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;--version&lt;/span&gt;
git &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;APT handles system software; pip handles Python packages. In the following steps, pip installs packages into our project environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Create a project and virtual environment
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; research/first-neural-network
&lt;span class="nb"&gt;cd &lt;/span&gt;research/first-neural-network
&lt;span class="nb"&gt;pwd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The path should end with &lt;code&gt;research/first-neural-network&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4sk69gnj5psoowcph7pk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4sk69gnj5psoowcph7pk.png" alt="Separate virtual environments let projects use different PyTorch versions" width="800" height="709"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagram's version numbers are examples: each project can manage its own dependencies independently.&lt;/p&gt;

&lt;p&gt;Create and activate the environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your prompt should now begin with &lt;code&gt;(.venv)&lt;/code&gt;. Closing the terminal leaves this directory on disk; you will reactivate it in the next session.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Install and verify PyTorch
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;.venv&lt;/code&gt; active, install a CPU build of PyTorch and NumPy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip
python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;torch &lt;span class="nt"&gt;--index-url&lt;/span&gt; https://download.pytorch.org/whl/cpu
python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;numpy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check &lt;a href="https://pytorch.org/get-started/locally/" rel="noopener noreferrer"&gt;PyTorch's official installation selector&lt;/a&gt; for supported Python versions or a GPU-specific installation command.&lt;/p&gt;

&lt;p&gt;Verify the installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import torch, numpy; print('PyTorch:', torch.__version__); print('NumPy:', numpy.__version__)"&lt;/span&gt;
python &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import torch; print(torch.rand(2, 2))"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second command should print a random 2 × 2 tensor. In my original setup, tensor creation worked but PyTorch warned that NumPy was missing. Installing NumPy resolved that missing dependency.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Write the training script
&lt;/h2&gt;

&lt;p&gt;Our task is XOR: output &lt;code&gt;1&lt;/code&gt; when the two inputs differ and &lt;code&gt;0&lt;/code&gt; when they match.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[0, 0]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[0, 1]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[1, 0]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[1, 1]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Open a new file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano train.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.nn&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;

&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;manual_seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Training data
&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="c1"&gt;# 2. A small network: two inputs, four hidden units, one output
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Tanh&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 3. Loss and optimizer
&lt;/span&gt;&lt;span class="n"&gt;criterion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BCEWithLogitsLoss&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;optimizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;optim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Adam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;lr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 4. Training
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;train&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;epoch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2001&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;optimizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zero_grad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;logits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;criterion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;optimizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;epoch&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Epoch &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;epoch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Loss: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 5. Inspect predictions on the four training examples
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_grad&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;probabilities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sigmoid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;predicted_labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probabilities&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Probabilities:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probabilities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Predicted labels:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predicted_labels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 6. Save learned parameters
&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;state_dict&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xor_model.pth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Saved weights to xor_model.pth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save with &lt;strong&gt;Ctrl + O&lt;/strong&gt;, press &lt;strong&gt;Enter&lt;/strong&gt;, and exit with &lt;strong&gt;Ctrl + X&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The loop computes predictions, measures the error, computes gradients, and updates parameters. &lt;code&gt;BCEWithLogitsLoss&lt;/code&gt; takes the network's raw output, so the sigmoid is applied when inspecting probabilities afterward.&lt;/p&gt;

&lt;p&gt;This is a small network with one hidden layer. It is a first neural network training exercise, rather than a large-scale deep learning experiment.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Run training and inspect the result
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python train.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One mistake I made was trying &lt;code&gt;torch train.py&lt;/code&gt;. PyTorch is a Python library; Python executes the file.&lt;/p&gt;

&lt;p&gt;You should see periodic loss reports, followed by probabilities and labels. Check that the loss trends downward and the predicted labels are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tensor([[0],
        [1],
        [1],
        [0]], dtype=torch.int32)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exact probabilities and loss values can vary with software versions. These predictions use the same four examples used for training, so they check that the network learned the XOR truth table; they do not measure generalization to a separate dataset.&lt;/p&gt;

&lt;p&gt;Check the files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-lh&lt;/span&gt; train.py xor_model.pth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;xor_model.pth&lt;/code&gt; contains the model's parameter state dictionary. It does not contain the training script or a complete experiment checkpoint. To restore these weights later, recreate the same architecture and load the state dictionary; see &lt;a href="https://docs.pytorch.org/tutorials/beginner/basics/saveloadrun_tutorial.html" rel="noopener noreferrer"&gt;PyTorch's saving and loading tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Resume the project next time
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;Windows CMD or PowerShell&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;strong&gt;Ubuntu&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/research/first-neural-network
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
python train.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs training again from newly initialized weights. It does not resume the previously saved model automatically.&lt;/p&gt;

&lt;p&gt;To leave the environment, run &lt;code&gt;deactivate&lt;/code&gt;. To leave Ubuntu, run &lt;code&gt;exit&lt;/code&gt;. An active foreground process may terminate if its terminal closes, but files already saved remain on disk.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Common setup mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;torch: command not found&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;python train.py&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;No module named 'torch'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Activate &lt;code&gt;.venv&lt;/code&gt;, then install PyTorch with that environment's Python&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;No module named 'numpy'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;python -m pip install numpy&lt;/code&gt; in &lt;code&gt;.venv&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;train.py&lt;/code&gt; prints nothing&lt;/td&gt;
&lt;td&gt;Check that the file contains and saves the code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;wsl -l -v&lt;/code&gt; fails inside Ubuntu&lt;/td&gt;
&lt;td&gt;Run it from Windows, or use &lt;code&gt;wsl.exe -l -v&lt;/code&gt; inside Ubuntu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker Desktop is stopped&lt;/td&gt;
&lt;td&gt;Docker is optional for this experiment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The terminal was closed&lt;/td&gt;
&lt;td&gt;Reopen Ubuntu, return to the folder, and reactivate &lt;code&gt;.venv&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  11. Where this fits in a research workflow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fod1rcre985psrgjjk4ek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fod1rcre985psrgjjk4ek.png" alt="Broader training workflow with Windows, WSL 2, Ubuntu, Docker, and a GPU" width="800" height="845"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This diagram from my notes shows a possible later setup with Docker and GPU acceleration. Those components are optional extensions beyond the CPU workflow used here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq1ojpcab4axbpr5g0ay4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq1ojpcab4axbpr5g0ay4.png" alt="Research workflow connecting version control, local development, remote compute, and saved results" width="800" height="839"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For larger experiments, I want to connect local development and version control with remote compute, then keep model weights, metrics, figures, and logs together. Access to university computing platforms depends on their own eligibility and allocation rules.&lt;/p&gt;

&lt;p&gt;The useful milestone here is modest but concrete: a project directory, isolated dependencies, an executable training script, inspectable predictions, and saved parameters.&lt;/p&gt;

&lt;p&gt;My notes and projects: &lt;a href="https://github.com/Lawson-Dong" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://lawson-dong.vercel.app/" rel="noopener noreferrer"&gt;Personal website&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>machinelearning</category>
      <category>beginners</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
