{"id":1161,"date":"2026-10-17T21:05:35","date_gmt":"2026-10-17T15:35:35","guid":{"rendered":"https:\/\/codeanddebug.in\/blog\/?p=1161"},"modified":"2026-10-20T13:50:30","modified_gmt":"2026-10-20T08:20:30","slug":"linear-regression-in-machine-learning","status":"publish","type":"post","link":"https:\/\/codeanddebug.in\/blog\/linear-regression-in-machine-learning\/","title":{"rendered":"Linear Regression in Machine Learning: Explained Visually (with Python)"},"content":{"rendered":"\n<style>.cdai{--cd-brand:#3c3fde;--cd-brand-soft:#eceeff;--cd-ink:#14162b;--cd-muted:#5b5f7a;--cd-line:#dfe1ee;--cd-card:#ffffff;--cd-bg:#f6f7fc;--cd-good:#0f8a5f;--cd-good-soft:#e3f6ee;--cd-bad:#c2410c;--cd-bad-soft:#fdebe1;--cd-warn:#b7791f;--cd-on-brand:#ffffff;\nfont-family:Inter,system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;color:var(--cd-ink);background:var(--cd-bg);border:1px solid var(--cd-line);border-radius:14px;padding:22px;margin:28px 0;line-height:1.55;font-size:16px;box-sizing:border-box;max-width:100%;overflow:hidden}\n.s-dark .cdai,.cdai.cd-dark{--cd-brand:#8d90ff;--cd-brand-soft:#23254a;--cd-ink:#e8e9f5;--cd-muted:#a3a6c2;--cd-line:#32354f;--cd-card:#1b1d33;--cd-bg:#14162a;--cd-good:#4ccf98;--cd-good-soft:#163a2c;--cd-bad:#ff9a6b;--cd-bad-soft:#3d2316;--cd-warn:#f2c46b;--cd-on-brand:#0f1030}\n.cdai *,.cdai *::before,.cdai *::after{box-sizing:border-box}\n.cdai h4.cd-h{font-family:Outfit,Inter,sans-serif;font-size:1.25rem;font-weight:700;margin:0 0 4px;color:var(--cd-ink);line-height:1.3}\n.cdai .cd-sub{color:var(--cd-muted);font-size:.95rem;margin:0 0 16px}\n.cdai .cd-tag{display:inline-block;font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--cd-brand);background:var(--cd-brand-soft);padding:3px 9px;border-radius:99px;margin-bottom:10px}\n.cdai button.cd-btn,.cdai .cd-chip{font:inherit;font-size:.92rem;font-weight:600;cursor:pointer;border-radius:10px;border:1.5px solid var(--cd-line);background:var(--cd-card);color:var(--cd-ink);padding:9px 14px;line-height:1.3;transition:transform .15s ease,border-color .15s ease,background .15s ease;text-transform:none;letter-spacing:normal;box-shadow:none;margin:0;min-height:0;height:auto}\n.cdai button.cd-btn:hover,.cdai .cd-chip:hover{border-color:var(--cd-brand);transform:translateY(-1px)}\n.cdai button.cd-btn:focus-visible,.cdai .cd-chip:focus-visible,.cdai input:focus-visible{outline:3px solid var(--cd-brand);outline-offset:2px}\n.cdai .cd-primary,.cdai button.cd-primary{background:var(--cd-brand);border-color:var(--cd-brand);color:var(--cd-on-brand)}\n.cdai .cd-chip[aria-pressed=\"true\"]{background:var(--cd-brand);border-color:var(--cd-brand);color:var(--cd-on-brand)}\n.cdai .cd-row{display:flex;flex-wrap:wrap;gap:10px;align-items:center}\n.cdai .cd-grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,230px),1fr));gap:12px}\n.cdai .cd-card{background:var(--cd-card);border:1px solid var(--cd-line);border-radius:12px;padding:14px}\n.cdai .cd-stat{font-family:Outfit,Inter,sans-serif;font-size:2rem;font-weight:700;color:var(--cd-brand);line-height:1.1;font-variant-numeric:tabular-nums}\n.cdai .cd-small{font-size:.85rem;color:var(--cd-muted)}\n.cdai label.cd-lab{font-weight:600;font-size:.92rem;display:flex;justify-content:space-between;gap:10px;margin:14px 0 6px}\n.cdai input[type=range]{width:100%;accent-color:var(--cd-brand);margin:0;height:28px;background:transparent;border:0;padding:0}\n.cdai canvas{display:block;width:100%;height:auto;border-radius:10px;background:var(--cd-card);border:1px solid var(--cd-line);touch-action:pan-y}\n\/* hero *\/\n.cdai.cd-hero{padding:0;position:relative;background:#101233;border-color:#24275a}\n.cdai.cd-hero canvas{border:0;border-radius:0;background:transparent;height:200px}\n.cdai.cd-hero .cd-hero-txt{position:absolute;left:0;right:0;bottom:0;padding:16px 20px;background:linear-gradient(transparent,rgba(16,18,51,.92) 55%);color:#fff}\n.cdai.cd-hero .cd-hero-txt b{font-family:Outfit,Inter,sans-serif;font-size:1.15rem}\n.cdai.cd-hero .cd-hero-txt span{display:block;color:#c9cbff;font-size:.9rem}\n\/* planner *\/\n.cdai .cd-timeline{display:flex;flex-direction:column;gap:7px;margin-top:6px}\n.cdai .cd-tl-row{display:grid;grid-template-columns:minmax(0,150px) 1fr 62px;gap:10px;align-items:center;font-size:.88rem}\n.cdai .cd-tl-name{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.cdai .cd-tl-name a{color:inherit;text-decoration:none}\n.cdai .cd-tl-name a:hover{color:var(--cd-brand)}\n.cdai .cd-tl-track{height:14px;background:var(--cd-brand-soft);border-radius:99px;overflow:hidden}\n.cdai .cd-tl-bar{height:100%;background:var(--cd-brand);border-radius:99px;width:0;transition:width .6s cubic-bezier(.2,.8,.2,1)}\n.cdai .cd-tl-bar.cd-skim{background:repeating-linear-gradient(45deg,var(--cd-brand),var(--cd-brand) 6px,transparent 6px,transparent 10px)}\n.cdai .cd-tl-w{text-align:right;font-variant-numeric:tabular-nums;color:var(--cd-muted)}\n.cdai .cd-prog{height:10px;border-radius:99px;background:var(--cd-brand-soft);overflow:hidden;margin-top:8px}\n.cdai .cd-prog i{display:block;height:100%;background:var(--cd-good);width:0;transition:width .4s ease}\n@media (max-width:520px){.cdai{padding:16px}.cdai .cd-tl-row{grid-template-columns:minmax(0,110px) 1fr 50px;font-size:.8rem}}\n\/* game *\/\n.cdai .cd-game-card{background:var(--cd-card);border:1px solid var(--cd-line);border-radius:12px;padding:18px;min-height:96px;font-size:1.05rem;font-weight:600;display:flex;align-items:center}\n.cdai .cd-feedback{margin-top:12px;padding:12px 14px;border-radius:10px;font-size:.93rem}\n.cdai .cd-feedback.cd-ok{background:var(--cd-good-soft);color:var(--cd-ink);border-left:4px solid var(--cd-good)}\n.cdai .cd-feedback.cd-no{background:var(--cd-bad-soft);color:var(--cd-ink);border-left:4px solid var(--cd-bad)}\n.cdai .cd-venn{position:relative;width:min(100%,300px);aspect-ratio:1\/1;margin:6px auto 0}\n.cdai .cd-venn div{position:absolute;border-radius:50%;border:2px solid var(--cd-brand);display:flex;justify-content:center;font-weight:700;font-size:.8rem;color:var(--cd-ink);padding-top:6px;transition:background .3s ease,transform .3s ease}\n.cdai .cd-venn div.cd-lit{background:var(--cd-brand-soft);transform:scale(1.03)}\n.cdai .cd-v1{inset:0}.cdai .cd-v2{inset:12%}.cdai .cd-v3{inset:26%}.cdai .cd-v4{inset:40%;align-items:center;padding-top:0!important}\n\/* checklist *\/\n.cdai.cd-check{padding:16px 18px;background:var(--cd-card)}\n.cdai.cd-check ul{list-style:none;margin:8px 0 0;padding:0}\n.cdai.cd-check li{margin:0;padding:0}\n.cdai.cd-check label{display:flex;gap:10px;align-items:flex-start;padding:7px 4px;cursor:pointer;font-size:.95rem;border-radius:8px}\n.cdai.cd-check label:hover{background:var(--cd-bg)}\n.cdai.cd-check input{width:18px;height:18px;margin-top:3px;accent-color:var(--cd-good);flex:none}\n.cdai.cd-check .cd-done{color:var(--cd-good);font-weight:700}\n\/* tokens *\/\n.cdai .cd-bars{display:flex;flex-direction:column;gap:6px;margin-top:10px}\n.cdai .cd-bar-row{display:grid;grid-template-columns:110px 1fr 52px;gap:10px;align-items:center;font-size:.9rem}\n.cdai .cd-bar-row b{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-weight:600}\n.cdai .cd-bar-row .cd-tl-bar{transition:width .35s ease}\n.cdai .cd-out{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:var(--cd-card);border:1px solid var(--cd-line);border-radius:10px;padding:12px;margin-top:12px;min-height:46px;font-size:.92rem;word-break:break-word}\n.cdai .cd-out mark{background:var(--cd-brand-soft);color:var(--cd-brand);padding:1px 4px;border-radius:4px;animation:cdpop .4s ease}\n@keyframes cdpop{from{transform:scale(1.4);opacity:0}to{transform:none;opacity:1}}\n.cdai .cd-meter{font-family:Outfit,Inter,sans-serif;font-weight:700;font-size:1.6rem;font-variant-numeric:tabular-nums}\n@media (prefers-reduced-motion:reduce){.cdai *{transition:none!important;animation:none!important}}\n.cdai .cd-tbl-wrap{overflow-x:auto;margin-top:10px}\n.cdai table.cd-tbl{border-collapse:collapse;width:100%;font-size:.88rem;font-variant-numeric:tabular-nums;background:var(--cd-card);margin:0}\n.cdai table.cd-tbl th,.cdai table.cd-tbl td{border:1px solid var(--cd-line);padding:6px 8px;text-align:center;color:var(--cd-ink)}\n.cdai table.cd-tbl th{background:var(--cd-brand-soft);font-weight:700;font-size:.8rem}\n.cdai table.cd-tbl input{width:64px;font:inherit;padding:4px 6px;border:1.5px solid var(--cd-line);border-radius:6px;background:var(--cd-bg);color:var(--cd-ink);text-align:center;margin:0}\n.cdai .cd-steps{margin-top:12px;display:grid;gap:6px;font-size:.92rem}\n.cdai .cd-steps div{background:var(--cd-card);border:1px solid var(--cd-line);border-radius:8px;padding:8px 12px}\n.cdai .cd-steps code,.cdai .cd-eq{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.9rem;background:transparent;color:var(--cd-ink);padding:0}\n.cdai .cd-eq{display:inline-block;background:var(--cd-brand-soft);color:var(--cd-brand);padding:4px 10px;border-radius:8px;font-weight:700}\n.cdai.cd-codebox{padding:0;background:#16182c;border-color:#2a2d48}\n.cdai.cd-codebox .cd-codehead{display:flex;justify-content:space-between;align-items:center;padding:8px 14px;border-bottom:1px solid #2a2d48;color:#a3a6c2;font-size:.8rem;font-weight:600}\n.cdai.cd-codebox pre{margin:0;padding:14px 16px;overflow-x:auto;background:transparent;border:0;color:#e6e7f2;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.86rem;line-height:1.6;white-space:pre}\n.cdai.cd-codebox pre code{background:transparent;color:inherit;padding:0;font:inherit}\n.cdai.cd-codebox .cd-copy{font:inherit;font-size:.78rem;font-weight:600;cursor:pointer;background:#2a2d48;color:#e6e7f2;border:0;border-radius:6px;padding:5px 10px;margin:0;text-transform:none;letter-spacing:normal}\n.cdai.cd-codebox .cd-outp{border-top:1px dashed #2a2d48;color:#8fe3b8}\n.cdai .cd-legend{display:flex;flex-wrap:wrap;gap:14px;font-size:.82rem;color:var(--cd-muted);margin-top:8px}\n.cdai .cd-legend i{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:5px;vertical-align:middle}\n.cdai canvas.cd-touch{touch-action:none;cursor:crosshair}\n.cdai canvas.cd-grab{touch-action:none;cursor:grab}\n.cdai .cd-q-opts{display:grid;gap:8px;margin-top:12px}\n.cdai .cd-q-opts button.cd-btn{text-align:left;width:100%}\n.cdai .cd-q-opts button.cd-right{border-color:var(--cd-good);background:var(--cd-good-soft)}\n.cdai .cd-q-opts button.cd-wrong{border-color:var(--cd-bad);background:var(--cd-bad-soft)}\n<\/style>\n\n\n\n<p class=\"wp-block-paragraph\">Linear regression is usually the first machine learning algorithm anyone learns, and for good reason. It is simple enough to calculate by hand, it is still used every day in companies to forecast sales, price flats and estimate demand, and almost every advanced model builds on the same ideas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide teaches it the way it clicks best: by playing with it. You will drag points and watch the line move, calculate the formula step by step, watch the model learn through gradient descent, spin a 3D regression plane, and break the assumptions on purpose to see what goes wrong. The Python code at the end is ready to copy and run.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-what\">What is linear regression in machine learning?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Linear regression is a supervised machine learning algorithm that predicts a number by fitting a straight line through your data. You give it examples where you already know the answer, like hours studied and the marks a student scored, and it finds the line that best describes how one changes with the other. Then it uses that line to predict answers for new inputs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The line is written as:<\/p>\n\n\n\n<div class=\"cdai\" style=\"text-align:center;padding:16px\"><span class=\"cd-eq\" style=\"font-size:1.25rem\">y = m \u00d7 x + b<\/span><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>x<\/strong> is the input, also called the feature or independent variable. Example: hours studied.<\/li>\n\n\n<li><strong>y<\/strong> is the output you want to predict, also called the target or dependent variable. Example: marks.<\/li>\n\n\n<li><strong>m<\/strong> is the slope, also called the weight or coefficient. It tells you how much y changes when x goes up by 1.<\/li>\n\n\n<li><strong>b<\/strong> is the intercept, also called the bias. It is the value of y when x is 0.<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Try it below. Every dot is a student. The blue line is the best-fit line, and the red lines are the errors, which are the gaps between what the line predicts and what really happened. Click anywhere to add a student, drag any dot to move it, and see how the line reacts. Then press <em>Add an outlier<\/em> and watch a single bad data point pull the whole line down.<\/p>\n\n\n\n<div class=\"cdai cd-lr-play\">\n<span class=\"cd-tag\">Try it<\/span>\n<h4 class=\"cd-h\">Linear regression playground<\/h4>\n<p class=\"cd-sub\">Click to add a point. Drag a point to move it.<\/p>\n<canvas class=\"cd-touch\"><\/canvas>\n<div class=\"cd-grid2\" style=\"margin-top:12px\">\n<div class=\"cd-card\"><div class=\"cd-small\">Best-fit line<\/div><div class=\"cd-play-eq\" style=\"font-family:ui-monospace,Menlo,Consolas,monospace;font-weight:700;color:var(--cd-brand);margin-top:4px\"><\/div><\/div>\n<div class=\"cd-card\"><div class=\"cd-row\" style=\"justify-content:space-between\"><span class=\"cd-small\">R\u00b2 score<\/span><b class=\"cd-play-r2\"><\/b><\/div><div class=\"cd-row\" style=\"justify-content:space-between\"><span class=\"cd-small\">Mean squared error<\/span><b class=\"cd-play-mse\"><\/b><\/div><div class=\"cd-row\" style=\"justify-content:space-between\"><span class=\"cd-small\">Points<\/span><b class=\"cd-play-n\"><\/b><\/div><\/div>\n<\/div>\n<div class=\"cd-row\" style=\"margin-top:12px\"><button type=\"button\" class=\"cd-btn cd-play-outlier\">Add an outlier<\/button><button type=\"button\" class=\"cd-btn cd-play-undo\">Remove last point<\/button><button type=\"button\" class=\"cd-btn cd-play-reset\">Reset<\/button><label class=\"cd-small\" style=\"display:flex;gap:6px;align-items:center\"><input type=\"checkbox\" class=\"cd-play-err\" checked> Show errors<\/label><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Notice that the line never passes through every point. It cannot, because real data is noisy. Linear regression finds the one line that keeps the total error as small as possible.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Real-life examples of linear regression<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Predicting the price of a flat from its size, age and distance from the metro<\/li>\n\n\n<li>Estimating next month&#8217;s sales from advertising spend<\/li>\n\n\n<li>Forecasting electricity demand from temperature<\/li>\n\n\n<li>Predicting a student&#8217;s marks from hours studied and attendance<\/li>\n\n\n<li>Estimating a delivery time from distance and traffic<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In all of these, the thing you predict is a number on a continuous scale. That is what regression means in machine learning. When the answer is a category instead, like spam or not spam, you need a classification model, which we compare later in this guide.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-formula\">Simple linear regression and its formula<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Simple linear regression has one input and one output. To find the best line, it uses a method called ordinary least squares (OLS), which picks the m and b that make the sum of squared errors as small as possible. The formulas are:<\/p>\n\n\n\n<div class=\"cdai\" style=\"padding:16px;display:grid;gap:10px;justify-items:center\"><span class=\"cd-eq\">m = \u03a3(x \u2212 x\u0304)(y \u2212 \u0233) \u00f7 \u03a3(x \u2212 x\u0304)\u00b2<\/span><span class=\"cd-eq\">b = \u0233 \u2212 m \u00d7 x\u0304<\/span><span class=\"cd-small\">x\u0304 and \u0233 are the averages of x and y<\/span><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The formula looks scary until you do it once. Edit any number in the table below and every step of the calculation updates with it.<\/p>\n\n\n\n<div class=\"cdai cd-lr-calc\">\n<span class=\"cd-tag\">Try it<\/span>\n<h4 class=\"cd-h\">Linear regression formula calculator<\/h4>\n<p class=\"cd-sub\">x = hours studied, y = marks. Change any value.<\/p>\n<div class=\"cd-tbl-wrap\"><table class=\"cd-tbl\"><thead><tr><th>x<\/th><th>y<\/th><th>x \u2212 x\u0304<\/th><th>y \u2212 \u0233<\/th><th>(x \u2212 x\u0304)(y \u2212 \u0233)<\/th><th>(x \u2212 x\u0304)\u00b2<\/th><\/tr><\/thead><tbody><tr><td><input type=\"number\" step=\"any\" value=\"2\" aria-label=\"x value row 1\"><\/td><td><input type=\"number\" step=\"any\" value=\"40\" aria-label=\"y value row 1\"><\/td><td><\/td><td><\/td><td><\/td><td><\/td><\/tr><tr><td><input type=\"number\" step=\"any\" value=\"3\" aria-label=\"x value row 2\"><\/td><td><input type=\"number\" step=\"any\" value=\"50\" aria-label=\"y value row 2\"><\/td><td><\/td><td><\/td><td><\/td><td><\/td><\/tr><tr><td><input type=\"number\" step=\"any\" value=\"5\" aria-label=\"x value row 3\"><\/td><td><input type=\"number\" step=\"any\" value=\"62\" aria-label=\"y value row 3\"><\/td><td><\/td><td><\/td><td><\/td><td><\/td><\/tr><tr><td><input type=\"number\" step=\"any\" value=\"7\" aria-label=\"x value row 4\"><\/td><td><input type=\"number\" step=\"any\" value=\"75\" aria-label=\"y value row 4\"><\/td><td><\/td><td><\/td><td><\/td><td><\/td><\/tr><tr><td><input type=\"number\" step=\"any\" value=\"8\" aria-label=\"x value row 5\"><\/td><td><input type=\"number\" step=\"any\" value=\"80\" aria-label=\"y value row 5\"><\/td><td><\/td><td><\/td><td><\/td><td><\/td><\/tr><\/tbody>\n<tfoot><tr><th colspan=\"4\" style=\"text-align:right\">Sums<\/th><th class=\"cd-sum-xy\"><\/th><th class=\"cd-sum-xx\"><\/th><\/tr><\/tfoot><\/table><\/div>\n<label class=\"cd-lab\" style=\"justify-content:flex-start;gap:10px;align-items:center\">Predict y when x = <input type=\"number\" step=\"any\" value=\"6\" class=\"cd-calc-q\" style=\"width:80px;font:inherit;padding:4px 6px;border:1.5px solid var(--cd-line);border-radius:6px;background:var(--cd-card);color:var(--cd-ink);margin:0\"><\/label>\n<div class=\"cd-steps cd-calc-res\"><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">With the default numbers you get <code>y = 6.538x + 28.708<\/code>. In plain words: each extra hour of study adds about 6.5 marks, and a student who studies zero hours would be expected to score about 29.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-learn\">How the model learns: cost function and gradient descent<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The formula above works perfectly for simple linear regression. Machine learning libraries also need a more general way to learn, one that still works with thousands of features and other model types. That way has two parts.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>cost function<\/strong> measures how wrong the line is. Linear regression uses the mean squared error (MSE): take each error, square it so negatives do not cancel positives, and average them.<\/p>\n\n\n\n<div class=\"cdai\" style=\"text-align:center;padding:16px\"><span class=\"cd-eq\">MSE = (1\/n) \u00d7 \u03a3 (actual \u2212 predicted)\u00b2<\/span><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Gradient descent<\/strong> then lowers that error step by step. It starts with a random line, calculates which direction to nudge m and b so the error drops, moves a small amount in that direction, and repeats. The size of each nudge is the <strong>learning rate<\/strong>. Watch it happen below, then push the learning rate above 0.035 to see training blow up.<\/p>\n\n\n\n<div class=\"cdai cd-lr-gd\">\n<span class=\"cd-tag\">Try it<\/span>\n<h4 class=\"cd-h\">Watch gradient descent find the line<\/h4>\n<p class=\"cd-sub\">Left: the line being learned. Right: the error falling over time.<\/p>\n<div class=\"cd-grid2\"><canvas><\/canvas><canvas><\/canvas><\/div>\n<label class=\"cd-lab\"><span>Learning rate<\/span><span class=\"cd-gd-lrv\">0.010<\/span><\/label>\n<input type=\"range\" class=\"cd-gd-lr\" min=\"0.001\" max=\"0.04\" step=\"0.001\" value=\"0.01\" aria-label=\"Learning rate\">\n<div class=\"cd-row\" style=\"margin-top:10px\"><button type=\"button\" class=\"cd-btn cd-primary cd-gd-run\">Run<\/button><button type=\"button\" class=\"cd-btn cd-gd-one\">One step<\/button><button type=\"button\" class=\"cd-btn cd-gd-reset\">Reset<\/button><\/div>\n<div class=\"cd-grid2\" style=\"margin-top:12px;grid-template-columns:repeat(auto-fit,minmax(110px,1fr))\">\n<div class=\"cd-card\"><div class=\"cd-small\">slope m<\/div><div class=\"cd-meter cd-gd-m\">0<\/div><\/div>\n<div class=\"cd-card\"><div class=\"cd-small\">intercept b<\/div><div class=\"cd-meter cd-gd-b\">0<\/div><\/div>\n<div class=\"cd-card\"><div class=\"cd-small\">MSE<\/div><div class=\"cd-meter cd-gd-e\">0<\/div><\/div>\n<div class=\"cd-card\"><div class=\"cd-small\">steps<\/div><div class=\"cd-meter cd-gd-n\">0<\/div><\/div>\n<\/div>\n<p class=\"cd-small cd-gd-note\" style=\"margin:10px 0 0\"><\/p>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Gradient descent ends up at almost exactly the same m and b that the formula gives. The formula is the shortcut, and gradient descent is the general method that also trains neural networks. If you want to see where this fits in the bigger picture, our <a href=\"https:\/\/codeanddebug.in\/blog\/how-to-learn-ai-ml-from-scratch-roadmap\/\">AI and ML roadmap<\/a> shows what to learn before and after this.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-multiple\">Multiple linear regression<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Real problems rarely have just one input. A flat&#8217;s price depends on its size, its age, the floor, the distance to the metro and more. Multiple linear regression handles this by giving each feature its own weight:<\/p>\n\n\n\n<div class=\"cdai\" style=\"text-align:center;padding:16px\"><span class=\"cd-eq\">y = b\u2080 + b\u2081x\u2081 + b\u2082x\u2082 + \u2026 + b\u2099x\u2099<\/span><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Each coefficient tells you the effect of one feature while the others stay fixed. With two features, the model is no longer a line. It is a flat plane in 3D space. Drag the chart below to rotate it.<\/p>\n\n\n\n<div class=\"cdai cd-lr-3d\">\n<span class=\"cd-tag\">Try it<\/span>\n<h4 class=\"cd-h\">Multiple regression plane in 3D<\/h4>\n<p class=\"cd-sub\">Price of 34 sample flats from size and age. Drag to rotate.<\/p>\n<canvas class=\"cd-grab\"><\/canvas>\n<div class=\"cd-legend\"><span><i style=\"background:var(--cd-good)\"><\/i>Flat priced above the plane<\/span><span><i style=\"background:var(--cd-ink)\"><\/i>Below the plane<\/span><span><i style=\"background:var(--cd-bad);border-radius:2px;height:3px;width:14px\"><\/i>Error<\/span><\/div>\n<div class=\"cd-row\" style=\"margin-top:10px;justify-content:space-between\"><span class=\"cd-eq cd-3d-eq\" style=\"font-size:.85rem\"><\/span><button type=\"button\" class=\"cd-btn cd-3d-spin\">Pause spin<\/button><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The size coefficient comes out positive (bigger flats cost more) and the age coefficient negative (older flats cost less), which is exactly what you would expect. Reading coefficients like this is one of the biggest reasons linear regression is still popular: you can explain every prediction it makes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Simple vs multiple linear regression<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th><\/th><th>Simple linear regression<\/th><th>Multiple linear regression<\/th><\/tr><\/thead><tbody><tr><td>Number of inputs<\/td><td>One feature<\/td><td>Two or more features<\/td><\/tr><tr><td>Equation<\/td><td>y = mx + b<\/td><td>y = b\u2080 + b\u2081x\u2081 + \u2026 + b\u2099x\u2099<\/td><\/tr><tr><td>Shape of the model<\/td><td>A line<\/td><td>A plane, or a hyperplane in more dimensions<\/td><\/tr><tr><td>Example<\/td><td>Marks from hours studied<\/td><td>Flat price from size, age and metro distance<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-assumptions\">Assumptions of linear regression<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Linear regression gives trustworthy results only when the data follows a few rules. A common way to remember them is <strong>LINE<\/strong>, plus one extra rule for multiple regression:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li><strong>Linearity:<\/strong> the relationship between the features and the target is roughly a straight line.<\/li>\n\n\n<li><strong>Independence:<\/strong> each data point is independent. One student&#8217;s marks do not affect another&#8217;s.<\/li>\n\n\n<li><strong>Normality:<\/strong> the errors (residuals) are roughly normally distributed.<\/li>\n\n\n<li><strong>Equal variance (homoscedasticity):<\/strong> the spread of errors stays about the same across all values of x.<\/li>\n\n\n<li><strong>No multicollinearity:<\/strong> features are not strongly correlated with each other.<\/li>\n\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">The easiest way to check most of these is a <strong>residual plot<\/strong>: plot each error against x. Healthy residuals look like random noise around zero. Click through the cases below to see what broken assumptions look like.<\/p>\n\n\n\n<div class=\"cdai cd-lr-assume\">\n<span class=\"cd-tag\">Try it<\/span>\n<h4 class=\"cd-h\">Assumption checker<\/h4>\n<div class=\"cd-row\" role=\"group\" aria-label=\"Data type\">\n<button type=\"button\" class=\"cd-chip\" data-k=\"healthy\" aria-pressed=\"true\">Healthy data<\/button>\n<button type=\"button\" class=\"cd-chip\" data-k=\"curved\" aria-pressed=\"false\">Curved<\/button>\n<button type=\"button\" class=\"cd-chip\" data-k=\"funnel\" aria-pressed=\"false\">Funnel<\/button>\n<button type=\"button\" class=\"cd-chip\" data-k=\"outlier\" aria-pressed=\"false\">Outliers<\/button>\n<\/div>\n<div class=\"cd-grid2\" style=\"margin-top:12px\"><div><div class=\"cd-small\" style=\"margin-bottom:4px\">Data and fitted line<\/div><canvas><\/canvas><\/div><div><div class=\"cd-small\" style=\"margin-bottom:4px\">Residual plot<\/div><canvas><\/canvas><\/div><\/div>\n<div class=\"cd-feedback cd-ok\" style=\"margin-top:12px\"><b class=\"cd-as-title\"><\/b> <span class=\"cd-as-text\"><\/span><\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-evaluate\">How to evaluate a linear regression model<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Once the model is trained, test it on data it has never seen. These are the four metrics you will use most:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Metric<\/th><th>What it measures<\/th><th>How to read it<\/th><\/tr><\/thead><tbody><tr><td>MAE (mean absolute error)<\/td><td>Average size of the errors<\/td><td>In the same units as y. MAE of 5 lakh means predictions are off by 5 lakh on average<\/td><\/tr><tr><td>MSE (mean squared error)<\/td><td>Average of squared errors<\/td><td>Punishes big errors heavily. Used for training<\/td><\/tr><tr><td>RMSE (root mean squared error)<\/td><td>Square root of MSE<\/td><td>Back in the units of y, and more sensitive to large misses than MAE<\/td><\/tr><tr><td>R\u00b2 (R-squared)<\/td><td>Share of the variation in y the model explains<\/td><td>1 is perfect, 0 is no better than predicting the average<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-vs-logistic\">Linear regression vs logistic regression<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The names are confusingly similar, but they solve different problems. Linear regression predicts a number, like a price or marks. Logistic regression predicts the probability of a category, like pass or fail, spam or not spam. The demo below shows why you cannot use a straight line for yes or no answers.<\/p>\n\n\n\n<div class=\"cdai cd-lr-log\">\n<span class=\"cd-tag\">Try it<\/span>\n<h4 class=\"cd-h\">Pass or fail: straight line vs S-curve<\/h4>\n<div class=\"cd-row\" role=\"group\" aria-label=\"Model type\"><button type=\"button\" class=\"cd-chip\" data-m=\"linear\" aria-pressed=\"true\">Linear regression<\/button><button type=\"button\" class=\"cd-chip\" data-m=\"logistic\" aria-pressed=\"false\">Logistic regression<\/button><\/div>\n<canvas style=\"margin-top:12px\"><\/canvas>\n<label class=\"cd-lab\"><span>Hours studied<\/span><span class=\"cd-log-hv\"><\/span><\/label>\n<input type=\"range\" class=\"cd-log-h\" min=\"0\" max=\"12\" step=\"0.5\" value=\"11\" aria-label=\"Hours studied\">\n<div class=\"cd-row\" style=\"justify-content:space-between;margin-top:8px\"><span class=\"cd-small\">Model output<\/span><span class=\"cd-meter cd-log-out\"><\/span><\/div>\n<p class=\"cd-small cd-log-msg\" style=\"margin:6px 0 0\"><\/p>\n<\/div>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th><\/th><th>Linear regression<\/th><th>Logistic regression<\/th><\/tr><\/thead><tbody><tr><td>Type of problem<\/td><td>Regression<\/td><td>Classification<\/td><\/tr><tr><td>Output<\/td><td>Any number, like 64.6 marks<\/td><td>A probability between 0 and 1<\/td><\/tr><tr><td>Shape<\/td><td>Straight line<\/td><td>S-shaped sigmoid curve<\/td><\/tr><tr><td>Loss used in training<\/td><td>Mean squared error<\/td><td>Log loss (cross-entropy)<\/td><\/tr><tr><td>Example<\/td><td>Predict a flat&#8217;s price<\/td><td>Predict if a loan will default<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-python\">Linear regression in Python with scikit-learn<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Time to write real code. You need NumPy, Pandas and scikit-learn (<code>pip install numpy pandas scikit-learn<\/code>). If Pandas is new to you, our <a href=\"https:\/\/codeanddebug.in\/blog\/pandas-python-roadmap\/\">Pandas roadmap<\/a> covers the basics. Every output shown below comes from actually running the code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Simple linear regression example<\/h3>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"import numpy as np\nfrom sklearn.linear_model import LinearRegression\n\n# Hours studied vs marks scored (out of 100)\nhours = np.array([1, 2, 3, 4, 5, 6, 7, 8]).reshape(-1, 1)\nmarks = np.array([35, 41, 50, 54, 62, 68, 75, 80])\n\nmodel = LinearRegression()\nmodel.fit(hours, marks)\n\nprint(&quot;Slope (m):&quot;, round(model.coef_[0], 2))\nprint(&quot;Intercept (b):&quot;, round(model.intercept_, 2))\nprint(&quot;Predicted marks for 5.5 hours:&quot;, round(model.predict([[5.5]])[0], 1))\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> numpy <\/span><span style=\"color: #C586C0\">as<\/span><span style=\"color: #D4D4D4\"> np<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">from<\/span><span style=\"color: #D4D4D4\"> sklearn.linear_model <\/span><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> LinearRegression<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"># Hours studied vs marks scored (out of 100)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">hours = np.array([<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">]).reshape(-<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">marks = np.array([<\/span><span style=\"color: #B5CEA8\">35<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">41<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">50<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">54<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">62<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">68<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">75<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">80<\/span><span style=\"color: #D4D4D4\">])<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">model = LinearRegression()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">model.fit(hours, marks)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;Slope (m):&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">round<\/span><span style=\"color: #D4D4D4\">(model.coef_[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;Intercept (b):&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">round<\/span><span style=\"color: #D4D4D4\">(model.intercept_, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;Predicted marks for 5.5 hours:&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">round<\/span><span style=\"color: #D4D4D4\">(model.predict([[<\/span><span style=\"color: #B5CEA8\">5.5<\/span><span style=\"color: #D4D4D4\">]])[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Output:<\/strong><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">Slope (m): 6.51<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Intercept (b): 28.82<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Predicted marks for 5.5 hours: 64.6<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><code>reshape(-1, 1)<\/code> is needed because scikit-learn expects features as a 2D table, even when there is only one column. The model learned a slope of 6.51 marks per hour.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Multiple linear regression with a train and test split<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This example creates 200 sample flats, trains on 80% of them and tests on the remaining 20%.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"import numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.linear_model import LinearRegression\nfrom sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score\n\n# Build a sample dataset of 200 flats\nrng = np.random.default_rng(42)\nn = 200\ndf = pd.DataFrame({\n    &quot;size_sqft&quot;: rng.integers(450, 2000, n),\n    &quot;age_years&quot;: rng.integers(0, 30, n),\n    &quot;metro_km&quot;: rng.uniform(0.2, 12, n).round(1),\n})\n# Price in lakh rupees, plus some random noise\ndf[&quot;price_lakh&quot;] = (0.055 * df[&quot;size_sqft&quot;] - 0.6 * df[&quot;age_years&quot;]\n                    - 1.8 * df[&quot;metro_km&quot;] + 15 + rng.normal(0, 6, n)).round(1)\n\nX = df[[&quot;size_sqft&quot;, &quot;age_years&quot;, &quot;metro_km&quot;]]\ny = df[&quot;price_lakh&quot;]\nX_train, X_test, y_train, y_test = train_test_split(\n    X, y, test_size=0.2, random_state=42)\n\nmodel = LinearRegression().fit(X_train, y_train)\npred = model.predict(X_test)\n\nfor name, coef in zip(X.columns, model.coef_):\n    print(f&quot;{name}: {coef:.3f}&quot;)\nprint(&quot;Intercept:&quot;, round(model.intercept_, 2))\nprint(&quot;MAE :&quot;, round(mean_absolute_error(y_test, pred), 2))\nprint(&quot;RMSE:&quot;, round(mean_squared_error(y_test, pred) ** 0.5, 2))\nprint(&quot;R2  :&quot;, round(r2_score(y_test, pred), 3))\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> numpy <\/span><span style=\"color: #C586C0\">as<\/span><span style=\"color: #D4D4D4\"> np<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> pandas <\/span><span style=\"color: #C586C0\">as<\/span><span style=\"color: #D4D4D4\"> pd<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">from<\/span><span style=\"color: #D4D4D4\"> sklearn.model_selection <\/span><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> train_test_split<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">from<\/span><span style=\"color: #D4D4D4\"> sklearn.linear_model <\/span><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> LinearRegression<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">from<\/span><span style=\"color: #D4D4D4\"> sklearn.metrics <\/span><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> mean_absolute_error, mean_squared_error, r2_score<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"># Build a sample dataset of 200 flats<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">rng = np.random.default_rng(<\/span><span style=\"color: #B5CEA8\">42<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">n = <\/span><span style=\"color: #B5CEA8\">200<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">df = pd.DataFrame({<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #CE9178\">&quot;size_sqft&quot;<\/span><span style=\"color: #D4D4D4\">: rng.integers(<\/span><span style=\"color: #B5CEA8\">450<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">2000<\/span><span style=\"color: #D4D4D4\">, n),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #CE9178\">&quot;age_years&quot;<\/span><span style=\"color: #D4D4D4\">: rng.integers(<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">30<\/span><span style=\"color: #D4D4D4\">, n),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #CE9178\">&quot;metro_km&quot;<\/span><span style=\"color: #D4D4D4\">: rng.uniform(<\/span><span style=\"color: #B5CEA8\">0.2<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">12<\/span><span style=\"color: #D4D4D4\">, n).round(<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">})<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"># Price in lakh rupees, plus some random noise<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">df[<\/span><span style=\"color: #CE9178\">&quot;price_lakh&quot;<\/span><span style=\"color: #D4D4D4\">] = (<\/span><span style=\"color: #B5CEA8\">0.055<\/span><span style=\"color: #D4D4D4\"> * df[<\/span><span style=\"color: #CE9178\">&quot;size_sqft&quot;<\/span><span style=\"color: #D4D4D4\">] - <\/span><span style=\"color: #B5CEA8\">0.6<\/span><span style=\"color: #D4D4D4\"> * df[<\/span><span style=\"color: #CE9178\">&quot;age_years&quot;<\/span><span style=\"color: #D4D4D4\">]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    - <\/span><span style=\"color: #B5CEA8\">1.8<\/span><span style=\"color: #D4D4D4\"> * df[<\/span><span style=\"color: #CE9178\">&quot;metro_km&quot;<\/span><span style=\"color: #D4D4D4\">] + <\/span><span style=\"color: #B5CEA8\">15<\/span><span style=\"color: #D4D4D4\"> + rng.normal(<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">, n)).round(<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">X = df[[<\/span><span style=\"color: #CE9178\">&quot;size_sqft&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;age_years&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;metro_km&quot;<\/span><span style=\"color: #D4D4D4\">]]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">y = df[<\/span><span style=\"color: #CE9178\">&quot;price_lakh&quot;<\/span><span style=\"color: #D4D4D4\">]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">X_train, X_test, y_train, y_test = train_test_split(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    X, y, <\/span><span style=\"color: #9CDCFE\">test_size<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #B5CEA8\">0.2<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">random_state<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #B5CEA8\">42<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">model = LinearRegression().fit(X_train, y_train)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">pred = model.predict(X_test)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> name, coef <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">zip<\/span><span style=\"color: #D4D4D4\">(X.columns, model.coef_):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">f<\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #569CD6\">{<\/span><span style=\"color: #D4D4D4\">name<\/span><span style=\"color: #569CD6\">}<\/span><span style=\"color: #CE9178\">: <\/span><span style=\"color: #569CD6\">{<\/span><span style=\"color: #D4D4D4\">coef<\/span><span style=\"color: #569CD6\">:.3f}<\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;Intercept:&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">round<\/span><span style=\"color: #D4D4D4\">(model.intercept_, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;MAE :&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">round<\/span><span style=\"color: #D4D4D4\">(mean_absolute_error(y_test, pred), <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;RMSE:&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">round<\/span><span style=\"color: #D4D4D4\">(mean_squared_error(y_test, pred) ** <\/span><span style=\"color: #B5CEA8\">0.5<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;R2  :&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">round<\/span><span style=\"color: #D4D4D4\">(r2_score(y_test, pred), <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Output:<\/strong><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">size_sqft: 0.055<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">age_years: -0.636<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">metro_km: -1.746<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Intercept: 14.23<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">MAE : 5.26<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">RMSE: 6.5<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">R2  : 0.933<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The model recovered weights very close to the ones used to create the data (0.055 per sq ft, about \u22120.6 per year of age, about \u22121.8 per km from the metro), and it explains about 93% of the variation in prices on unseen flats.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Linear regression from scratch with NumPy<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Writing it yourself is the best way to understand what <code>model.fit()<\/code> does. This is the same gradient descent you watched earlier, in about ten lines:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"import numpy as np\n\nx = np.array([1, 2, 3, 4, 5, 6, 7, 8], dtype=float)\ny = np.array([35, 41, 50, 54, 62, 68, 75, 80], dtype=float)\n\nm, b = 0.0, 0.0      # start with a flat line\nlr = 0.01            # learning rate\n\nfor step in range(5000):\n    pred = m * x + b\n    error = pred - y\n    dm = 2 * np.mean(error * x)   # gradient of MSE with respect to m\n    db = 2 * np.mean(error)       # gradient of MSE with respect to b\n    m -= lr * dm\n    b -= lr * db\n\nprint(&quot;m =&quot;, round(m, 2), &quot; b =&quot;, round(b, 2))\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> numpy <\/span><span style=\"color: #C586C0\">as<\/span><span style=\"color: #D4D4D4\"> np<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">x = np.array([<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">5<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">6<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">7<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">8<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">dtype<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4EC9B0\">float<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">y = np.array([<\/span><span style=\"color: #B5CEA8\">35<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">41<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">50<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">54<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">62<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">68<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">75<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">80<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">dtype<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4EC9B0\">float<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">m, b = <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #6A9955\"># start with a flat line<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">lr = <\/span><span style=\"color: #B5CEA8\">0.01<\/span><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #6A9955\"># learning rate<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> step <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">range<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #B5CEA8\">5000<\/span><span style=\"color: #D4D4D4\">):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    pred = m * x + b<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    error = pred - y<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    dm = <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> * np.mean(error * x)   <\/span><span style=\"color: #6A9955\"># gradient of MSE with respect to m<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    db = <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> * np.mean(error)       <\/span><span style=\"color: #6A9955\"># gradient of MSE with respect to b<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    m -= lr * dm<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    b -= lr * db<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">print<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;m =&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">round<\/span><span style=\"color: #D4D4D4\">(m, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">), <\/span><span style=\"color: #CE9178\">&quot; b =&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">round<\/span><span style=\"color: #D4D4D4\">(b, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Output:<\/strong><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">m = 6.51  b = 28.82<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">It lands on exactly the same slope and intercept as scikit-learn. A good exercise is to change <code>lr<\/code> to 0.05 and see the numbers explode, just like in the demo above.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-pros-cons\">Advantages and limitations<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>Easy to explain.<\/strong> Each coefficient has a clear meaning, which matters in finance, healthcare and anywhere decisions need justification.<\/li>\n\n\n<li><strong>Fast.<\/strong> It trains in milliseconds even on large datasets.<\/li>\n\n\n<li><strong>A strong baseline.<\/strong> Always try it before reaching for complex models. Sometimes it is all you need.<\/li>\n\n\n<li><strong>Limited to straight-line patterns<\/strong> unless you add polynomial or interaction features.<\/li>\n\n\n<li><strong>Sensitive to outliers,<\/strong> as the playground showed. Ridge, Lasso or robust regression can help.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-quiz\">Test yourself<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Six quick questions. If you get five or more right, you are ready to use linear regression on a real dataset.<\/p>\n\n\n\n<div class=\"cdai cd-lr-quiz\"><span class=\"cd-tag\">Quiz<\/span><h4 class=\"cd-h\">Linear regression quiz<\/h4><div class=\"cd-lrq-body\"><p class=\"cd-sub\">Takes about two minutes.<\/p><button type=\"button\" class=\"cd-btn cd-primary cd-lrq-start\">Start the quiz<\/button><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-faq\">Frequently asked questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">What is linear regression in simple words?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Linear regression finds the straight line that best fits your data, then uses it to predict a number for new inputs. For example, it can learn how marks change with hours studied and predict the marks for a student who studies 6 hours.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is the formula for linear regression?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Simple linear regression uses y = mx + b. The slope is m = \u03a3(x \u2212 x\u0304)(y \u2212 \u0233) \u00f7 \u03a3(x \u2212 x\u0304)\u00b2, and the intercept is b = \u0233 \u2212 m \u00d7 x\u0304, where x\u0304 and \u0233 are the averages of x and y. Multiple linear regression extends this to y = b\u2080 + b\u2081x\u2081 + b\u2082x\u2082 + \u2026 + b\u2099x\u2099.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is the difference between simple and multiple linear regression?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Simple linear regression uses one input feature and fits a line. Multiple linear regression uses two or more features and fits a plane or hyperplane, with a separate coefficient for each feature.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Is linear regression supervised or unsupervised learning?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It is supervised learning, because the model learns from examples where the correct answer (the target value) is already known.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is the difference between linear and logistic regression?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Linear regression predicts a continuous number, such as a price. Logistic regression predicts the probability of a class, such as pass or fail, using an S-shaped sigmoid curve that keeps outputs between 0 and 1.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What are the assumptions of linear regression?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Linearity, independence of observations, normally distributed residuals, equal variance of residuals (homoscedasticity), and, for multiple regression, no strong multicollinearity between features.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">When should I not use linear regression?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Avoid it when the relationship is clearly curved, when the target is a category, or when the data has extreme outliers you cannot explain. In those cases try polynomial regression, logistic regression, or tree-based models.<\/p>\n\n\n\n<script type=\"application\/ld+json\">{\"@context\": \"https:\/\/schema.org\", \"@type\": \"FAQPage\", \"mainEntity\": [{\"@type\": \"Question\", \"name\": \"What is linear regression in simple words?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Linear regression finds the straight line that best fits your data, then uses it to predict a number for new inputs. For example, it can learn how marks change with hours studied and predict the marks for a student who studies 6 hours.\"}}, {\"@type\": \"Question\", \"name\": \"What is the formula for linear regression?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Simple linear regression uses y = mx + b. The slope is m = \u03a3(x \u2212 x\u0304)(y \u2212 \u0233) \u00f7 \u03a3(x \u2212 x\u0304)\u00b2, and the intercept is b = \u0233 \u2212 m \u00d7 x\u0304, where x\u0304 and \u0233 are the averages of x and y. Multiple linear regression extends this to y = b\u2080 + b\u2081x\u2081 + b\u2082x\u2082 + \u2026 + b\u2099x\u2099.\"}}, {\"@type\": \"Question\", \"name\": \"What is the difference between simple and multiple linear regression?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Simple linear regression uses one input feature and fits a line. Multiple linear regression uses two or more features and fits a plane or hyperplane, with a separate coefficient for each feature.\"}}, {\"@type\": \"Question\", \"name\": \"Is linear regression supervised or unsupervised learning?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"It is supervised learning, because the model learns from examples where the correct answer (the target value) is already known.\"}}, {\"@type\": \"Question\", \"name\": \"What is the difference between linear and logistic regression?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Linear regression predicts a continuous number, such as a price. Logistic regression predicts the probability of a class, such as pass or fail, using an S-shaped sigmoid curve that keeps outputs between 0 and 1.\"}}, {\"@type\": \"Question\", \"name\": \"What are the assumptions of linear regression?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Linearity, independence of observations, normally distributed residuals, equal variance of residuals (homoscedasticity), and, for multiple regression, no strong multicollinearity between features.\"}}, {\"@type\": \"Question\", \"name\": \"When should I not use linear regression?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Avoid it when the relationship is clearly curved, when the target is a category, or when the data has extreme outliers you cannot explain. In those cases try polynomial regression, logistic regression, or tree-based models.\"}}]}<\/script>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cd-next\">What to learn next<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now that the line makes sense, the natural next steps are <a href=\"https:\/\/codeanddebug.in\/blog\/logistic-regression-in-machine-learning\/\">logistic regression<\/a> for classification, then decision trees and random forests. Our <a href=\"https:\/\/codeanddebug.in\/blog\/how-to-learn-ai-ml-from-scratch-roadmap\/\">interactive AI and ML roadmap<\/a> shows the full path, and you can track which skills you have already ticked off.<\/p>\n\n\n\n<script src=\"data:text\/javascript;base64,KGZ1bmN0aW9uKCl7CiJ1c2Ugc3RyaWN0IjsKdmFyIFJNPXdpbmRvdy5tYXRjaE1lZGlhJiZ3aW5kb3cubWF0Y2hNZWRpYSgiKHByZWZlcnMtcmVkdWNlZC1tb3Rpb246IHJlZHVjZSkiKS5tYXRjaGVzOwpmdW5jdGlvbiAkKHMscil7cmV0dXJuIChyfHxkb2N1bWVudCkucXVlcnlTZWxlY3RvcihzKX0KZnVuY3Rpb24gJCQocyxyKXtyZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoKHJ8fGRvY3VtZW50KS5xdWVyeVNlbGVjdG9yQWxsKHMpKX0KZnVuY3Rpb24gY3NzKGVsLG4pe3JldHVybiBnZXRDb21wdXRlZFN0eWxlKGVsKS5nZXRQcm9wZXJ0eVZhbHVlKG4pLnRyaW0oKX0KZnVuY3Rpb24gY2FudmFzRm9yKGN2LGgpe3ZhciBkcHI9TWF0aC5taW4od2luZG93LmRldmljZVBpeGVsUmF0aW98fDEsMiksdz1jdi5jbGllbnRXaWR0aHx8NjAwO2N2LndpZHRoPXcqZHByO2N2LmhlaWdodD1oKmRwcjtjdi5zdHlsZS5oZWlnaHQ9aCsicHgiO3ZhciBjPWN2LmdldENvbnRleHQoIjJkIik7Yy5zZXRUcmFuc2Zvcm0oZHByLDAsMCxkcHIsMCwwKTtyZXR1cm4ge2M6Yyx3OncsaDpofX0KZnVuY3Rpb24gY29sb3JzKGVsKXtyZXR1cm4ge2luazpjc3MoZWwsIi0tY2QtaW5rIiksbXV0OmNzcyhlbCwiLS1jZC1tdXRlZCIpLGxpbmU6Y3NzKGVsLCItLWNkLWxpbmUiKSxicjpjc3MoZWwsIi0tY2QtYnJhbmQiKSxiYWQ6Y3NzKGVsLCItLWNkLWJhZCIpLGdvb2Q6Y3NzKGVsLCItLWNkLWdvb2QiKSxjYXJkOmNzcyhlbCwiLS1jZC1jYXJkIil9fQpmdW5jdGlvbiBmaXQocHRzKXt2YXIgbj1wdHMubGVuZ3RoO2lmKG48MilyZXR1cm4gbnVsbDt2YXIgbXg9MCxteT0wO3B0cy5mb3JFYWNoKGZ1bmN0aW9uKHApe214Kz1wWzBdO215Kz1wWzFdfSk7bXgvPW47bXkvPW47dmFyIHN4eT0wLHN4eD0wLHN5eT0wO3B0cy5mb3JFYWNoKGZ1bmN0aW9uKHApe3N4eSs9KHBbMF0tbXgpKihwWzFdLW15KTtzeHgrPShwWzBdLW14KSoocFswXS1teCk7c3l5Kz0ocFsxXS1teSkqKHBbMV0tbXkpfSk7aWYoc3h4PT09MClyZXR1cm4gbnVsbDt2YXIgbT1zeHkvc3h4LGI9bXktbSpteCxzc2U9MDtwdHMuZm9yRWFjaChmdW5jdGlvbihwKXt2YXIgZT1wWzFdLShtKnBbMF0rYik7c3NlKz1lKmV9KTtyZXR1cm4ge206bSxiOmIsbXNlOnNzZS9uLHIyOnN5eT8xLXNzZS9zeXk6MX19CmZ1bmN0aW9uIGF4ZXMoYyxTLG8pe2Muc3Ryb2tlU3R5bGU9by5jb2wubGluZTtjLmxpbmVXaWR0aD0xO2MuZm9udD0iMTFweCBJbnRlcixzYW5zLXNlcmlmIjtjLmZpbGxTdHlsZT1vLmNvbC5tdXQ7CiBvLnh0LmZvckVhY2goZnVuY3Rpb24odil7dmFyIHg9by5zeCh2KTtjLmdsb2JhbEFscGhhPS42O2MuYmVnaW5QYXRoKCk7Yy5tb3ZlVG8oeCxvLnRvcCk7Yy5saW5lVG8oeCxTLmgtby5ib3QpO2Muc3Ryb2tlKCk7Yy5nbG9iYWxBbHBoYT0xO2MuZmlsbFRleHQodix4LTYsUy5oLW8uYm90KzE0KX0pOwogby55dC5mb3JFYWNoKGZ1bmN0aW9uKHYpe3ZhciB5PW8uc3kodik7Yy5nbG9iYWxBbHBoYT0uNjtjLmJlZ2luUGF0aCgpO2MubW92ZVRvKG8ubGVmdCx5KTtjLmxpbmVUbyhTLnctby5yaWdodCx5KTtjLnN0cm9rZSgpO2MuZ2xvYmFsQWxwaGE9MTtjLmZpbGxUZXh0KHYsNCx5KzQpfSk7CiBpZihvLnhsKXtjLmZpbGxUZXh0KG8ueGwsUy53LW8ucmlnaHQtYy5tZWFzdXJlVGV4dChvLnhsKS53aWR0aCxTLmgtNCl9aWYoby55bCl7Yy5maWxsVGV4dChvLnlsLG8ubGVmdCs0LG8udG9wLTYpfX0KZnVuY3Rpb24gZjEodixkKXtyZXR1cm4gKE1hdGgucm91bmQodipNYXRoLnBvdygxMCxkKSkvTWF0aC5wb3coMTAsZCkpLnRvRml4ZWQoZCl9CmZ1bmN0aW9uIHJuZyhzZWVkKXt2YXIgcz1zZWVkO3JldHVybiBmdW5jdGlvbigpe3M9KHMqMTY2NDUyNSsxMDEzOTA0MjIzKSU0Mjk0OTY3Mjk2O3JldHVybiBzLzQyOTQ5NjcyOTZ9fQpmdW5jdGlvbiBnYXVzcyhyKXt2YXIgdT0wLHY9MDt3aGlsZSh1PT09MCl1PXIoKTt3aGlsZSh2PT09MCl2PXIoKTtyZXR1cm4gTWF0aC5zcXJ0KC0yKk1hdGgubG9nKHUpKSpNYXRoLmNvcygyKk1hdGguUEkqdil9CnZhciBCQVNFPVtbMSwzNV0sWzIsNDFdLFszLDUwXSxbNCw1NF0sWzUsNjJdLFs2LDY4XSxbNyw3NV0sWzgsODBdXTsKCi8qIDEuIFBsYXlncm91bmQgKi8KJCQoIi5jZGFpLmNkLWxyLXBsYXkiKS5mb3JFYWNoKGZ1bmN0aW9uKGJveCl7CiB2YXIgY3Y9JCgiY2FudmFzIixib3gpLFMscHRzPUJBU0UubWFwKGZ1bmN0aW9uKHApe3JldHVybiBwLnNsaWNlKCl9KSxkcmFnPS0xLHNob3dFcnI9dHJ1ZSxjb2w7CiB2YXIgTD0zNCxSPTEyLFQ9MjIsQm09MzA7CiBmdW5jdGlvbiBzeCh2KXtyZXR1cm4gTCt2LzEwKihTLnctTC1SKX1mdW5jdGlvbiBzeSh2KXtyZXR1cm4gUy5oLUJtLXYvMTAwKihTLmgtVC1CbSl9CiBmdW5jdGlvbiBpeChweCl7cmV0dXJuIChweC1MKS8oUy53LUwtUikqMTB9ZnVuY3Rpb24gaXkocHkpe3JldHVybiAoUy5oLUJtLXB5KS8oUy5oLVQtQm0pKjEwMH0KIGZ1bmN0aW9uIGRyYXcoKXtpZighUylTPWNhbnZhc0ZvcihjdiwzMDApO2NvbD1jb2xvcnMoYm94KTt2YXIgYz1TLmM7Yy5jbGVhclJlY3QoMCwwLFMudyxTLmgpOwogIGF4ZXMoYyxTLHtjb2w6Y29sLHN4OnN4LHN5OnN5LHh0OlswLDIsNCw2LDgsMTBdLHl0OlswLDIwLDQwLDYwLDgwLDEwMF0sbGVmdDpMLHJpZ2h0OlIsdG9wOlQsYm90OkJtLHhsOiJob3VycyBzdHVkaWVkIix5bDoibWFya3MifSk7CiAgdmFyIEY9Zml0KHB0cyk7CiAgaWYoRil7aWYoc2hvd0Vycil7Yy5zdHJva2VTdHlsZT1jb2wuYmFkO2MuZ2xvYmFsQWxwaGE9LjU1O2MubGluZVdpZHRoPTEuNTtwdHMuZm9yRWFjaChmdW5jdGlvbihwKXtjLmJlZ2luUGF0aCgpO2MubW92ZVRvKHN4KHBbMF0pLHN5KHBbMV0pKTtjLmxpbmVUbyhzeChwWzBdKSxzeShGLm0qcFswXStGLmIpKTtjLnN0cm9rZSgpfSk7Yy5nbG9iYWxBbHBoYT0xfQogICBjLnNhdmUoKTtjLmJlZ2luUGF0aCgpO2MucmVjdChMLFQsUy53LUwtUixTLmgtVC1CbSk7Yy5jbGlwKCk7Yy5zdHJva2VTdHlsZT1jb2wuYnI7Yy5saW5lV2lkdGg9MztjLmJlZ2luUGF0aCgpO2MubW92ZVRvKHN4KDApLHN5KEYuYikpO2MubGluZVRvKHN4KDEwKSxzeShGLm0qMTArRi5iKSk7Yy5zdHJva2UoKTtjLnJlc3RvcmUoKX0KICBwdHMuZm9yRWFjaChmdW5jdGlvbihwLGkpe2MuZmlsbFN0eWxlPWk9PT1kcmFnP2NvbC5icjpjb2wuaW5rO2MuYmVnaW5QYXRoKCk7Yy5hcmMoc3gocFswXSksc3kocFsxXSksaT09PWRyYWc\/ODo2LDAsNyk7Yy5maWxsKCl9KTsKICAkKCIuY2QtcGxheS1lcSIsYm94KS50ZXh0Q29udGVudD1GPyJtYXJrcyA9ICIrZjEoRi5tLDIpKyIgw5cgaG91cnMgKyAiK2YxKEYuYiwyKToiQWRkIGF0IGxlYXN0IDIgcG9pbnRzIjsKICAkKCIuY2QtcGxheS1yMiIsYm94KS50ZXh0Q29udGVudD1GP2YxKEYucjIsMyk6Ii0iOyQoIi5jZC1wbGF5LW1zZSIsYm94KS50ZXh0Q29udGVudD1GP2YxKEYubXNlLDEpOiItIjskKCIuY2QtcGxheS1uIixib3gpLnRleHRDb250ZW50PXB0cy5sZW5ndGh9CiBmdW5jdGlvbiBwb3MoZSl7dmFyIHI9Y3YuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7cmV0dXJuIFtlLmNsaWVudFgtci5sZWZ0LGUuY2xpZW50WS1yLnRvcF19CiBjdi5hZGRFdmVudExpc3RlbmVyKCJwb2ludGVyZG93biIsZnVuY3Rpb24oZSl7dmFyIHA9cG9zKGUpLGJlc3Q9LTEsYmQ9MTg7cHRzLmZvckVhY2goZnVuY3Rpb24ocSxpKXt2YXIgZD1NYXRoLmh5cG90KHN4KHFbMF0pLXBbMF0sc3kocVsxXSktcFsxXSk7aWYoZDxiZCl7YmQ9ZDtiZXN0PWl9fSk7CiAgaWYoYmVzdDwwKXt2YXIgbng9TWF0aC5tYXgoMCxNYXRoLm1pbigxMCxpeChwWzBdKSkpLG55PU1hdGgubWF4KDAsTWF0aC5taW4oMTAwLGl5KHBbMV0pKSk7cHRzLnB1c2goW254LG55XSk7YmVzdD1wdHMubGVuZ3RoLTF9CiAgZHJhZz1iZXN0O2N2LnNldFBvaW50ZXJDYXB0dXJlKGUucG9pbnRlcklkKTtkcmF3KCk7ZS5wcmV2ZW50RGVmYXVsdCgpfSk7CiBjdi5hZGRFdmVudExpc3RlbmVyKCJwb2ludGVybW92ZSIsZnVuY3Rpb24oZSl7aWYoZHJhZzwwKXJldHVybjt2YXIgcD1wb3MoZSk7cHRzW2RyYWddPVtNYXRoLm1heCgwLE1hdGgubWluKDEwLGl4KHBbMF0pKSksTWF0aC5tYXgoMCxNYXRoLm1pbigxMDAsaXkocFsxXSkpKV07ZHJhdygpfSk7CiBmdW5jdGlvbiB1cCgpe2RyYWc9LTE7ZHJhdygpfWN2LmFkZEV2ZW50TGlzdGVuZXIoInBvaW50ZXJ1cCIsdXApO2N2LmFkZEV2ZW50TGlzdGVuZXIoInBvaW50ZXJjYW5jZWwiLHVwKTsKICQoIi5jZC1wbGF5LW91dGxpZXIiLGJveCkuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLGZ1bmN0aW9uKCl7cHRzLnB1c2goWzkuNSwyMF0pO2RyYXcoKX0pOwogJCgiLmNkLXBsYXktdW5kbyIsYm94KS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtpZihwdHMubGVuZ3RoKXB0cy5wb3AoKTtkcmF3KCl9KTsKICQoIi5jZC1wbGF5LXJlc2V0Iixib3gpLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe3B0cz1CQVNFLm1hcChmdW5jdGlvbihwKXtyZXR1cm4gcC5zbGljZSgpfSk7ZHJhdygpfSk7CiAkKCIuY2QtcGxheS1lcnIiLGJveCkuYWRkRXZlbnRMaXN0ZW5lcigiY2hhbmdlIixmdW5jdGlvbihlKXtzaG93RXJyPWUudGFyZ2V0LmNoZWNrZWQ7ZHJhdygpfSk7CiB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigicmVzaXplIixmdW5jdGlvbigpe1M9bnVsbDtkcmF3KCl9KTtkcmF3KCk7Cn0pOwoKLyogMi4gRm9ybXVsYSBjYWxjdWxhdG9yICovCiQkKCIuY2RhaS5jZC1sci1jYWxjIikuZm9yRWFjaChmdW5jdGlvbihib3gpewogdmFyIHJvd3M9JCQoInRib2R5IHRyIixib3gpOwogZnVuY3Rpb24gY2FsYygpe3ZhciB4cz1bXSx5cz1bXTtyb3dzLmZvckVhY2goZnVuY3Rpb24ocil7dmFyIGk9JCQoImlucHV0IixyKTt4cy5wdXNoKHBhcnNlRmxvYXQoaVswXS52YWx1ZSkpO3lzLnB1c2gocGFyc2VGbG9hdChpWzFdLnZhbHVlKSl9KTsKICBpZih4cy5jb25jYXQoeXMpLnNvbWUoaXNOYU4pKXskKCIuY2QtY2FsYy1yZXMiLGJveCkuaW5uZXJIVE1MPSI8ZGl2PkZpbGwgZXZlcnkgY2VsbCB3aXRoIGEgbnVtYmVyLjwvZGl2PiI7cmV0dXJufQogIHZhciBuPXhzLmxlbmd0aCxteD14cy5yZWR1Y2UoZnVuY3Rpb24oYSxiKXtyZXR1cm4gYStifSwwKS9uLG15PXlzLnJlZHVjZShmdW5jdGlvbihhLGIpe3JldHVybiBhK2J9LDApL24sc3h5PTAsc3h4PTA7CiAgcm93cy5mb3JFYWNoKGZ1bmN0aW9uKHIsayl7dmFyIGR4PXhzW2tdLW14LGR5PXlzW2tdLW15O3N4eSs9ZHgqZHk7c3h4Kz1keCpkeDt2YXIgdD0kJCgidGQiLHIpO3RbMl0udGV4dENvbnRlbnQ9ZjEoZHgsMik7dFszXS50ZXh0Q29udGVudD1mMShkeSwyKTt0WzRdLnRleHRDb250ZW50PWYxKGR4KmR5LDIpO3RbNV0udGV4dENvbnRlbnQ9ZjEoZHgqZHgsMil9KTsKICAkKCIuY2Qtc3VtLXh5Iixib3gpLnRleHRDb250ZW50PWYxKHN4eSwyKTskKCIuY2Qtc3VtLXh4Iixib3gpLnRleHRDb250ZW50PWYxKHN4eCwyKTsKICBpZihzeHg9PT0wKXskKCIuY2QtY2FsYy1yZXMiLGJveCkuaW5uZXJIVE1MPSI8ZGl2PkFsbCB4IHZhbHVlcyBhcmUgdGhlIHNhbWUsIHNvIG5vIGxpbmUgY2FuIGJlIGZpdHRlZC4gQ2hhbmdlIG9uZSBvZiB0aGVtLjwvZGl2PiI7cmV0dXJufQogIHZhciBtPXN4eS9zeHgsYj1teS1tKm14LHE9cGFyc2VGbG9hdCgkKCIuY2QtY2FsYy1xIixib3gpLnZhbHVlKXx8MDsKICAkKCIuY2QtY2FsYy1yZXMiLGJveCkuaW5uZXJIVE1MPSI8ZGl2PjxiPlN0ZXAgMS48L2I+IEF2ZXJhZ2VzOiA8Y29kZT54zIQgPSAiK2YxKG14LDIpKyI8L2NvZGU+LCA8Y29kZT7IsyA9ICIrZjEobXksMikrIjwvY29kZT48L2Rpdj4iKwogICAiPGRpdj48Yj5TdGVwIDIuPC9iPiBTbG9wZTogPGNvZGU+bSA9IM6jKHjiiJJ4zIQpKHniiJLIsykgw7cgzqMoeOKIknjMhCnCsiA9ICIrZjEoc3h5LDIpKyIgw7cgIitmMShzeHgsMikrIiA9ICIrZjEobSwzKSsiPC9jb2RlPjwvZGl2PiIrCiAgICI8ZGl2PjxiPlN0ZXAgMy48L2I+IEludGVyY2VwdDogPGNvZGU+YiA9IMizIOKIkiBtwrd4zIQgPSAiK2YxKG15LDIpKyIg4oiSICIrZjEobSwzKSsiIMOXICIrZjEobXgsMikrIiA9ICIrZjEoYiwzKSsiPC9jb2RlPjwvZGl2PiIrCiAgICI8ZGl2PjxiPllvdXIgbGluZTo8L2I+IDxzcGFuIGNsYXNzPVwiY2QtZXFcIj55ID0gIitmMShtLDMpKyJ4ICsgIitmMShiLDMpKyI8L3NwYW4+PC9kaXY+IisKICAgIjxkaXY+PGI+UHJlZGljdGlvbjwvYj4gZm9yIHggPSAiK3ErIjogPGNvZGU+IitmMShtLDMpKyIgw5cgIitxKyIgKyAiK2YxKGIsMykrIiA9ICIrZjEobSpxK2IsMikrIjwvY29kZT48L2Rpdj4ifQogJCQoImlucHV0Iixib3gpLmZvckVhY2goZnVuY3Rpb24oaSl7aS5hZGRFdmVudExpc3RlbmVyKCJpbnB1dCIsY2FsYyl9KTtjYWxjKCk7Cn0pOwoKLyogMy4gR3JhZGllbnQgZGVzY2VudCBvbiBtIGFuZCBiICovCiQkKCIuY2RhaS5jZC1sci1nZCIpLmZvckVhY2goZnVuY3Rpb24oYm94KXsKIHZhciBjdnM9JCQoImNhbnZhcyIsYm94KSxBLEJjLG09MCxiPTAsbHI9MC4wMSxzdGVwPTAsaGlzdD1bXSx0aW1lcj1udWxsLGNvbDsKIHZhciB4cz1CQVNFLm1hcChmdW5jdGlvbihwKXtyZXR1cm4gcFswXX0pLHlzPUJBU0UubWFwKGZ1bmN0aW9uKHApe3JldHVybiBwWzFdfSk7CiBmdW5jdGlvbiBtc2UoKXt2YXIgcz0wO2Zvcih2YXIgaT0wO2k8eHMubGVuZ3RoO2krKyl7dmFyIGU9bSp4c1tpXStiLXlzW2ldO3MrPWUqZX1yZXR1cm4gcy94cy5sZW5ndGh9CiBmdW5jdGlvbiBvbmUoKXt2YXIgZG09MCxkYj0wLG49eHMubGVuZ3RoO2Zvcih2YXIgaT0wO2k8bjtpKyspe3ZhciBlPW0qeHNbaV0rYi15c1tpXTtkbSs9MiplKnhzW2ldL247ZGIrPTIqZS9ufW0tPWxyKmRtO2ItPWxyKmRiO3N0ZXArKztoaXN0LnB1c2gobXNlKCkpfQogZnVuY3Rpb24gZHJhdygpe2lmKCFBKXtBPWNhbnZhc0ZvcihjdnNbMF0sMjMwKTtCYz1jYW52YXNGb3IoY3ZzWzFdLDIzMCl9Y29sPWNvbG9ycyhib3gpOwogIHZhciBjPUEuYyxMPTMwLFI9MTAsVD0xOCxCbT0yNjtmdW5jdGlvbiBzeCh2KXtyZXR1cm4gTCt2LzEwKihBLnctTC1SKX1mdW5jdGlvbiBzeSh2KXtyZXR1cm4gQS5oLUJtLXYvMTAwKihBLmgtVC1CbSl9CiAgYy5jbGVhclJlY3QoMCwwLEEudyxBLmgpO2F4ZXMoYyxBLHtjb2w6Y29sLHN4OnN4LHN5OnN5LHh0OlswLDUsMTBdLHl0OlswLDUwLDEwMF0sbGVmdDpMLHJpZ2h0OlIsdG9wOlQsYm90OkJtLHhsOiJob3VycyIseWw6Im1hcmtzIn0pOwogIGMuc2F2ZSgpO2MuYmVnaW5QYXRoKCk7Yy5yZWN0KEwsVCxBLnctTC1SLEEuaC1ULUJtKTtjLmNsaXAoKTtjLnN0cm9rZVN0eWxlPWNvbC5icjtjLmxpbmVXaWR0aD0zO2MuYmVnaW5QYXRoKCk7Yy5tb3ZlVG8oc3goMCksc3koYikpO2MubGluZVRvKHN4KDEwKSxzeShtKjEwK2IpKTtjLnN0cm9rZSgpO2MucmVzdG9yZSgpOwogIGMuZmlsbFN0eWxlPWNvbC5pbms7QkFTRS5mb3JFYWNoKGZ1bmN0aW9uKHApe2MuYmVnaW5QYXRoKCk7Yy5hcmMoc3gocFswXSksc3kocFsxXSksNSwwLDcpO2MuZmlsbCgpfSk7CiAgdmFyIGQ9QmMuYztkLmNsZWFyUmVjdCgwLDAsQmMudyxCYy5oKTt2YXIgaD1oaXN0Lmxlbmd0aD9oaXN0Olttc2UoKV0sbG89TWF0aC5sb2cxMCgwLjUpLGhpPU1hdGgubG9nMTAoTWF0aC5tYXgoNDAwMCxoWzBdKSksTj1NYXRoLm1heCg1MCxoLmxlbmd0aCk7CiAgZnVuY3Rpb24gcHgoaSl7cmV0dXJuIDM0K2kvTiooQmMudy00NCl9ZnVuY3Rpb24gcHkodil7dmFyIGw9TWF0aC5sb2cxMChNYXRoLm1heCgwLjUsTWF0aC5taW4odiwxZTkpKSk7cmV0dXJuIEJjLmgtMjYtKE1hdGgubWluKGwsaGkpLWxvKS8oaGktbG8pKihCYy5oLTQ0KX0KICBheGVzKGQsQmMse2NvbDpjb2wsc3g6ZnVuY3Rpb24oKXtyZXR1cm4gMH0sc3k6cHkseHQ6W10seXQ6WzEsMTAsMTAwLDEwMDBdLGxlZnQ6MzQscmlnaHQ6MTAsdG9wOjE4LGJvdDoyNix4bDoic3RlcHMg4oaSIix5bDoiZXJyb3IgKGxvZyBzY2FsZSkifSk7CiAgZC5zdHJva2VTdHlsZT1jb2wuYmFkO2QubGluZVdpZHRoPTIuNTtkLmJlZ2luUGF0aCgpO2guZm9yRWFjaChmdW5jdGlvbih2LGkpe2k\/ZC5saW5lVG8ocHgoaSkscHkodikpOmQubW92ZVRvKHB4KGkpLHB5KHYpKX0pO2Quc3Ryb2tlKCk7CiAgdmFyIGU9bXNlKCk7JCgiLmNkLWdkLW0iLGJveCkudGV4dENvbnRlbnQ9aXNGaW5pdGUobSk\/ZjEobSwyKToi4oieIjskKCIuY2QtZ2QtYiIsYm94KS50ZXh0Q29udGVudD1pc0Zpbml0ZShiKT9mMShiLDIpOiLiiJ4iOyQoIi5jZC1nZC1lIixib3gpLnRleHRDb250ZW50PWlzRmluaXRlKGUpJiZlPDFlOT9mMShlLDIpOiJleHBsb2RlZCI7JCgiLmNkLWdkLW4iLGJveCkudGV4dENvbnRlbnQ9c3RlcDsKICB2YXIgbXNnPSQoIi5jZC1nZC1ub3RlIixib3gpOwogIGlmKCFpc0Zpbml0ZShlKXx8ZT4xZTYpbXNnLnRleHRDb250ZW50PSJUaGUgbGVhcm5pbmcgcmF0ZSBpcyB0b28gaGlnaC4gRXZlcnkgdXBkYXRlIG92ZXJzaG9vdHMsIHNvIHRoZSBlcnJvciBncm93cyBpbnN0ZWFkIG9mIHNocmlua2luZy4gTG93ZXIgaXQgYW5kIHJlc2V0LiI7CiAgZWxzZSBpZihzdGVwPT09MCltc2cudGV4dENvbnRlbnQ9IlRoZSBtb2RlbCBzdGFydHMgd2l0aCBhIGZsYXQgbGluZSBhdCB6ZXJvLiBQcmVzcyBSdW4gYW5kIHdhdGNoIGl0IGxlYXJuLiI7CiAgZWxzZSBpZihlPDAuNzM0NCltc2cudGV4dENvbnRlbnQ9IkNvbnZlcmdlZCBhdCBtID0gIitmMShtLDIpKyIgYW5kIGIgPSAiK2YxKGIsMikrIi4gVGhlIGV4YWN0IGZvcm11bGEgZ2l2ZXMgNi41MSBhbmQgMjguODIsIHNvIGdyYWRpZW50IGRlc2NlbnQgZ290IHRoZXJlIGJ5IHRyaWFsIGFuZCBlcnJvci4iOwogIGVsc2UgaWYoc3RlcD4yMCYmbT41KW1zZy50ZXh0Q29udGVudD0iVGhlIHNsb3BlIHNldHRsZWQgcXVpY2tseS4gVGhlIGludGVyY2VwdCBtb3ZlcyBzbG93bHksIHdoaWNoIGlzIHdoeSByZWFsIHRyYWluaW5nIHJ1bnMgZm9yIHRob3VzYW5kcyBvZiBzdGVwcy4iOwogIGVsc2UgbXNnLnRleHRDb250ZW50PSJFYWNoIHN0ZXAgbnVkZ2VzIG0gYW5kIGIgaW4gdGhlIGRpcmVjdGlvbiB0aGF0IGxvd2VycyB0aGUgZXJyb3IuIjt9CiBmdW5jdGlvbiBzdG9wKCl7Y2xlYXJJbnRlcnZhbCh0aW1lcik7dGltZXI9bnVsbDskKCIuY2QtZ2QtcnVuIixib3gpLnRleHRDb250ZW50PSJSdW4ifQogZnVuY3Rpb24gdGljaygpe2Zvcih2YXIgaz0wO2s8KHN0ZXA8NjA\/MToyNSk7aysrKXtvbmUoKTtpZighaXNGaW5pdGUobXNlKCkpfHxtc2UoKT4xZTkpYnJlYWt9ZHJhdygpO3ZhciBlPW1zZSgpO2lmKGU8MC43MzQ0fHxzdGVwPjgwMDB8fCFpc0Zpbml0ZShlKXx8ZT4xZTkpc3RvcCgpfQogJCgiLmNkLWdkLXJ1biIsYm94KS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtpZih0aW1lcilyZXR1cm4gc3RvcCgpO3RoaXMudGV4dENvbnRlbnQ9IlBhdXNlIjt0aW1lcj1zZXRJbnRlcnZhbCh0aWNrLFJNPzEwOjYwKX0pOwogJCgiLmNkLWdkLW9uZSIsYm94KS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtvbmUoKTtkcmF3KCl9KTsKICQoIi5jZC1nZC1yZXNldCIsYm94KS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtzdG9wKCk7bT0wO2I9MDtzdGVwPTA7aGlzdD1bXTtkcmF3KCl9KTsKICQoIi5jZC1nZC1sciIsYm94KS5hZGRFdmVudExpc3RlbmVyKCJpbnB1dCIsZnVuY3Rpb24oZSl7bHI9K2UudGFyZ2V0LnZhbHVlOyQoIi5jZC1nZC1scnYiLGJveCkudGV4dENvbnRlbnQ9bHIudG9GaXhlZCgzKTtzdG9wKCk7bT0wO2I9MDtzdGVwPTA7aGlzdD1bXTtkcmF3KCl9KTsKIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJyZXNpemUiLGZ1bmN0aW9uKCl7QT1udWxsO2RyYXcoKX0pO2RyYXcoKTsKfSk7CgovKiA0LiBNdWx0aXBsZSByZWdyZXNzaW9uIDNEICovCiQkKCIuY2RhaS5jZC1sci0zZCIpLmZvckVhY2goZnVuY3Rpb24oYm94KXsKIHZhciBjdj0kKCJjYW52YXMiLGJveCksUyx5YXc9MC43NSxwaXRjaD0wLjYyLGF1dG89IVJNLGRyYWdnaW5nPWZhbHNlLGx4PTAsY29sLHI9cm5nKDcpLFA9W107CiBmb3IodmFyIGk9MDtpPDM0O2krKyl7dmFyIHN6PTQ1MCtyKCkqMTU1MCxhZz1yKCkqMzAscHI9MC4wNTUqc3otMC42KmFnKzE1K2dhdXNzKHIpKjY7UC5wdXNoKFtzeixhZyxwcl0pfQogdmFyIG49UC5sZW5ndGgsWD1bWzAsMCwwXSxbMCwwLDBdLFswLDAsMF1dLFk9WzAsMCwwXTtQLmZvckVhY2goZnVuY3Rpb24ocCl7dmFyIHY9WzEscFswXSxwWzFdXTtmb3IodmFyIGE9MDthPDM7YSsrKXtZW2FdKz12W2FdKnBbMl07Zm9yKHZhciBjMj0wO2MyPDM7YzIrKylYW2FdW2MyXSs9dlthXSp2W2MyXX19KTsKIGZ1bmN0aW9uIHNvbHZlKE0sdil7dmFyIEE9TS5tYXAoZnVuY3Rpb24ocm93LGkpe3JldHVybiByb3cuY29uY2F0KFt2W2ldXSl9KTtmb3IodmFyIGk9MDtpPDM7aSsrKXt2YXIgbXg9aTtmb3IodmFyIGs9aSsxO2s8MztrKyspaWYoTWF0aC5hYnMoQVtrXVtpXSk+TWF0aC5hYnMoQVtteF1baV0pKW14PWs7dmFyIHQ9QVtpXTtBW2ldPUFbbXhdO0FbbXhdPXQ7Zm9yKHZhciBrMj1pKzE7azI8MztrMisrKXt2YXIgZj1BW2syXVtpXS9BW2ldW2ldO2Zvcih2YXIgaj1pO2o8NDtqKyspQVtrMl1bal0tPWYqQVtpXVtqXX19dmFyIHg9WzAsMCwwXTtmb3IodmFyIGkyPTI7aTI+PTA7aTItLSl7dmFyIHM9QVtpMl1bM107Zm9yKHZhciBqMj1pMisxO2oyPDM7ajIrKylzLT1BW2kyXVtqMl0qeFtqMl07eFtpMl09cy9BW2kyXVtpMl19cmV0dXJuIHh9CiB2YXIgVz1zb2x2ZShYLFkpOwogJCgiLmNkLTNkLWVxIixib3gpLnRleHRDb250ZW50PSJwcmljZSA9ICIrZjEoV1swXSwxKSsiICsgIitmMShXWzFdLDMpKyIgw5cgc2l6ZSAiKyhXWzJdPDA\/IuKIkiAiOiIrICIpK2YxKE1hdGguYWJzKFdbMl0pLDIpKyIgw5cgYWdlIjsKIGZ1bmN0aW9uIG5ybShwKXtyZXR1cm4gWyhwWzBdLTEyMjUpLzc3NSwocFsxXS0xNSkvMTUsKHBbMl0tNzApLzYwXX0KIGZ1bmN0aW9uIHByb2oodil7dmFyIGN5PU1hdGguY29zKHlhdyksc3kyPU1hdGguc2luKHlhdykseD12WzBdKmN5LXZbMV0qc3kyLHo9dlswXSpzeTIrdlsxXSpjeSx5PXZbMl0sY3A9TWF0aC5jb3MocGl0Y2gpLHNwPU1hdGguc2luKHBpdGNoKSx5Mj15KmNwLXoqc3AsejI9eSpzcCt6KmNwLHNjPU1hdGgubWluKFMudyowLjI2LFMuaCowLjI4KTtyZXR1cm4gW1Mudy8yK3gqc2MsUy5oLzIteTIqc2MrNix6Ml19CiBmdW5jdGlvbiBwcmVkKHN6LGFnKXtyZXR1cm4gV1swXStXWzFdKnN6K1dbMl0qYWd9CiBmdW5jdGlvbiBkcmF3KCl7aWYoIVMpUz1jYW52YXNGb3IoY3YsMzIwKTtjb2w9Y29sb3JzKGJveCk7dmFyIGM9Uy5jO2MuY2xlYXJSZWN0KDAsMCxTLncsUy5oKTtjLmxpbmVXaWR0aD0xOwogIHZhciBheD1bW1s0NTAsMCwxMF0sWzIwMDAsMCwxMF0sInNpemUgKHNxIGZ0KSJdLFtbNDUwLDAsMTBdLFs0NTAsMzAsMTBdLCJhZ2UgKHllYXJzKSJdLFtbNDUwLDAsMTBdLFs0NTAsMCwxMzBdLCJwcmljZSAo4oK5IGxha2gpIl1dOwogIGF4LmZvckVhY2goZnVuY3Rpb24oYSl7dmFyIHAxPXByb2oobnJtKGFbMF0pKSxwMj1wcm9qKG5ybShhWzFdKSk7Yy5zdHJva2VTdHlsZT1jb2wubXV0O2MuYmVnaW5QYXRoKCk7Yy5tb3ZlVG8ocDFbMF0scDFbMV0pO2MubGluZVRvKHAyWzBdLHAyWzFdKTtjLnN0cm9rZSgpO2MuZmlsbFN0eWxlPWNvbC5tdXQ7Yy5mb250PSIxMXB4IEludGVyLHNhbnMtc2VyaWYiO2MuZmlsbFRleHQoYVsyXSxwMlswXSs0LHAyWzFdKX0pOwogIGMuc3Ryb2tlU3R5bGU9Y29sLmJyO2MuZ2xvYmFsQWxwaGE9LjU7Zm9yKHZhciBrPTA7azw9NjtrKyspe3ZhciBzMT00NTArayoxNTUwLzYsYTE9ayo1OwogICB2YXIgcTE9cHJvaihucm0oW3MxLDAscHJlZChzMSwwKV0pKSxxMj1wcm9qKG5ybShbczEsMzAscHJlZChzMSwzMCldKSk7Yy5iZWdpblBhdGgoKTtjLm1vdmVUbyhxMVswXSxxMVsxXSk7Yy5saW5lVG8ocTJbMF0scTJbMV0pO2Muc3Ryb2tlKCk7CiAgIHZhciBxMz1wcm9qKG5ybShbNDUwLGExLHByZWQoNDUwLGExKV0pKSxxND1wcm9qKG5ybShbMjAwMCxhMSxwcmVkKDIwMDAsYTEpXSkpO2MuYmVnaW5QYXRoKCk7Yy5tb3ZlVG8ocTNbMF0scTNbMV0pO2MubGluZVRvKHE0WzBdLHE0WzFdKTtjLnN0cm9rZSgpfWMuZ2xvYmFsQWxwaGE9MTsKICB2YXIgaXRlbXM9UC5tYXAoZnVuY3Rpb24ocCl7dmFyIGE9cHJvaihucm0ocCkpLGIyPXByb2oobnJtKFtwWzBdLHBbMV0scHJlZChwWzBdLHBbMV0pXSkpO3JldHVybiB7YTphLGI6YjIsdXA6cFsyXT5wcmVkKHBbMF0scFsxXSl9fSkuc29ydChmdW5jdGlvbih1LHYpe3JldHVybiB2LmFbMl0tdS5hWzJdfSk7CiAgaXRlbXMuZm9yRWFjaChmdW5jdGlvbihpdCl7Yy5zdHJva2VTdHlsZT1jb2wuYmFkO2MuZ2xvYmFsQWxwaGE9LjU7Yy5iZWdpblBhdGgoKTtjLm1vdmVUbyhpdC5hWzBdLGl0LmFbMV0pO2MubGluZVRvKGl0LmJbMF0saXQuYlsxXSk7Yy5zdHJva2UoKTtjLmdsb2JhbEFscGhhPTE7Yy5maWxsU3R5bGU9aXQudXA\/Y29sLmdvb2Q6Y29sLmluaztjLmJlZ2luUGF0aCgpO2MuYXJjKGl0LmFbMF0saXQuYVsxXSw0LjUsMCw3KTtjLmZpbGwoKX0pfQogZnVuY3Rpb24gbG9vcCgpe2lmKGF1dG8pe3lhdys9MC4wMDQ7ZHJhdygpO3JlcXVlc3RBbmltYXRpb25GcmFtZShsb29wKX19CiBjdi5hZGRFdmVudExpc3RlbmVyKCJwb2ludGVyZG93biIsZnVuY3Rpb24oZSl7ZHJhZ2dpbmc9dHJ1ZTthdXRvPWZhbHNlO2x4PWUuY2xpZW50WDtjdi5zZXRQb2ludGVyQ2FwdHVyZShlLnBvaW50ZXJJZCl9KTsKIGN2LmFkZEV2ZW50TGlzdGVuZXIoInBvaW50ZXJtb3ZlIixmdW5jdGlvbihlKXtpZighZHJhZ2dpbmcpcmV0dXJuO3lhdys9KGUuY2xpZW50WC1seCkqMC4wMTtseD1lLmNsaWVudFg7ZHJhdygpfSk7CiBjdi5hZGRFdmVudExpc3RlbmVyKCJwb2ludGVydXAiLGZ1bmN0aW9uKCl7ZHJhZ2dpbmc9ZmFsc2V9KTtjdi5hZGRFdmVudExpc3RlbmVyKCJwb2ludGVyY2FuY2VsIixmdW5jdGlvbigpe2RyYWdnaW5nPWZhbHNlfSk7CiAkKCIuY2QtM2Qtc3BpbiIsYm94KS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXthdXRvPSFhdXRvO3RoaXMudGV4dENvbnRlbnQ9YXV0bz8iUGF1c2Ugc3BpbiI6IkF1dG8gc3BpbiI7aWYoYXV0bylsb29wKCl9KTsKIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJyZXNpemUiLGZ1bmN0aW9uKCl7Uz1udWxsO2RyYXcoKX0pO2RyYXcoKTtpZihhdXRvKWxvb3AoKTsKfSk7CgovKiA1LiBBc3N1bXB0aW9uIGNoZWNrZXIgKi8KJCQoIi5jZGFpLmNkLWxyLWFzc3VtZSIpLmZvckVhY2goZnVuY3Rpb24oYm94KXsKIHZhciBjdnM9JCQoImNhbnZhcyIsYm94KSxBLEIyLGN1cj0iaGVhbHRoeSIsY29sOwogdmFyIGluZm89e2hlYWx0aHk6WyJIZWFsdGh5IGRhdGEiLCJSZXNpZHVhbHMgc2NhdHRlciByYW5kb21seSBhcm91bmQgemVybyBpbiBhbiBldmVuIGJhbmQuIEFsbCB0aGUgYXNzdW1wdGlvbnMgbG9vayBmaW5lLCBzbyB5b3UgY2FuIHRydXN0IHRoZSBtb2RlbCdzIG51bWJlcnMuIl0sCiAgY3VydmVkOlsiTm90IGxpbmVhciIsIlRoZSByZXNpZHVhbHMgZm9ybSBhIFUgc2hhcGUuIEEgc3RyYWlnaHQgbGluZSBjYW5ub3QgZm9sbG93IHRoZSBjdXJ2ZSwgc28gcHJlZGljdGlvbnMgYXJlIHRvbyBoaWdoIGluIHRoZSBtaWRkbGUgYW5kIHRvbyBsb3cgYXQgdGhlIGVuZHMuIFRyeSBhZGRpbmcgYSBzcXVhcmVkIGZlYXR1cmUgKHBvbHlub21pYWwgcmVncmVzc2lvbikuIl0sCiAgZnVubmVsOlsiVW5lcXVhbCB2YXJpYW5jZSAoaGV0ZXJvc2NlZGFzdGljaXR5KSIsIlRoZSByZXNpZHVhbHMgc3ByZWFkIG91dCBsaWtlIGEgZnVubmVsIGFzIHggZ3Jvd3MuIFByZWRpY3Rpb25zIGZvciBsYXJnZSB2YWx1ZXMgYXJlIG11Y2ggbGVzcyByZWxpYWJsZS4gQSBsb2cgdHJhbnNmb3JtIG9mIHkgb2Z0ZW4gaGVscHMuIl0sCiAgb3V0bGllcjpbIk91dGxpZXJzIiwiQSBjb3VwbGUgb2YgZXh0cmVtZSBwb2ludHMgZHJhZyB0aGUgbGluZSBhd2F5IGZyb20gdGhlIHJlc3Qgb2YgdGhlIGRhdGEuIENoZWNrIHdoZXRoZXIgdGhleSBhcmUgZGF0YSBlbnRyeSBtaXN0YWtlcyBiZWZvcmUgeW91IGRlY2lkZSB0byBrZWVwIG9yIHJlbW92ZSB0aGVtLiJdfTsKIGZ1bmN0aW9uIGRhdGEoa2luZCl7dmFyIHI9cm5nKGtpbmQubGVuZ3RoKjk3KzMpLHB0cz1bXTtmb3IodmFyIGk9MDtpPDQwO2krKyl7dmFyIHg9MC4zK2kqMC4yNCx5OwogIGlmKGtpbmQ9PT0iY3VydmVkIil5PTEuMiooeC01KSooeC01KSsxMCtnYXVzcyhyKSoxLjY7ZWxzZSBpZihraW5kPT09ImZ1bm5lbCIpeT0yLjQqeCs2K2dhdXNzKHIpKigwLjMreCowLjkpO2Vsc2UgeT0yLjQqeCs2K2dhdXNzKHIpKjEuODtwdHMucHVzaChbeCx5XSl9CiAgaWYoa2luZD09PSJvdXRsaWVyIil7cHRzLnB1c2goWzguOCwxXSk7cHRzLnB1c2goWzkuNCwzXSl9cmV0dXJuIHB0c30KIGZ1bmN0aW9uIHBsb3QoQ3YscHRzLEYscmVzaWQpe3ZhciBjPUN2LmMsTD0yNixSPTgsVD0xNixCbT0yMCx4cz1wdHMubWFwKGZ1bmN0aW9uKHApe3JldHVybiBwWzBdfSksdmFscz1yZXNpZD9wdHMubWFwKGZ1bmN0aW9uKHApe3JldHVybiBwWzFdLShGLm0qcFswXStGLmIpfSk6cHRzLm1hcChmdW5jdGlvbihwKXtyZXR1cm4gcFsxXX0pOwogIHZhciBsbz1NYXRoLm1pbi5hcHBseShudWxsLHZhbHMpLGhpPU1hdGgubWF4LmFwcGx5KG51bGwsdmFscykscGFkPShoaS1sbykqMC4xMnx8MTtsby09cGFkO2hpKz1wYWQ7aWYocmVzaWQpe3ZhciBtbT1NYXRoLm1heChNYXRoLmFicyhsbyksTWF0aC5hYnMoaGkpKTtsbz0tbW07aGk9bW19CiAgZnVuY3Rpb24gc3godil7cmV0dXJuIEwrdi8xMCooQ3Yudy1MLVIpfWZ1bmN0aW9uIHN5KHYpe3JldHVybiBDdi5oLUJtLSh2LWxvKS8oaGktbG8pKihDdi5oLVQtQm0pfQogIGMuY2xlYXJSZWN0KDAsMCxDdi53LEN2LmgpO2MuZmlsbFN0eWxlPWNvbC5tdXQ7Yy5mb250PSIxMXB4IEludGVyLHNhbnMtc2VyaWYiO2MuZmlsbFRleHQocmVzaWQ\/InJlc2lkdWFsIChlcnJvcikiOiJ5IixMLDExKTtjLmZpbGxUZXh0KHJlc2lkPyJ4IOKGkiI6Ingg4oaSIixDdi53LTMwLEN2LmgtNSk7CiAgYy5zdHJva2VTdHlsZT1yZXNpZD9jb2wuZ29vZDpjb2wuYnI7Yy5saW5lV2lkdGg9cmVzaWQ\/MS41OjIuNTtjLnNldExpbmVEYXNoKHJlc2lkP1s1LDRdOltdKTtjLmJlZ2luUGF0aCgpOwogIGlmKHJlc2lkKXtjLm1vdmVUbyhMLHN5KDApKTtjLmxpbmVUbyhDdi53LVIsc3koMCkpfWVsc2V7Yy5tb3ZlVG8oc3goMCksc3koRi5iKSk7Yy5saW5lVG8oc3goMTApLHN5KEYubSoxMCtGLmIpKX1jLnN0cm9rZSgpO2Muc2V0TGluZURhc2goW10pOwogIGMuZmlsbFN0eWxlPXJlc2lkP2NvbC5iYWQ6Y29sLmluazt4cy5mb3JFYWNoKGZ1bmN0aW9uKHgsaSl7Yy5iZWdpblBhdGgoKTtjLmFyYyhzeCh4KSxzeSh2YWxzW2ldKSwzLjUsMCw3KTtjLmZpbGwoKX0pfQogZnVuY3Rpb24gZHJhdygpe2lmKCFBKXtBPWNhbnZhc0ZvcihjdnNbMF0sMjAwKTtCMj1jYW52YXNGb3IoY3ZzWzFdLDIwMCl9Y29sPWNvbG9ycyhib3gpO3ZhciBwdHM9ZGF0YShjdXIpLEY9Zml0KHB0cyk7cGxvdChBLHB0cyxGLGZhbHNlKTtwbG90KEIyLHB0cyxGLHRydWUpOwogICQoIi5jZC1hcy10aXRsZSIsYm94KS50ZXh0Q29udGVudD1pbmZvW2N1cl1bMF07JCgiLmNkLWFzLXRleHQiLGJveCkudGV4dENvbnRlbnQ9aW5mb1tjdXJdWzFdOwogICQkKCIuY2QtY2hpcCIsYm94KS5mb3JFYWNoKGZ1bmN0aW9uKGNoKXtjaC5zZXRBdHRyaWJ1dGUoImFyaWEtcHJlc3NlZCIsY2guZGF0YXNldC5rPT09Y3VyPyJ0cnVlIjoiZmFsc2UiKX0pfQogJCQoIi5jZC1jaGlwIixib3gpLmZvckVhY2goZnVuY3Rpb24oY2gpe2NoLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe2N1cj1jaC5kYXRhc2V0Lms7ZHJhdygpfSl9KTsKIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJyZXNpemUiLGZ1bmN0aW9uKCl7QT1udWxsO2RyYXcoKX0pO2RyYXcoKTsKfSk7CgovKiA2LiBMaW5lYXIgdnMgbG9naXN0aWMgKi8KJCQoIi5jZGFpLmNkLWxyLWxvZyIpLmZvckVhY2goZnVuY3Rpb24oYm94KXsKIHZhciBjdj0kKCJjYW52YXMiLGJveCksUyxtb2RlPSJsaW5lYXIiLGNvbCxIPVswLjUsMSwxLjUsMiwyLjUsMywzLjUsNCw0LjUsNSw1LjUsNiw2LjUsNyw4LDkuNV0sWT1bMCwwLDAsMCwwLDEsMCwwLDEsMSwwLDEsMSwxLDEsMV07CiB2YXIgRj1maXQoSC5tYXAoZnVuY3Rpb24oaCxpKXtyZXR1cm4gW2gsWVtpXV19KSksdz0wLGI9MDsKIGZvcih2YXIgaXQ9MDtpdDwyMDAwMDtpdCsrKXt2YXIgZ3c9MCxnYj0wO2Zvcih2YXIgaT0wO2k8SC5sZW5ndGg7aSsrKXt2YXIgcD0xLygxK01hdGguZXhwKC0odypIW2ldK2IpKSk7Z3crPShwLVlbaV0pKkhbaV07Z2IrPXAtWVtpXX13LT0wLjA1Kmd3L0gubGVuZ3RoO2ItPTAuMDUqZ2IvSC5sZW5ndGh9CiBmdW5jdGlvbiBzaWcoeCl7cmV0dXJuIDEvKDErTWF0aC5leHAoLSh3KngrYikpKX0KIHZhciBMPTM2LFI9MTIsVD0xNCxCbT0yNjsKIGZ1bmN0aW9uIHN4KHYpe3JldHVybiBMK3YvMTIqKFMudy1MLVIpfWZ1bmN0aW9uIHN5KHYpe3JldHVybiBTLmgtQm0tKHYrMC41KS8yKihTLmgtVC1CbSl9CiBmdW5jdGlvbiBkcmF3KCl7aWYoIVMpUz1jYW52YXNGb3IoY3YsMjYwKTtjb2w9Y29sb3JzKGJveCk7dmFyIGM9Uy5jLHE9KyQoIi5jZC1sb2ctaCIsYm94KS52YWx1ZTtjLmNsZWFyUmVjdCgwLDAsUy53LFMuaCk7CiAgYy5maWxsU3R5bGU9Y29sLmJhZDtjLmdsb2JhbEFscGhhPS4wODtjLmZpbGxSZWN0KEwsc3koMS41KSxTLnctTC1SLHN5KDEpLXN5KDEuNSkpO2MuZmlsbFJlY3QoTCxzeSgwKSxTLnctTC1SLHN5KC0wLjUpLXN5KDApKTtjLmdsb2JhbEFscGhhPTE7CiAgYXhlcyhjLFMse2NvbDpjb2wsc3g6c3gsc3k6c3kseHQ6WzAsMiw0LDYsOCwxMCwxMl0seXQ6WzAsMC41LDFdLGxlZnQ6TCxyaWdodDpSLHRvcDpULGJvdDpCbSx4bDoiaG91cnMgc3R1ZGllZCIseWw6InBhc3MgKDEpIC8gZmFpbCAoMCkifSk7CiAgYy5maWxsU3R5bGU9Y29sLmJhZDtjLmZvbnQ9IjExcHggSW50ZXIsc2Fucy1zZXJpZiI7Yy5maWxsVGV4dCgiaW1wb3NzaWJsZSB6b25lIChhYm92ZSAxKSIsTCs2LHN5KDEuNDIpKTtjLmZpbGxUZXh0KCJpbXBvc3NpYmxlIHpvbmUgKGJlbG93IDApIixTLnctUi0xNTAsc3koLTAuNCkpOwogIGMuc2F2ZSgpO2MuYmVnaW5QYXRoKCk7Yy5yZWN0KEwsVCxTLnctTC1SLFMuaC1ULUJtKTtjLmNsaXAoKTtjLnN0cm9rZVN0eWxlPWNvbC5icjtjLmxpbmVXaWR0aD0zO2MuYmVnaW5QYXRoKCk7CiAgaWYobW9kZT09PSJsaW5lYXIiKXtjLm1vdmVUbyhzeCgwKSxzeShGLmIpKTtjLmxpbmVUbyhzeCgxMiksc3koRi5tKjEyK0YuYikpfWVsc2V7Zm9yKHZhciB4PTA7eDw9MTI7eCs9MC4xKXt4PT09MD9jLm1vdmVUbyhzeCh4KSxzeShzaWcoeCkpKTpjLmxpbmVUbyhzeCh4KSxzeShzaWcoeCkpKX19Yy5zdHJva2UoKTtjLnJlc3RvcmUoKTsKICBILmZvckVhY2goZnVuY3Rpb24oaCxpKXtjLmZpbGxTdHlsZT1ZW2ldP2NvbC5nb29kOmNvbC5pbms7Yy5iZWdpblBhdGgoKTtjLmFyYyhzeChoKSxzeShZW2ldKSw1LjUsMCw3KTtjLmZpbGwoKX0pOwogIHZhciB2PW1vZGU9PT0ibGluZWFyIj9GLm0qcStGLmI6c2lnKHEpO2Muc3Ryb2tlU3R5bGU9Y29sLm11dDtjLnNldExpbmVEYXNoKFs0LDRdKTtjLmxpbmVXaWR0aD0xO2MuYmVnaW5QYXRoKCk7Yy5tb3ZlVG8oc3gocSksc3koLTAuNSkpO2MubGluZVRvKHN4KHEpLHN5KDEuNSkpO2Muc3Ryb2tlKCk7Yy5zZXRMaW5lRGFzaChbXSk7CiAgYy5maWxsU3R5bGU9Y29sLmJyO2MuYmVnaW5QYXRoKCk7Yy5hcmMoc3gocSksc3koTWF0aC5tYXgoLTAuNSxNYXRoLm1pbigxLjUsdikpKSw3LDAsNyk7Yy5maWxsKCk7CiAgJCgiLmNkLWxvZy1odiIsYm94KS50ZXh0Q29udGVudD1xKyIgaHJzIjskKCIuY2QtbG9nLW91dCIsYm94KS50ZXh0Q29udGVudD1mMSh2LDIpOwogIHZhciBtc2c9bW9kZT09PSJsaW5lYXIiPyh2PjE\/IkxpbmVhciByZWdyZXNzaW9uIHNheXMgIitmMSh2LDIpKyIsIHdoaWNoIHdvdWxkIGJlIGEgIitNYXRoLnJvdW5kKHYqMTAwKSsiJSBjaGFuY2Ugb2YgcGFzc2luZy4gVGhhdCBpcyBpbXBvc3NpYmxlLiI6djwwPyJMaW5lYXIgcmVncmVzc2lvbiBzYXlzICIrZjEodiwyKSsiLCBhIG5lZ2F0aXZlIHByb2JhYmlsaXR5LiBUaGF0IG1ha2VzIG5vIHNlbnNlLiI6Ikluc2lkZSAwIHRvIDEgaGVyZSwgYnV0IGRyYWcgdGhlIHNsaWRlciB0byB0aGUgZW5kcyBhbmQgc2VlIHdoYXQgaGFwcGVucy4iKToiTG9naXN0aWMgcmVncmVzc2lvbiBzcXVlZXplcyBldmVyeSBhbnN3ZXIgYmV0d2VlbiAwIGFuZCAxOiAiK01hdGgucm91bmQodioxMDApKyIlIGNoYW5jZSBvZiBwYXNzaW5nLiI7CiAgJCgiLmNkLWxvZy1tc2ciLGJveCkudGV4dENvbnRlbnQ9bXNnOyQkKCIuY2QtY2hpcCIsYm94KS5mb3JFYWNoKGZ1bmN0aW9uKGNoKXtjaC5zZXRBdHRyaWJ1dGUoImFyaWEtcHJlc3NlZCIsY2guZGF0YXNldC5tPT09bW9kZT8idHJ1ZSI6ImZhbHNlIil9KX0KICQkKCIuY2QtY2hpcCIsYm94KS5mb3JFYWNoKGZ1bmN0aW9uKGNoKXtjaC5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXttb2RlPWNoLmRhdGFzZXQubTtkcmF3KCl9KX0pOwogJCgiLmNkLWxvZy1oIixib3gpLmFkZEV2ZW50TGlzdGVuZXIoImlucHV0IixkcmF3KTsKIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJyZXNpemUiLGZ1bmN0aW9uKCl7Uz1udWxsO2RyYXcoKX0pO2RyYXcoKTsKfSk7CgovKiA3LiBRdWl6ICovCiQkKCIuY2RhaS5jZC1sci1xdWl6IikuZm9yRWFjaChmdW5jdGlvbihib3gpewogdmFyIFE9Wwoge3E6IkluIHkgPSBteCArIGIsIHdoYXQgZG9lcyBtIHRlbGwgeW91PyIsbzpbIldoZXJlIHRoZSBsaW5lIGNyb3NzZXMgdGhlIHktYXhpcyIsIkhvdyBtdWNoIHkgY2hhbmdlcyB3aGVuIHggZ29lcyB1cCBieSAxIiwiVGhlIGVycm9yIG9mIHRoZSBtb2RlbCIsIlRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMiXSxhOjEsZToibSBpcyB0aGUgc2xvcGUuIElmIG0gPSA2LjUgaW4gb3VyIG1hcmtzIGV4YW1wbGUsIGV2ZXJ5IGV4dHJhIGhvdXIgb2Ygc3R1ZHkgYWRkcyBhYm91dCA2LjUgbWFya3MuIn0sCiB7cToiV2hhdCBkb2VzIGxpbmVhciByZWdyZXNzaW9uIHRyeSB0byBtaW5pbWlzZSBkdXJpbmcgdHJhaW5pbmc\/IixvOlsiVGhlIG51bWJlciBvZiBmZWF0dXJlcyIsIlRoZSBzbG9wZSIsIlRoZSBtZWFuIHNxdWFyZWQgZXJyb3IgYmV0d2VlbiBwcmVkaWN0aW9ucyBhbmQgYWN0dWFsIHZhbHVlcyIsIlRoZSBSwrIgc2NvcmUiXSxhOjIsZToiVHJhaW5pbmcgcGlja3MgdGhlIGxpbmUgd2l0aCB0aGUgc21hbGxlc3QgYXZlcmFnZSBzcXVhcmVkIGVycm9yLiBUaGF0IGlzIHdoeSBpdCBpcyBhbHNvIGNhbGxlZCBvcmRpbmFyeSBsZWFzdCBzcXVhcmVzLiJ9LAoge3E6IllvdXIgcmVzaWR1YWwgcGxvdCBsb29rcyBsaWtlIGEgVSBzaGFwZS4gV2hhdCBkb2VzIHRoYXQgc3VnZ2VzdD8iLG86WyJFdmVyeXRoaW5nIGlzIGZpbmUiLCJUaGUgcmVsYXRpb25zaGlwIGlzIG5vdCBsaW5lYXIiLCJZb3UgaGF2ZSB0b28gbXVjaCBkYXRhIiwiVGhlIGxlYXJuaW5nIHJhdGUgaXMgdG9vIGhpZ2giXSxhOjEsZToiQSBjdXJ2ZWQgcGF0dGVybiBpbiByZXNpZHVhbHMgbWVhbnMgYSBzdHJhaWdodCBsaW5lIGlzIG1pc3NpbmcgYSBjdXJ2ZSBpbiB0aGUgZGF0YS4gVHJ5IHBvbHlub21pYWwgZmVhdHVyZXMuIn0sCiB7cToiWW91IHdhbnQgdG8gcHJlZGljdCB3aGV0aGVyIGFuIGVtYWlsIGlzIHNwYW0gKHllcyBvciBubykuIFdoaWNoIG1vZGVsIGZpdHMgYmV0dGVyPyIsbzpbIkxpbmVhciByZWdyZXNzaW9uIiwiTG9naXN0aWMgcmVncmVzc2lvbiJdLGE6MSxlOiJTcGFtIG9yIG5vdCBzcGFtIGlzIGEgY2xhc3NpZmljYXRpb24gcHJvYmxlbSB3aXRoIHR3byBjbGFzc2VzLiBMb2dpc3RpYyByZWdyZXNzaW9uIG91dHB1dHMgYSBwcm9iYWJpbGl0eSBiZXR3ZWVuIDAgYW5kIDEuIn0sCiB7cToiQSBtb2RlbCBoYXMgUsKyID0gMC45MyBvbiB0ZXN0IGRhdGEuIFdoYXQgZG9lcyB0aGF0IG1lYW4\/IixvOlsiOTMlIG9mIHByZWRpY3Rpb25zIGFyZSBleGFjdGx5IHJpZ2h0IiwiVGhlIG1vZGVsIGV4cGxhaW5zIGFib3V0IDkzJSBvZiB0aGUgdmFyaWF0aW9uIGluIHRoZSB0YXJnZXQiLCJUaGUgZXJyb3IgaXMgNyBsYWtoIHJ1cGVlcyIsIlRoZSBtb2RlbCBpcyBvdmVyZml0dGluZyJdLGE6MSxlOiJSwrIgbWVhc3VyZXMgaG93IG11Y2ggb2YgdGhlIHZhcmlhdGlvbiBpbiB5IHRoZSBtb2RlbCBleHBsYWlucy4gMS4wIGlzIHBlcmZlY3QgYW5kIDAgbWVhbnMgaXQgZG9lcyBubyBiZXR0ZXIgdGhhbiBwcmVkaWN0aW5nIHRoZSBhdmVyYWdlLiJ9LAoge3E6IlR3byBmZWF0dXJlcywgdG90YWwgZmxvb3IgYXJlYSBhbmQgbnVtYmVyIG9mIHJvb21zLCBhcmUgc3Ryb25nbHkgY29ycmVsYXRlZC4gV2hpY2ggYXNzdW1wdGlvbiBpcyBhdCByaXNrPyIsbzpbIk5vIG11bHRpY29sbGluZWFyaXR5IiwiTm9ybWFsaXR5IG9mIHJlc2lkdWFscyIsIkxpbmVhcml0eSIsIkluZGVwZW5kZW5jZSBvZiBvYnNlcnZhdGlvbnMiXSxhOjAsZToiV2hlbiBmZWF0dXJlcyBtb3ZlIHRvZ2V0aGVyLCB0aGUgbW9kZWwgc3RydWdnbGVzIHRvIHRlbGwgdGhlaXIgZWZmZWN0cyBhcGFydCwgYW5kIHRoZSBjb2VmZmljaWVudHMgYmVjb21lIHVuc3RhYmxlLiJ9XTsKIHZhciBpPTAsc2NvcmU9MCxib2R5PSQoIi5jZC1scnEtYm9keSIsYm94KTsKIGZ1bmN0aW9uIHNob3coKXt2YXIgaXQ9UVtpXTtib2R5LmlubmVySFRNTD0nPHAgY2xhc3M9ImNkLXNtYWxsIj5RdWVzdGlvbiAnKyhpKzEpKycgb2YgJytRLmxlbmd0aCsnIHwgU2NvcmUgJytzY29yZSsnPC9wPjxkaXYgY2xhc3M9ImNkLWdhbWUtY2FyZCIgc3R5bGU9Im1pbi1oZWlnaHQ6NjRweCI+JytpdC5xKyc8L2Rpdj48ZGl2IGNsYXNzPSJjZC1xLW9wdHMiPicraXQuby5tYXAoZnVuY3Rpb24obyxrKXtyZXR1cm4gJzxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2QtYnRuIiBkYXRhLWs9IicraysnIj4nK28rJzwvYnV0dG9uPid9KS5qb2luKCIiKSsnPC9kaXY+PGRpdiBjbGFzcz0iY2QtZmVlZGJhY2siIGhpZGRlbj48L2Rpdj48ZGl2IHN0eWxlPSJtYXJnaW4tdG9wOjEycHgiPjxidXR0b24gdHlwZT0iYnV0dG9uIiBjbGFzcz0iY2QtYnRuIGNkLXByaW1hcnkgY2QtbHJxLW5leHQiIGhpZGRlbj4nKyhpPFEubGVuZ3RoLTE\/Ik5leHQgcXVlc3Rpb24iOiJTZWUgbXkgc2NvcmUiKSsnPC9idXR0b24+PC9kaXY+JzsKICAkJCgiLmNkLXEtb3B0cyBidXR0b24iLGJvZHkpLmZvckVhY2goZnVuY3Rpb24oYnQpe2J0LmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe3ZhciBrPStidC5kYXRhc2V0Lmssb2s9az09PWl0LmE7aWYob2spc2NvcmUrKzskJCgiLmNkLXEtb3B0cyBidXR0b24iLGJvZHkpLmZvckVhY2goZnVuY3Rpb24oeCxqKXt4LmRpc2FibGVkPXRydWU7aWYoaj09PWl0LmEpeC5jbGFzc0xpc3QuYWRkKCJjZC1yaWdodCIpO2Vsc2UgaWYoaj09PWspeC5jbGFzc0xpc3QuYWRkKCJjZC13cm9uZyIpfSk7CiAgIHZhciBmYj0kKCIuY2QtZmVlZGJhY2siLGJvZHkpO2ZiLmhpZGRlbj1mYWxzZTtmYi5jbGFzc05hbWU9ImNkLWZlZWRiYWNrICIrKG9rPyJjZC1vayI6ImNkLW5vIik7ZmIuaW5uZXJIVE1MPSI8Yj4iKyhvaz8iQ29ycmVjdC4iOiJOb3QgcXVpdGUuIikrIjwvYj4gIitpdC5lOyQoIi5jZC1scnEtbmV4dCIsYm9keSkuaGlkZGVuPWZhbHNlfSl9KTsKICAkKCIuY2QtbHJxLW5leHQiLGJvZHkpLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe2krKztpZihpPFEubGVuZ3RoKXNob3coKTtlbHNlIGRvbmUoKX0pfQogZnVuY3Rpb24gZG9uZSgpe2JvZHkuaW5uZXJIVE1MPSc8ZGl2IGNsYXNzPSJjZC1mZWVkYmFjayBjZC1vayI+PGI+WW91IHNjb3JlZCAnK3Njb3JlKycgb3V0IG9mICcrUS5sZW5ndGgrJy48L2I+ICcrKHNjb3JlPj01PyJZb3UgdW5kZXJzdGFuZCBsaW5lYXIgcmVncmVzc2lvbiB3ZWxsIGVub3VnaCB0byB1c2UgaXQgb24gcmVhbCBkYXRhLiI6c2NvcmU+PTM\/Ikdvb2QgYmFzZS4gUmV2aXNpdCB0aGUgYXNzdW1wdGlvbnMgYW5kIGV2YWx1YXRpb24gc2VjdGlvbnMgb25jZSBtb3JlLiI6IlNjcm9sbCBiYWNrIHVwIGFuZCBwbGF5IHdpdGggdGhlIHdpZGdldHMgYWdhaW4sIHRoZW4gcmV0cnkuIikrJzwvZGl2PjxkaXYgc3R5bGU9Im1hcmdpbi10b3A6MTJweCI+PGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJjZC1idG4gY2QtbHJxLWFnYWluIj5UcnkgYWdhaW48L2J1dHRvbj48L2Rpdj4nOyQoIi5jZC1scnEtYWdhaW4iLGJvZHkpLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe2k9MDtzY29yZT0wO3Nob3coKX0pfQogJCgiLmNkLWxycS1zdGFydCIsYm94KS5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsc2hvdyk7Cn0pOwoKLyogQ29weSBidXR0b25zICovCiQkKCIuY2RhaS5jZC1jb2RlYm94IikuZm9yRWFjaChmdW5jdGlvbihib3gpe3ZhciBidD0kKCIuY2QtY29weSIsYm94KTtpZighYnQpcmV0dXJuO2J0LmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixmdW5jdGlvbigpe3ZhciB0PSQoInByZSBjb2RlIixib3gpLnRleHRDb250ZW50O2Z1bmN0aW9uIG9rKCl7YnQudGV4dENvbnRlbnQ9IkNvcGllZCI7c2V0VGltZW91dChmdW5jdGlvbigpe2J0LnRleHRDb250ZW50PSJDb3B5In0sMTUwMCl9CiBpZihuYXZpZ2F0b3IuY2xpcGJvYXJkJiZuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCl7bmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQodCkudGhlbihvayxmdW5jdGlvbigpe3NlbCgpfSl9ZWxzZSBzZWwoKTsKIGZ1bmN0aW9uIHNlbCgpe3ZhciByPWRvY3VtZW50LmNyZWF0ZVJhbmdlKCk7ci5zZWxlY3ROb2RlQ29udGVudHMoJCgicHJlIGNvZGUiLGJveCkpO3ZhciBzPXdpbmRvdy5nZXRTZWxlY3Rpb24oKTtzLnJlbW92ZUFsbFJhbmdlcygpO3MuYWRkUmFuZ2Uocik7YnQudGV4dENvbnRlbnQ9IlByZXNzIEN0cmwrQyJ9fSl9KTsKfSkoKTsK\"><\/script>\n","protected":false},"excerpt":{"rendered":"<p>Learn linear regression by playing with it: drag points, calculate the formula step by step, watch gradient descent, rotate a 3D regression plane, and run Python code with scikit-learn.<\/p>\n","protected":false},"author":1,"featured_media":1160,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[47],"tags":[],"class_list":["post-1161","post","type-post","status-publish","format-standard","has-post-thumbnail","category-ai-machine-learning"],"featured_image_src":"https:\/\/codeanddebug.in\/blog\/wp-content\/uploads\/2026\/10\/linear-regression-in-machine-learning.jpg","author_info":{"display_name":"codeanddebug","author_link":"https:\/\/codeanddebug.in\/blog\/author\/codeanddebug\/"},"_links":{"self":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts\/1161","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/comments?post=1161"}],"version-history":[{"count":3,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts\/1161\/revisions"}],"predecessor-version":[{"id":1181,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts\/1161\/revisions\/1181"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/media\/1160"}],"wp:attachment":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/media?parent=1161"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/categories?post=1161"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/tags?post=1161"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}