Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ikanher/c349b802d904ffccb863d750eec8eea9 to your computer and use it in GitHub Desktop.
Save ikanher/c349b802d904ffccb863d750eec8eea9 to your computer and use it in GitHub Desktop.
Gradient descent bias convergence problem (convert celcius to f)
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt\n",
"import numpy as np\n",
"import torch\n",
"from torch import nn, optim\n",
"dtype = torch.float\n",
"device = torch.device(\"cpu\")\n",
"#device = torch.device(\"cuda:0\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.4.0\n"
]
}
],
"source": [
"print(torch.__version__)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# convert from celcius to fahrenheit: T(°F) = T(°C) × 9/5 + 32\n",
"def c_to_f(celcius):\n",
" return celcius * 9/5 + 32"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"#x = np.array([[-15], [-11], [-10], [-7], [-2], [0], [3], [17], [15], [25], [60], [84], [120]], dtype=np.float32)\n",
"x = np.array([ [c] for c in np.random.randint(-500, high=500, size=2000)], dtype=np.float32)\n",
"\n",
"# multiplying by some random * 50 just to add some noise\n",
"y = np.array([ c_to_f(c) + np.random.randn() * 50 for c in x], dtype=np.float32)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0,0.5,'y')"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.scatter(x, y, s=0.1)\n",
"plt.xlabel(\"x\"); plt.ylabel(\"y\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"x_train = torch.from_numpy(x)\n",
"y_train = torch.from_numpy(y)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"lr = 1e-6"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def lin(a, b, x):\n",
" return a * x + b"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def mse_loss(y_pred, y):\n",
" return (y_pred - y).pow(2).mean()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"a = torch.randn(1, device=device, dtype=dtype, requires_grad=True)\n",
"b = torch.randn(1, device=device, dtype=dtype, requires_grad=True)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 loss: tensor(1.00000e+05 *\n",
" 6.6192) a: tensor([-1.0054]) b: tensor([-0.5949])\n",
"100 loss: tensor(3574.2202) a: tensor([ 1.8045]) b: tensor([-0.5883])\n",
"200 loss: tensor(3573.7935) a: tensor([ 1.8045]) b: tensor([-0.5818])\n",
"300 loss: tensor(3573.3669) a: tensor([ 1.8045]) b: tensor([-0.5752])\n",
"400 loss: tensor(3572.9404) a: tensor([ 1.8045]) b: tensor([-0.5687])\n",
"500 loss: tensor(3572.5142) a: tensor([ 1.8045]) b: tensor([-0.5622])\n",
"600 loss: tensor(3572.0896) a: tensor([ 1.8045]) b: tensor([-0.5556])\n",
"700 loss: tensor(3571.6636) a: tensor([ 1.8045]) b: tensor([-0.5491])\n",
"800 loss: tensor(3571.2375) a: tensor([ 1.8045]) b: tensor([-0.5426])\n",
"900 loss: tensor(3570.8120) a: tensor([ 1.8045]) b: tensor([-0.5361])\n",
"1000 loss: tensor(3570.3865) a: tensor([ 1.8045]) b: tensor([-0.5295])\n",
"1100 loss: tensor(3569.9607) a: tensor([ 1.8045]) b: tensor([-0.5230])\n",
"1200 loss: tensor(3569.5356) a: tensor([ 1.8045]) b: tensor([-0.5165])\n",
"1300 loss: tensor(3569.1104) a: tensor([ 1.8045]) b: tensor([-0.5100])\n",
"1400 loss: tensor(3568.6865) a: tensor([ 1.8045]) b: tensor([-0.5035])\n",
"1500 loss: tensor(3568.2620) a: tensor([ 1.8045]) b: tensor([-0.4969])\n",
"1600 loss: tensor(3567.8374) a: tensor([ 1.8045]) b: tensor([-0.4904])\n",
"1700 loss: tensor(3567.4141) a: tensor([ 1.8045]) b: tensor([-0.4839])\n",
"1800 loss: tensor(3566.9895) a: tensor([ 1.8045]) b: tensor([-0.4774])\n",
"1900 loss: tensor(3566.5649) a: tensor([ 1.8045]) b: tensor([-0.4709])\n",
"2000 loss: tensor(3566.1423) a: tensor([ 1.8045]) b: tensor([-0.4644])\n",
"2100 loss: tensor(3565.7185) a: tensor([ 1.8045]) b: tensor([-0.4579])\n",
"2200 loss: tensor(3565.2944) a: tensor([ 1.8045]) b: tensor([-0.4514])\n",
"2300 loss: tensor(3564.8718) a: tensor([ 1.8045]) b: tensor([-0.4449])\n",
"2400 loss: tensor(3564.4482) a: tensor([ 1.8045]) b: tensor([-0.4384])\n",
"2500 loss: tensor(3564.0264) a: tensor([ 1.8045]) b: tensor([-0.4319])\n",
"2600 loss: tensor(3563.6028) a: tensor([ 1.8045]) b: tensor([-0.4254])\n",
"2700 loss: tensor(3563.1812) a: tensor([ 1.8045]) b: tensor([-0.4189])\n",
"2800 loss: tensor(3562.7581) a: tensor([ 1.8045]) b: tensor([-0.4124])\n",
"2900 loss: tensor(3562.3364) a: tensor([ 1.8045]) b: tensor([-0.4059])\n",
"3000 loss: tensor(3561.9133) a: tensor([ 1.8045]) b: tensor([-0.3994])\n",
"3100 loss: tensor(3561.4927) a: tensor([ 1.8045]) b: tensor([-0.3929])\n",
"3200 loss: tensor(3561.0698) a: tensor([ 1.8045]) b: tensor([-0.3864])\n",
"3300 loss: tensor(3560.6489) a: tensor([ 1.8045]) b: tensor([-0.3799])\n",
"3400 loss: tensor(3560.2280) a: tensor([ 1.8045]) b: tensor([-0.3734])\n",
"3500 loss: tensor(3559.8062) a: tensor([ 1.8045]) b: tensor([-0.3669])\n",
"3600 loss: tensor(3559.3853) a: tensor([ 1.8045]) b: tensor([-0.3604])\n",
"3700 loss: tensor(3558.9653) a: tensor([ 1.8045]) b: tensor([-0.3539])\n",
"3800 loss: tensor(3558.5447) a: tensor([ 1.8045]) b: tensor([-0.3474])\n",
"3900 loss: tensor(3558.1233) a: tensor([ 1.8045]) b: tensor([-0.3410])\n",
"4000 loss: tensor(3557.7031) a: tensor([ 1.8045]) b: tensor([-0.3345])\n",
"4100 loss: tensor(3557.2834) a: tensor([ 1.8045]) b: tensor([-0.3280])\n",
"4200 loss: tensor(3556.8635) a: tensor([ 1.8045]) b: tensor([-0.3215])\n",
"4300 loss: tensor(3556.4441) a: tensor([ 1.8045]) b: tensor([-0.3150])\n",
"4400 loss: tensor(3556.0232) a: tensor([ 1.8044]) b: tensor([-0.3086])\n",
"4500 loss: tensor(3555.6040) a: tensor([ 1.8044]) b: tensor([-0.3021])\n",
"4600 loss: tensor(3555.1843) a: tensor([ 1.8044]) b: tensor([-0.2956])\n",
"4700 loss: tensor(3554.7654) a: tensor([ 1.8044]) b: tensor([-0.2891])\n",
"4800 loss: tensor(3554.3467) a: tensor([ 1.8044]) b: tensor([-0.2827])\n",
"4900 loss: tensor(3553.9277) a: tensor([ 1.8044]) b: tensor([-0.2762])\n"
]
}
],
"source": [
"n_epochs = 5000\n",
"for epoch in range(n_epochs):\n",
" \n",
" # compute loss\n",
" loss = mse_loss(lin(a, b, x_train), y_train)\n",
"\n",
" # backpropagate a and b\n",
" loss.backward()\n",
"\n",
" if epoch % 100 == 0:\n",
" print(epoch, \"loss: \", loss, \"a: \" , a, \"b: \", b)\n",
" \n",
" with torch.no_grad():\n",
" a -= lr * a.grad\n",
" b -= lr * b.grad\n",
" #print(\"Reducing bias with respect to bias gradient: \", b.grad, \" new bias: \", b)\n",
" \n",
" # zero gradient\n",
" a.grad.zero_()\n",
" b.grad.zero_()\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from matplotlib import pyplot as plt\n",
"import numpy as np\n",
"import torch\n",
"from torch import nn, optim\n",
"dtype = torch.float\n",
"device = torch.device(\"cpu\")\n",
"#device = torch.device(\"cuda:0\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.4.0\n"
]
}
],
"source": [
"print(torch.__version__)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# convert from celcius to fahrenheit: T(°F) = T(°C) × 9/5 + 32\n",
"def c_to_f(celcius):\n",
" return celcius * 9/5 + 32"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"#x = np.array([[-15], [-11], [-10], [-7], [-2], [0], [3], [17], [15], [25], [60], [84], [120]], dtype=np.float32)\n",
"x = np.array([ [c] for c in np.random.randint(-500, high=500, size=2000)], dtype=np.float32)\n",
"\n",
"# multiplying by some random * 50 just to add some noise\n",
"y = np.array([ c_to_f(c) + np.random.randn() * 50 for c in x], dtype=np.float32)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Text(0,0.5,'y')"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.scatter(x, y, s=0.1)\n",
"plt.xlabel(\"x\"); plt.ylabel(\"y\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"x_train = torch.from_numpy(x)\n",
"y_train = torch.from_numpy(y)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"lr = 1e-6"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def lin(a, b, x):\n",
" return a * x + b"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def mse_loss(y_pred, y):\n",
" return (y_pred - y).pow(2).mean()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"a = torch.randn(1, device=device, dtype=dtype, requires_grad=True)\n",
"b = torch.randn(1, device=device, dtype=dtype, requires_grad=True)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 loss: tensor(1.00000e+05 *\n",
" 6.6192) a: tensor([-1.0054]) b: tensor([-0.5949])\n",
"100 loss: tensor(3574.2202) a: tensor([ 1.8045]) b: tensor([-0.5883])\n",
"200 loss: tensor(3573.7935) a: tensor([ 1.8045]) b: tensor([-0.5818])\n",
"300 loss: tensor(3573.3669) a: tensor([ 1.8045]) b: tensor([-0.5752])\n",
"400 loss: tensor(3572.9404) a: tensor([ 1.8045]) b: tensor([-0.5687])\n",
"500 loss: tensor(3572.5142) a: tensor([ 1.8045]) b: tensor([-0.5622])\n",
"600 loss: tensor(3572.0896) a: tensor([ 1.8045]) b: tensor([-0.5556])\n",
"700 loss: tensor(3571.6636) a: tensor([ 1.8045]) b: tensor([-0.5491])\n",
"800 loss: tensor(3571.2375) a: tensor([ 1.8045]) b: tensor([-0.5426])\n",
"900 loss: tensor(3570.8120) a: tensor([ 1.8045]) b: tensor([-0.5361])\n",
"1000 loss: tensor(3570.3865) a: tensor([ 1.8045]) b: tensor([-0.5295])\n",
"1100 loss: tensor(3569.9607) a: tensor([ 1.8045]) b: tensor([-0.5230])\n",
"1200 loss: tensor(3569.5356) a: tensor([ 1.8045]) b: tensor([-0.5165])\n",
"1300 loss: tensor(3569.1104) a: tensor([ 1.8045]) b: tensor([-0.5100])\n",
"1400 loss: tensor(3568.6865) a: tensor([ 1.8045]) b: tensor([-0.5035])\n",
"1500 loss: tensor(3568.2620) a: tensor([ 1.8045]) b: tensor([-0.4969])\n",
"1600 loss: tensor(3567.8374) a: tensor([ 1.8045]) b: tensor([-0.4904])\n",
"1700 loss: tensor(3567.4141) a: tensor([ 1.8045]) b: tensor([-0.4839])\n",
"1800 loss: tensor(3566.9895) a: tensor([ 1.8045]) b: tensor([-0.4774])\n",
"1900 loss: tensor(3566.5649) a: tensor([ 1.8045]) b: tensor([-0.4709])\n",
"2000 loss: tensor(3566.1423) a: tensor([ 1.8045]) b: tensor([-0.4644])\n",
"2100 loss: tensor(3565.7185) a: tensor([ 1.8045]) b: tensor([-0.4579])\n",
"2200 loss: tensor(3565.2944) a: tensor([ 1.8045]) b: tensor([-0.4514])\n",
"2300 loss: tensor(3564.8718) a: tensor([ 1.8045]) b: tensor([-0.4449])\n",
"2400 loss: tensor(3564.4482) a: tensor([ 1.8045]) b: tensor([-0.4384])\n",
"2500 loss: tensor(3564.0264) a: tensor([ 1.8045]) b: tensor([-0.4319])\n",
"2600 loss: tensor(3563.6028) a: tensor([ 1.8045]) b: tensor([-0.4254])\n",
"2700 loss: tensor(3563.1812) a: tensor([ 1.8045]) b: tensor([-0.4189])\n",
"2800 loss: tensor(3562.7581) a: tensor([ 1.8045]) b: tensor([-0.4124])\n",
"2900 loss: tensor(3562.3364) a: tensor([ 1.8045]) b: tensor([-0.4059])\n",
"3000 loss: tensor(3561.9133) a: tensor([ 1.8045]) b: tensor([-0.3994])\n",
"3100 loss: tensor(3561.4927) a: tensor([ 1.8045]) b: tensor([-0.3929])\n",
"3200 loss: tensor(3561.0698) a: tensor([ 1.8045]) b: tensor([-0.3864])\n",
"3300 loss: tensor(3560.6489) a: tensor([ 1.8045]) b: tensor([-0.3799])\n",
"3400 loss: tensor(3560.2280) a: tensor([ 1.8045]) b: tensor([-0.3734])\n",
"3500 loss: tensor(3559.8062) a: tensor([ 1.8045]) b: tensor([-0.3669])\n",
"3600 loss: tensor(3559.3853) a: tensor([ 1.8045]) b: tensor([-0.3604])\n",
"3700 loss: tensor(3558.9653) a: tensor([ 1.8045]) b: tensor([-0.3539])\n",
"3800 loss: tensor(3558.5447) a: tensor([ 1.8045]) b: tensor([-0.3474])\n",
"3900 loss: tensor(3558.1233) a: tensor([ 1.8045]) b: tensor([-0.3410])\n",
"4000 loss: tensor(3557.7031) a: tensor([ 1.8045]) b: tensor([-0.3345])\n",
"4100 loss: tensor(3557.2834) a: tensor([ 1.8045]) b: tensor([-0.3280])\n",
"4200 loss: tensor(3556.8635) a: tensor([ 1.8045]) b: tensor([-0.3215])\n",
"4300 loss: tensor(3556.4441) a: tensor([ 1.8045]) b: tensor([-0.3150])\n",
"4400 loss: tensor(3556.0232) a: tensor([ 1.8044]) b: tensor([-0.3086])\n",
"4500 loss: tensor(3555.6040) a: tensor([ 1.8044]) b: tensor([-0.3021])\n",
"4600 loss: tensor(3555.1843) a: tensor([ 1.8044]) b: tensor([-0.2956])\n",
"4700 loss: tensor(3554.7654) a: tensor([ 1.8044]) b: tensor([-0.2891])\n",
"4800 loss: tensor(3554.3467) a: tensor([ 1.8044]) b: tensor([-0.2827])\n",
"4900 loss: tensor(3553.9277) a: tensor([ 1.8044]) b: tensor([-0.2762])\n"
]
}
],
"source": [
"n_epochs = 5000\n",
"for epoch in range(n_epochs):\n",
" \n",
" # compute loss\n",
" loss = mse_loss(lin(a, b, x_train), y_train)\n",
"\n",
" # backpropagate a and b\n",
" loss.backward()\n",
"\n",
" if epoch % 100 == 0:\n",
" print(epoch, \"loss: \", loss, \"a: \" , a, \"b: \", b)\n",
" \n",
" with torch.no_grad():\n",
" a -= lr * a.grad\n",
" b -= lr * b.grad\n",
" #print(\"Reducing bias with respect to bias gradient: \", b.grad, \" new bias: \", b)\n",
" \n",
" # zero gradient\n",
" a.grad.zero_()\n",
" b.grad.zero_()\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment