{
  "source_file": "0930",
  "source_platform": "个人博客",
  "author": "3Blue1Brown",
  "title_listed": "Gradient descent, how neural networks learn",
  "keywords": "梯度下降,学习,可视化",
  "domain": "机器学习",
  "content_type": "视频/教程",
  "is_paid_flag": "否",
  "url": "https://www.3blue1brown.com/lessons/gradient-descent",
  "publish_date": "2017",
  "corpus_stage": "机器学习",
  "notes": "梯度下降可视化",
  "id": "31e255ce5dfc",
  "collected_at": "2026-10-02T15:17:38",
  "title": "Gradient descent, how neural networks learn | 3Blue1Brown",
  "body_markdown": "Neural Networks\nChapter\n2\nG\nr\na\nd\ni\ne\nn\nt\nd\ne\ns\nc\ne\nn\nt\n,\nh\no\nw\nn\ne\nu\nr\na\nl\nn\ne\nt\nw\no\nr\nk\ns\nl\ne\na\nr\nn\nAn overview of gradient descent in the context of neural networks. This is a method used widely throughout machine learning for optimizing how a computer performs on certain tasks.\nOct 16, 2017\nLesson\nby\nGrant Sanderson\nText adaptation\nby\nJosh Pullen\nSource\nIn the last lesson we explored the structure of a neural network. Now, let's talk about how the network learns by seeing many labeled training data. The core idea is a method known as gradient descent, which underlies not only how neural networks learn, but a lot of other machine learning as well.\nRecap From Last Time\nAs a reminder, our goal is to recognize handwritten digits. It's a classic example—the \"hello world\" of neural networks.\nOur goal is to recognize these handwritten digits.\nThese digits are rendered onto a 28x28 pixel grid, where each pixel has some grayscale value between 0.0 and 1.0. Those 784 values determine the activations of the neurons in the input layer of the network.\nEach pixel value in the image becomes the activation of a particular neuron in\nthe first layer of the network.\nThe activation for each neuron in the following layers is based on a weighted sum of all activations from the previous layer, plus some number called the \"bias.\" We then wrap a nonlinear function around this sum, such as a sigmoid or a ReLU.\na_{0}^{(1)} =\n\\textcolor{orange}{\n\\sigma\\left(\n\\textcolor{currentColor}{\n\n\\textcolor{green}{w_{0,0}} a_{0}^{(0)} +\n\\textcolor{green}{w_{0,1}} a_{1}^{(0)} +\n\\cdots +\n\\textcolor{green}{w_{0,n}} a_{n}^{(0)}\n\\textcolor{blue}{+ b_{0}}\n\n}\n\\right)\n}\nIn this way, values propagate from one layer to the next, entirely determined by the weights and biases. The brightest of the ten neurons in the output layer is the network's choice for which digit the image represents.\nImage\nVideo\nThe input layer of neurons has activations based on the pixel values of an\nimage. The rest of the layers have activations depending on each previous\nlayer.\nIn total, given the somewhat arbitrary choice of 2 hidden layers with 16 neurons each, this network has 13,002 weights and biases that we can adjust, and it's these values that determine what exactly the network does.\nRemember, the motivation we had in mind for this layered structure was that maybe the second layer could pick up on edges, the third on patterns like loops and lines, and the last one pieces together those patterns to recognize digits:\nWe hope that the layered structure might allow the problem to be broken into\nsmaller steps, from pixels to edges to loops and lines, and finally to digits.\nHow the Network Learns\nWhat makes machine learning different from other computer science is that you don't explicitly write instructions for doing a particular task. In this case, you never actually write an algorithm for recognizing digits. Instead, you write an algorithm that can take in a bunch of example images of handwritten digits along with labels for what they are and adjust those 13,002 weights and biases of the network to make it perform better on those examples.\nThe labeled images we feed in are collectively known as the \"training data\".\nThe network learns by looking at examples of correctly identified digits.\nHopefully, the layered structure will mean that what it learns generalizes to images beyond the training data. To test this, after training the network, we can show it more labeled data that it's never seen before and see how accurately it classifies them.\nWe use some of the data for training the network and some other data it's\nnever seen before for testing it after it's trained.\nThis process requires a\nlot\nof data. Fortunately, the good people behind the\nMNIST database\nhave put together a collection of tens of thousands of handwritten digit images, each labeled with the number they are supposed to be, that we can use for free.\nI should point out that although it can be provocative to describe a machine as \"learning\", once you see how it works, it feels a lot less like some crazy sci-fi premise and a lot more like a calculus exercise. It really just comes down to finding the minimum of a specific function.\nThe process of learning is essentially just finding lower and lower points on\na specific function.\nThe Cost Function\nRemember, our network's behavior is determined by all of its weights and biases. The weights represent the strength of connections between each neuron in one layer and each neuron in the next. And each bias is an indication of whether its neuron tends to be active or inactive.\nThe behavior of the network depends on its weights and biases.\nTo start things off, initialize all the weights and biases to be random numbers. This network will perform horribly on the given training example since it's just doing something random.\nFor example, if you feed in this image of a 3, the output layer just looks like a mess:\nInitialized with totally random weights and biases, the network is terrible at\nidentifying digits.\nSo how do you programmatically identify that the computer is doing a lousy job and then help it improve?\nWhat you do is define a cost function, which is a way of telling the computer, \"No, bad computer, that output layer should have activations which are 0 for most neurons, but with a 1 for the third neuron. What you gave me is utter trash!\"\nWe measure how badly the network is doing by comparing its results to the\ncorrect answer.\nTo say that a little more mathematically, add up the squares of the differences between each of these trash output activations and the values you want them to have. We'll call this the \"cost\" of a single training example.\nThe \"cost\" is calculated by adding up the squares of the differences between what we got and what we want.\nThe cost is small when the network confidently classifies this image correctly but large when it doesn't know what it's doing.\nSuppose the network is shown an image of a 4. Rank the costs associated with each of the possible outputs shown above.\nB > A > C > D\nB > C > A > D\nD > A > C > B\nD > C > A > B\nCheck\nWhat could it be...\nThe Cost Over Many Examples\nBut we aren't just interested in how the network performs on a\nsingle\nimage. To really measure its performance, we need to consider the\naverage\ncost over all the tens of thousands of training examples. This average is our measure of how lousy the network is and how bad the computer should feel.\nThis is, to put it lightly, a complicated function. Remember how the network itself is a function? It has 784 inputs (the pixel values), 10 outputs, and 13,002 parameters.\nThe neural network is a function that takes in images and spits out digit\npredictions based on the weights and biases.\nThe cost function is a layer of complexity on top of that. The inputs of the cost function are those 13,002 weights and biases, and it spits out a single number describing how bad those weights and biases are. It's defined in terms of the network's behavior on all the tens of thousands of pieces of labeled training data. In other words, this training data is a massive set of parameters to the cost function.\nThe cost function takes in the weights and biases of a network and uses the\ntraining images to compute a \"cost,\" measuring how bad the network is at\nclassifying those training images.\nMinimizing the Cost Function\nJust telling the computer what a terrible job it's doing isn't very helpful. You want to tell it how it should change those 13,002 weights and biases so as to improve.\nWe can do better! Growth mindset!\nTo make it easier, rather than struggling to imagine this cost function with 13,002 inputs, let's imagine a simple function with one number as an input, and one number as an output.\nIn this simple example, we'll imagine that the cost function takes just one\ninput (although, in reality, ours takes 13,002 inputs). How do we find an\ninput that minimizes the cost?\nHow do you find an input that minimizes the value of this cost function?\nCalculus students will know you can sometimes figure out that minimum explicitly by solving for when the slope is zero. However, that's not always feasible for really complicated functions, and it certainly won't be for our 13,002-input function defined in terms of an ungodly number of parameters.\nFor a complicated cost function, computing the exact minimum directly isn't\ngoing to work.\nA more flexible tactic is to start at a random input and figure out which direction to step to make the output lower. Specifically, find the slope of the function where you are. If the slope is negative, shift to the right. If the slope is positive, shift to the left.\nImage\nVideo\nBy following the slope (moving in the downhill direction), we approach a local\nminimum.\nChecking the new slope at each point and doing this repeatedly, you approach some local minimum of the function.\nThe image to have in mind is a ball rolling down a hill:\nNotice, even for this simplified single-input cost function, there are many possible valleys you might land in. It depends on which random input you start at, and there's no guarantee that the local minimum you land in will be the smallest possible value for the cost function.\nAlso, notice how if you make your step sizes proportional to the slope itself when the slope flattens out towards a minimum, your steps will get smaller and smaller, and that keeps you from overshooting.\nBumping up the complexity a bit, imagine a function with two inputs and one output. You might think of the input space as the xy-plane, with the cost function graphed as a surface above it.\nWe can imagine minimizing a function that takes two inputs (which is still not\n13,002 inputs, but it's one step closer). Starting with a random value, look\nfor the downhill direction and repeatedly move that way.\nInstead of asking about the slope of the function, you ask which direction you should step in this input space to decrease the output of the function most quickly. Again, think of a ball rolling down a hill.\nBeyond Slope: Using The Gradient\nIn this higher-dimensional space, it doesn't really make sense to talk about the \"slope\" as a single number. Instead, we need to use a vector to represent the direction of steepest ascent.\nThose of you familiar with multivariable calculus will know that this vector is called the \"gradient\", and it tells you which direction you should step to\nincrease\nthe function most quickly.\nNaturally enough, taking the negative of that vector gives you the direction to step which\ndecreases\nthe function most quickly. What's more, the length of that gradient vector is an indication for just how steep that steepest slope is.\nThe gradient,\n\\nabla C\n, gives the uphill direction, so the negative of the\ngradient,\n-\\nabla C\n, gives the downhill direction.\nTo those of you unfamiliar with multivariable calculus, check out some of\nthe work I did for Khan Academy on the topic\n. Honestly though? All that matters for you and me right now is that in principle, there exists a way to compute this vector, which tells you both what the \"downhill\" direction is, and how steep it is. You'll be okay even if you're not rock solid on the details.\nSo the algorithm for minimizing this function is to compute this gradient direction, take a step downhill, and repeat that over and over. This process is called \"gradient descent.\"\nGradient descent just means walking in the downhill direction to minimize the\ncost function.\nAnd remember, our cost function is specially designed to measure how bad the network is at classifying the training examples. So changing the weights and biases to decrease the cost will make the network's performance better!\n1\nIn practice, each step will look like\n-\\eta \\nabla C\nwhere the constant\n\\eta\nis known as the learning rate. The larger it is, the bigger your steps, which means you might approach the minimum faster, but there's a risk of overshooting and oscillating a lot around that minimum.\nIt's the same basic idea for a function with 13,002 inputs instead of two inputs. I'm still showing the picture of a function with two inputs because nudges to a 13,002-dimensional input are a little hard to wrap your mind around. But let me give you a non-spatial way to think about it.\nAnother Way to Think About The Gradient\nImagine organizing all the weights and biases for the entire network into one big column vector with 13,002 entries. Then the negative gradient of the cost function will also be a vector with 13,002 entries.\nImage\nVideo\nThe vector on the left is a list of all the weights and biases for the entire\nnetwork. The vector on the right is the negative gradient, which is just a\nlist of all the little nudges you should make to the weights and biases (on\nthe left) in order to move downhill.\nThe negative gradient is a vector direction in this insanely huge input space that tells you what nudges to those 13,002 numbers would cause the most rapid decrease to the cost function.\nEach component of the negative gradient vector tells us two things. The sign, of course, tells us whether the corresponding component of the input vector should be nudged up or down. But importantly, the relative magnitudes of the components in this gradient tells us which of those changes matters more.\nYou see, in our network, an adjustment to one weight might have a greater impact on the cost function than an adjustment to some other weight. Consider the image below, and suppose that the network is supposed to be classifying its input as a \"3\".\nSome weights have a larger impact on the cost than others.\nSome of these connections just matter more for our training data than others, and a way you can think about the gradient of our massive cost function is that it encodes the relative importance of each weight and bias. That is, which changes will carry the most bang for your buck.\nSo if the cost function is a layer of complexity on top of the original neural network function, its gradient is one more layer of complexity still, telling us what nudge to all these weights and biases causes the fastest change to the value of the cost function.\nThe negative gradient tells us how to change the weights and biases to\ndecrease the cost most effectively.\nThe algorithm for computing the value of this gradient vector efficiently is called backpropagation, which we'll dig into in the next lesson. There, I want to take the time to really walk through what happens to each weight and bias for a given piece of training data, trying to give an intuitive feel for what's happening beyond the pile of relevant formulas.\nThe main thing I want you to understand here, independent of implementation details, is that when we refer to a network \"learning\", we mean changing the weights and biases to minimize a cost function, which improves the network's performance on the training data.\n2\nBut before we continue on to learn the details of computing this gradient, let's take a\nbrief sidestep\nto dig into what this network looks like after it's trained.\nRemember, this cost function involves an average over\nall\ntraining data, so minimizing it means a better performance on\nall\nthe training samples.\n↩\nOne consequence is that the cost function needs to be nice and smooth so that we can efficiently find a local minimum by taking many little steps downhill.\nThis is why, by the way, these artificial neurons have continuously ranging activations, rather than simply being active or inactive the way biological neurons are.\n↩\nPrevious Lesson\nBut what is a Neural Network?\nNext Lesson\nAnalyzing our neural network\nThanks\nSpecial thanks to those below for supporting this lesson.\nDesmos\nBurt Humburg\nCrypticSwarm\nJuan Benet\nAli Yahya\nWilliam\nMayank M. Mehrotra\nLukas Biewald\nSamantha D. Suplee\nYana Chernobilsky\nKaustuv DeBiswas\nKathryn Schmiedicke\nYu Jun\nDave Nicponski\nDamion Kistler\nMarkus Persson\nYoni Nazarathy\nEd Kellett\nJoseph John Cox\nLuc Ritchie\nEric Chow\nMathias Jansson\nPedro Pérez Sánchez\nDavid Clark\nMichael Gardner\nHarsev Singh\nMads Elvheim\nErik Sundell\nXueqi Li\nDavid G. Stork\nTianyu Ge\nTed Suzman\nLinh Tran\nAndrew Busey\nJohn Haley\nAnkalagon\nEric Lavault\nBoris Veselinovich\nJulian Pulgarin\nJeff Linse\nCooper Jones\nRyan Dahl\nMark Govea\nRobert Teed\nJason Hise\nMeshal Alshammari\nBernd Sing\nJames Thornton\nMustafa Mahdi\nMathew Bramson\nJerry Ling\nVecht\nShimin Kuang\nRish Kundalia\nAchille Brighton\nRipta Pasay\nPsylence\nSoufiane KHIAT\ndim85\nChris\nGokcen Eraslan\nRichard Barthel\nEurghSireAwe\nRyan Cumings\nAlex Samarin\nYixiu Zhao\nJames Park\nJohn C. Vesey\nSuraj Pratap\nSergii Iastremskyi\nTomohiro Furusawa\nSean Bibby\nPatrickJMT\nKenneth Larsen\nSteve Cohen\nGuy rosen\nAnkit Agarwal\nJames Golab\nChad Hurst\nValentin Mayer-Eichberger\nSidwill\nDevin Scott\nHadrien Pierre\nDmitry Chepuryshkin\nKevin Norris\nJake Vartuli - Schonberg\nManuel Garcia\nFlorian Ragwitz\nNikolay Dubina\nMikko\nAlvin Khaled\nBrooks Ryba\nMyles Buckley\nSven Ostertag\nMarcelo Gómez\nMohannad Elhamod\nJustin Helps\nChris Willis\nJim Lauridson\nJim Mussared\nGabriel Cunha\nLoro Lukic\nLee Burnette\nAlexander Juda\nAndy Petsch\nOtavio Good\nV\nBrendan Shah\nAndrew Mcnab\nMatt Parlmer\nDan Davison\naidan boneham\nHenry Reich\nPaul Constantine\nBen Granger\nShow More",
  "metadata": {
    "title": "Gradient descent, how neural networks learn | 3Blue1Brown",
    "description": "An overview of gradient descent in the context of neural networks. This is a method used widely throughout machine learning for optimizing how a computer performs on certain tasks.",
    "keywords": null,
    "author": null,
    "og:type": "website",
    "og:url": "https://www.3blue1brown.com/lessons/gradient-descent/",
    "og:title": "Gradient descent, how neural networks learn | 3Blue1Brown",
    "og:description": "An overview of gradient descent in the context of neural networks. This is a method used widely throughout machine learning for optimizing how a computer performs on certain tasks.",
    "og:image": "https://www.3blue1brown.com/share.jpg",
    "twitter:card": "summary_large_image",
    "twitter:image": "https://www.3blue1brown.com/share.jpg"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/31e255ce5dfc/code/body-000.txt",
      "chars": 242,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/three-3s.jpg",
      "bytes": 67798,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/000.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/three-3s.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/pixels-as-input.jpg",
      "bytes": 737145,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/001.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/pixels-as-input.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/recap-propagation.jpg",
      "bytes": 542985,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/002.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/recap-propagation.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/layer-hypothesis.jpg",
      "bytes": 361214,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/003.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/layer-hypothesis.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/training-data.jpg",
      "bytes": 516480,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/004.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/training-data.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/training-vs-testing.jpg",
      "bytes": 152449,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/005.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/training-vs-testing.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/finding-minima.jpg",
      "bytes": 98472,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/006.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/finding-minima.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/weights-and-biases.jpg",
      "bytes": 151964,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/007.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/weights-and-biases.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/random-trash.jpg",
      "bytes": 574057,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/008.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/random-trash.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/cost-of-difference.jpg",
      "bytes": 621003,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/009.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/cost-of-difference.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/cost-calculation.jpg",
      "bytes": 208853,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/010.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/cost-calculation.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/cost-ranking-question.jpg",
      "bytes": 130292,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/011.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/cost-ranking-question.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/neural-network-function.jpg",
      "bytes": 171969,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/012.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/neural-network-function.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/cost-function.jpg",
      "bytes": 204415,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/013.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/cost-function.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/single-input-cost.jpg",
      "bytes": 93257,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/014.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/single-input-cost.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/infeasible-minimum.jpg",
      "bytes": 121600,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/015.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/infeasible-minimum.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/follow-slope.jpg",
      "bytes": 76564,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/016.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/follow-slope.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/2-input-cost.jpg",
      "bytes": 387113,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/017.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/2-input-cost.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/negative-gradient.jpg",
      "bytes": 402004,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/018.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/negative-gradient.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/gradient-descent.jpg",
      "bytes": 301799,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/019.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/gradient-descent.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/weights-and-gradient.jpg",
      "bytes": 144707,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/020.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/weights-and-gradient.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/gradient-explained.jpg",
      "bytes": 127727,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/021.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/gradient-explained.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/weight-importance.jpg",
      "bytes": 369880,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/022.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/weight-importance.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/nudges-on-network.jpg",
      "bytes": 430021,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/023.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/nudges-on-network.jpg",
      "alt": "Image",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://img.youtube.com/vi/aircAruvnKk/maxresdefault.jpg",
      "bytes": 184532,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/024.jpg",
      "src": "https://img.youtube.com/vi/aircAruvnKk/maxresdefault.jpg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/neural-network-analysis/thumbnail.jpg",
      "bytes": 371298,
      "reused": true,
      "local_path": "attachments/31e255ce5dfc/images/025.jpg",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/neural-network-analysis/thumbnail.jpg",
      "alt": "",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [
    {
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/balls-rolling-down.mp4",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/balls-rolling-down.mp4",
      "status": "ok",
      "kind": "direct_video",
      "bytes": 95482,
      "reused": false,
      "content_type": "video/mp4",
      "valid": true,
      "height": 1080,
      "width": 1920,
      "duration": "4.371033",
      "local_path": "attachments/31e255ce5dfc/videos/repair-f2ee374b22dc12739f1a.mp4"
    },
    {
      "url": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/proportional-to-slope.mp4",
      "src": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/proportional-to-slope.mp4",
      "status": "ok",
      "kind": "direct_video",
      "bytes": 133830,
      "reused": false,
      "content_type": "video/mp4",
      "valid": true,
      "height": 1080,
      "width": 1920,
      "duration": "8.575233",
      "local_path": "attachments/31e255ce5dfc/videos/repair-c29fe529830e01a08a18.mp4"
    }
  ],
  "links": [
    {
      "href": "https://www.3blue1brown.com/?topic=neural-networks",
      "label": "Neural Networks",
      "type": "a"
    },
    {
      "href": "https://www.3blue1brown.com/lessons/gradient-descent/",
      "label": "G r a d i e n t d e s c e n t , h o w n e u r a l n e t w o r k s l e a r n",
      "type": "a"
    },
    {
      "href": "https://www.3blue1brown.com/about",
      "label": "Grant Sanderson",
      "type": "a"
    },
    {
      "href": "https://www.joshuapullen.com/",
      "label": "Josh Pullen",
      "type": "a"
    },
    {
      "href": "https://github.com/3b1b/videos/blob/master/_2017/nn/part2.py",
      "label": "Source",
      "type": "a"
    },
    {
      "href": "http://yann.lecun.com/exdb/mnist/",
      "label": "MNIST database",
      "type": "a"
    },
    {
      "href": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/balls-rolling-down.mp4",
      "label": "",
      "type": "source"
    },
    {
      "href": "https://storage.googleapis.com/3blue1brown-website-bucket/lessons/2017/gradient-descent/proportional-to-slope.mp4",
      "label": "",
      "type": "source"
    },
    {
      "href": "https://www.khanacademy.org/math/multivariable-calculus",
      "label": "the work I did for Khan Academy on the topic",
      "type": "a"
    },
    {
      "href": "https://www.3blue1brown.com/lessons/neural-networks",
      "label": "Previous Lesson But what is a Neural Network?",
      "type": "a"
    },
    {
      "href": "https://www.3blue1brown.com/lessons/neural-network-analysis",
      "label": "Next Lesson Analyzing our neural network",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:53:11Z",
  "source_url": "https://www.3blue1brown.com/lessons/gradient-descent",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 17170,
  "expected_body_images": 26,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/31e255ce5dfc/pages/source.html",
  "local_html": "attachments/31e255ce5dfc/pages/article.html",
  "body_base_path": "attachments/31e255ce5dfc/pages/",
  "body_markdown_path": "attachments/31e255ce5dfc/pages/article.md"
}