hello_paddle.ipynb 12.6 KB
Notebook
Newer Older
J
jzhang533 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Hello Paddle: 从普通程序走向机器学习程序"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这篇示例向你介绍普通的程序跟机器学习程序的区别,并带着你用飞桨框架,实现你的第一个机器学习程序。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
21
    "## 普通程序跟机器学习程序的逻辑区别\n",
J
jzhang533 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
    "\n",
    "作为一名开发者,你最熟悉的开始学习一门编程语言,或者一个深度学习框架的方式,可能是通过一个hello, world程序。\n",
    "\n",
    "学习飞桨也可以这样,这篇小示例教程将会通过一个非常简单的示例来向你展示如何开始使用飞桨。\n",
    "\n",
    "机器学习程序跟通常的程序最大的不同是,通常的程序是在给定输入的情况下,通过告诉计算机处理数据的规则,然后得到处理后的结果。而机器学习程序则是在并不知道这些规则的情况下,让机器来从数据当中**学习**出来规则。\n",
    "\n",
    "作为热身,我们先来看看通常的程序所做的事情。\n",
    "\n",
    "我们现在面临这样一个任务:\n",
    "\n",
    "我们乘坐出租车的时候,会有一个10元的起步价,只要上车就需要收取。出租车每行驶1公里,需要再支付每公里2元的行驶费用。当一个乘客坐完出租车之后,车上的计价器需要算出来该乘客需要支付的乘车费用。\n",
    "\n",
    "如果用python来实现该功能,会如下所示:"
   ]
  },
  {
   "cell_type": "code",
J
jzhang533 已提交
40
   "execution_count": 22,
J
jzhang533 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "12.0\n",
      "16.0\n",
      "20.0\n",
      "28.0\n",
      "30.0\n",
      "50.0\n"
     ]
    }
   ],
   "source": [
J
jzhang533 已提交
57 58
    "def calculate_fee(distance_travelled):\n",
    "    return 10 + 2 * distance_travelled\n",
J
jzhang533 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
    "\n",
    "for x in [1.0, 3.0, 5.0, 9.0, 10.0, 20.0]:\n",
    "    print(calculate_fee(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来,我们把问题稍微变换一下,现在我们知道乘客每次乘坐出租车的公里数,也知道乘客每次下车的时候支付给出租车司机的总费用。但是并不知道乘车的起步价,以及每公里行驶费用是多少。我们希望让机器从这些数据当中学习出来计算总费用的规则。\n",
    "\n",
    "更具体的,我们想要让机器学习程序通过数据学习出来下面的公式当中的参数w和参数b(这是一个非常简单的示例,所以`w`和`b`都是浮点数,随着对深度学习了解的深入,你将会知道`w`和`b`通常情况下会是矩阵和向量)。这样,当下次乘车的时候,我们知道了行驶里程`distance_travelled`的时候,我们就可以估算出来用户的总费用`total_fee`了。\n",
    "\n",
    "```\n",
    "total_fee = w * distance_travelled + b\n",
    "```\n",
    "\n",
    "接下来,我们看看用飞桨如何实现这个hello, world级别的机器学习程序。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
83
    "## 导入飞桨\n",
J
jzhang533 已提交
84 85 86 87 88 89 90 91 92
    "\n",
    "为了能够使用飞桨,我们需要先用python的`import`语句导入飞桨`paddle`。\n",
    "同时,为了能够更好的对数组进行计算和处理,我们也还需要导入`numpy`。\n",
    "\n",
    "如果你是在本机运行这个notebook,而且还没有安装飞桨,可以去飞桨的官网查看如何安装:[飞桨官网](https://www.paddlepaddle.org.cn/)。并且请使用2.0beta或以上版本的飞桨。"
   ]
  },
  {
   "cell_type": "code",
J
jzhang533 已提交
93
   "execution_count": 3,
J
jzhang533 已提交
94 95 96 97 98 99
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
J
jzhang533 已提交
100
      "paddle 2.0.0-beta0\n"
J
jzhang533 已提交
101 102 103 104 105
     ]
    }
   ],
   "source": [
    "import paddle\n",
J
jzhang533 已提交
106
    "paddle.disable_static()\n",
J
jzhang533 已提交
107
    "print(\"paddle \" + paddle.__version__)"
J
jzhang533 已提交
108 109 110 111 112 113
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
114
    "## 准备数据\n",
J
jzhang533 已提交
115 116 117 118
    "\n",
    "在这个机器学习任务中,我们已经知道了乘客的行驶里程`distance_travelled`,和对应的,这些乘客的总费用`total_fee`。\n",
    "通常情况下,在机器学习任务中,像`distance_travelled`这样的输入值,一般被称为`x`(或者特征`feature`),像`total_fee`这样的输出值,一般被称为`y`(或者标签`label`)。\n",
    "\n",
J
jzhang533 已提交
119
    "我们用`paddle.to_tensor`把示例数据转换为paddle的Tensor数据。"
J
jzhang533 已提交
120 121 122 123
   ]
  },
  {
   "cell_type": "code",
J
jzhang533 已提交
124
   "execution_count": 4,
J
jzhang533 已提交
125 126
   "metadata": {},
   "outputs": [],
J
jzhang533 已提交
127
   "source": [
J
jzhang533 已提交
128 129
    "x_data = paddle.to_tensor([[1.], [3.0], [5.0], [9.0], [10.0], [20.0]])\n",
    "y_data = paddle.to_tensor([[12.], [16.0], [20.0], [28.0], [30.0], [50.0]])"
J
jzhang533 已提交
130 131 132 133 134 135
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
136
    "## 用飞桨定义模型的计算\n",
J
jzhang533 已提交
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
    "\n",
    "使用飞桨定义模型的计算的过程,本质上,是我们用python,通过飞桨提供的API,来告诉飞桨我们的计算规则的过程。回顾一下,我们想要通过飞桨用机器学习方法,从数据当中学习出来如下公式当中的`w`和`b`。这样在未来,给定`x`时就可以估算出来`y`值(估算出来的`y`记为`y_predict`)\n",
    "\n",
    "```\n",
    "y_predict = w * x + b\n",
    "```\n",
    "\n",
    "我们将会用飞桨的线性变换层:`paddle.nn.Linear`来实现这个计算过程,这个公式里的变量`x, y, w, b, y_predict`,对应着飞桨里面的[Tensor概念](https://www.paddlepaddle.org.cn/documentation/docs/zh/beginners_guide/basic_concept/tensor.html)。\n",
    "\n",
    "### 稍微补充一下\n",
    "\n",
    "在这里的示例中,我们根据经验,已经事先知道了`distance_travelled`和`total_fee`之间是线性的关系,而在更实际的问题当中,`x`和`y`的关系通常是非线性的,因此也就需要使用更多类型,也更复杂的神经网络。(比如,BMI指数跟你的身高就不是线性关系,一张图片里的某个像素值跟这个图片是猫还是狗也不是线性关系。)\n"
   ]
  },
  {
   "cell_type": "code",
J
jzhang533 已提交
153
   "execution_count": 5,
J
jzhang533 已提交
154 155 156
   "metadata": {},
   "outputs": [],
   "source": [
J
jzhang533 已提交
157
    "linear = paddle.nn.Linear(in_features=1, out_features=1)"
J
jzhang533 已提交
158 159 160 161 162 163
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
164
    "## 准备好运行飞桨\n",
J
jzhang533 已提交
165
    "\n",
J
jzhang533 已提交
166
    "机器(计算机)在一开始的时候会随便猜`w`和`b`,我们先看看机器猜的怎么样。你应该可以看到,这时候的`w`是一个随机值,`b`是0.0,这是飞桨的初始化策略,也是这个领域常用的初始化策略。(如果你愿意,也可以采用其他的初始化的方式,今后你也会看到,选择不同的初始化策略也是对于做好深度学习任务来说很重要的一点)。"
J
jzhang533 已提交
167 168 169 170
   ]
  },
  {
   "cell_type": "code",
J
jzhang533 已提交
171
   "execution_count": 6,
J
jzhang533 已提交
172 173 174 175 176 177
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
J
jzhang533 已提交
178
      "w before optimize: -1.696260690689087\n",
J
jzhang533 已提交
179 180 181 182 183
      "b before optimize: 0.0\n"
     ]
    }
   ],
   "source": [
J
jzhang533 已提交
184 185
    "w_before_opt = linear.weight.numpy().item()\n",
    "b_before_opt = linear.bias.numpy().item()\n",
J
jzhang533 已提交
186 187
    "\n",
    "print(\"w before optimize: {}\".format(w_before_opt))\n",
J
jzhang533 已提交
188
    "print(\"b before optimize: {}\".format(b_before_opt))"
J
jzhang533 已提交
189 190 191 192 193 194
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
195
    "## 告诉飞桨怎么样学习\n",
J
jzhang533 已提交
196 197 198 199 200 201 202
    "\n",
    "前面我们定义好了神经网络(尽管是一个最简单的神经网络),我们还需要告诉飞桨,怎么样去**学习**,从而能得到参数`w`和`b`。\n",
    "\n",
    "这个过程简单的来陈述一下,你应该就会大致明白了(尽管背后的理论和知识还需要逐步的去学习)。在机器学习/深度学习当中,机器(计算机)在最开始的时候,得到参数`w`和`b`的方式是随便猜一下,用这种随便猜测得到的参数值,去进行计算(预测)的时候,得到的`y_predict`,跟实际的`y`值一定是有**差距**的。接下来,机器会根据这个差距来**调整`w`和`b`**,随着这样的逐步的调整,`w`和`b`会越来越正确,`y_predict`跟`y`之间的差距也会越来越小,从而最终能得到好用的`w`和`b`。这个过程就是机器**学习**的过程。\n",
    "\n",
    "用更加技术的语言来说,衡量**差距**的函数(一个公式)就是损失函数,用来**调整**参数的方法就是优化算法。\n",
    "\n",
J
jzhang533 已提交
203
    "在本示例当中,我们用最简单的均方误差(mean square error)作为损失函数(`paddle.nn.MSELoss`);和最常见的优化算法SGD(stocastic gradient descent)作为优化算法(传给`paddle.optimizer.SGD`的参数`learning_rate`,你可以理解为控制每次调整的步子大小的参数)。"
J
jzhang533 已提交
204 205 206 207
   ]
  },
  {
   "cell_type": "code",
J
jzhang533 已提交
208
   "execution_count": 7,
J
jzhang533 已提交
209 210 211 212
   "metadata": {},
   "outputs": [],
   "source": [
    "mse_loss = paddle.nn.MSELoss()\n",
J
jzhang533 已提交
213
    "sgd_optimizer = paddle.optimizer.SGD(learning_rate=0.001, parameters = linear.parameters())"
J
jzhang533 已提交
214 215 216 217 218 219
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
220
    "## 运行优化算法\n",
J
jzhang533 已提交
221
    "\n",
J
jzhang533 已提交
222
    "接下来,我们让飞桨运行一下这个优化算法,这会是一个前面介绍过的逐步调整参数的过程,你应该可以看到loss值(衡量`y`和`y_predict`的差距的`loss`)在不断的降低。"
J
jzhang533 已提交
223 224 225 226
   ]
  },
  {
   "cell_type": "code",
J
jzhang533 已提交
227
   "execution_count": 8,
J
jzhang533 已提交
228 229 230 231 232 233
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
J
jzhang533 已提交
234 235 236 237 238 239
      "epoch 0 loss [2094.069]\n",
      "epoch 1000 loss [7.8451133]\n",
      "epoch 2000 loss [1.7541145]\n",
      "epoch 3000 loss [0.39221546]\n",
      "epoch 4000 loss [0.08769739]\n",
      "finished training, loss [0.0196382]\n"
J
jzhang533 已提交
240 241 242 243
     ]
    }
   ],
   "source": [
J
jzhang533 已提交
244 245 246 247
    "total_epoch = 5000\n",
    "for i in range(total_epoch):\n",
    "    y_predict = linear(x_data)\n",
    "    loss = mse_loss(y_predict, y_data)\n",
J
jzhang533 已提交
248
    "    loss.backward()\n",
J
jzhang533 已提交
249 250
    "    sgd_optimizer.step()\n",
    "    sgd_optimizer.clear_grad()\n",
J
jzhang533 已提交
251 252
    "    \n",
    "    if i%1000 == 0:\n",
J
jzhang533 已提交
253
    "        print(\"epoch {} loss {}\".format(i, loss.numpy()))\n",
J
jzhang533 已提交
254
    "        \n",
J
jzhang533 已提交
255
    "print(\"finished training, loss {}\".format(loss.numpy()))"
J
jzhang533 已提交
256 257 258 259 260 261
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
262
    "## 机器学习出来的参数\n",
J
jzhang533 已提交
263 264 265 266 267 268
    "\n",
    "经过了这样的对参数`w`和`b`的调整(**学习**),我们再通过下面的程序,来看看现在的参数变成了多少。你应该会发现`w`变成了很接近2.0的一个值,`b`变成了接近10.0的一个值。虽然并不是正好的2和10,但却是从数据当中学习出来的还不错的模型的参数,可以在未来的时候,用从这批数据当中学习到的参数来预估了。(如果你愿意,也可以通过让机器多学习一段时间,从而得到更加接近2.0和10.0的参数值。)"
   ]
  },
  {
   "cell_type": "code",
J
jzhang533 已提交
269
   "execution_count": 9,
J
jzhang533 已提交
270 271 272 273 274 275
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
J
jzhang533 已提交
276 277
      "w after optimize: 2.0178451538085938\n",
      "b after optimize: 9.771825790405273\n"
J
jzhang533 已提交
278 279 280 281
     ]
    }
   ],
   "source": [
J
jzhang533 已提交
282 283
    "w_after_opt = linear.weight.numpy().item()\n",
    "b_after_opt = linear.bias.numpy().item()\n",
J
jzhang533 已提交
284 285 286 287 288 289 290 291 292
    "\n",
    "print(\"w after optimize: {}\".format(w_after_opt))\n",
    "print(\"b after optimize: {}\".format(b_after_opt))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
293
    "## hello paddle\n",
J
jzhang533 已提交
294 295 296 297 298 299
    "\n",
    "通过这个小示例,希望你已经初步了解了飞桨,能在接下来随着对飞桨的更多学习,来解决实际遇到的问题。"
   ]
  },
  {
   "cell_type": "code",
J
jzhang533 已提交
300
   "execution_count": 10,
J
jzhang533 已提交
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello paddle\n"
     ]
    }
   ],
   "source": [
    "print(\"hello paddle\")"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "hello-paddle.ipynb",
   "private_outputs": true,
   "provenance": [],
   "toc_visible": true
  },
  "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",
338
   "version": "3.7.3"
J
jzhang533 已提交
339 340 341
  }
 },
 "nbformat": 4,
J
jzhang533 已提交
342
 "nbformat_minor": 4
J
jzhang533 已提交
343
}