{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tensor 张量\n", "Tensor类似于Numpy的ndarray,但不同的是,Tensor可以在GPU上被加速。" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from __future__ import print_function\n", "import torch" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "生成一个未初始化的 5×3 矩阵:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([[0., 0., 0.],\n", " [0., 0., 0.],\n", " [0., 0., 0.],\n", " [0., 0., 0.],\n", " [0., 0., 0.]])\n" ] } ], "source": [ "x = torch.empty(5,3)\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "生成一个随机矩阵:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([[0.4907, 0.1470, 0.9752],\n", " [0.9518, 0.6973, 0.4775],\n", " [0.5643, 0.6586, 0.3142],\n", " [0.2364, 0.8435, 0.6187],\n", " [0.3253, 0.5903, 0.9939]])\n" ] } ], "source": [ "x = torch.rand(5,3)\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "生成一个0矩阵,数据类型为long" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([[0, 0, 0],\n", " [0, 0, 0],\n", " [0, 0, 0],\n", " [0, 0, 0],\n", " [0, 0, 0]])\n" ] } ], "source": [ "x = torch.zeros(5,3,dtype=torch.long)\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "直接从数据创造tensor" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([6.7000, 6.0000, 7.0000])\n" ] } ], "source": [ "x = torch.tensor([6.7,6,7])\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "在已有tensor的基础上创建tensor。这些方法将会继承原tensor的属性,比如数据类型,除非新的值由用户给出。" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x:\n", " tensor([6.7000, 6.0000, 7.0000])\n", "y:\n", " tensor([[1., 1., 1.],\n", " [1., 1., 1.],\n", " [1., 1., 1.],\n", " [1., 1., 1.],\n", " [1., 1., 1.]], dtype=torch.float64)\n", "tensor([-0.3186, 0.5506, 0.4940])\n" ] } ], "source": [ "print('x:\\n',x)\n", "y = x.new_ones(5, 3, dtype=torch.double)\n", "print('y:\\n',y)\n", "\n", "x = torch.randn_like(x, dtype=torch.float) # dtype被改写,但是结果继承了size。\n", "print(x) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "获得tensor的size" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torch.Size([3])\n" ] } ], "source": [ "print(x.size())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Operations 操作\n", "## 相加\n", "PyTorch中有许多种相加语法:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**相加:**语法1" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([[0.9943, 0.3976, 0.6645],\n", " [0.6796, 1.1703, 1.2389],\n", " [1.5879, 1.1208, 1.5912],\n", " [1.2165, 0.8195, 1.0364],\n", " [1.2178, 1.3195, 1.1736]])\n" ] } ], "source": [ "x = torch.rand(5, 3)\n", "y = torch.rand(5, 3)\n", "print(x + y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**相加:**语法2" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([[0.9943, 0.3976, 0.6645],\n", " [0.6796, 1.1703, 1.2389],\n", " [1.5879, 1.1208, 1.5912],\n", " [1.2165, 0.8195, 1.0364],\n", " [1.2178, 1.3195, 1.1736]])\n" ] } ], "source": [ "print(torch.add(x,y))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**相加:**将一个tensor作为out参数,用以输出。" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([[0.9943, 0.3976, 0.6645],\n", " [0.6796, 1.1703, 1.2389],\n", " [1.5879, 1.1208, 1.5912],\n", " [1.2165, 0.8195, 1.0364],\n", " [1.2178, 1.3195, 1.1736]])\n" ] } ], "source": [ "result = torch.empty(5,3)\n", "torch.add(x,y,out=result)\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**相加:**替代" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([[0.9943, 0.3976, 0.6645],\n", " [0.6796, 1.1703, 1.2389],\n", " [1.5879, 1.1208, 1.5912],\n", " [1.2165, 0.8195, 1.0364],\n", " [1.2178, 1.3195, 1.1736]])\n" ] } ], "source": [ "y.add_(x)\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note:\n", "> 任何让tensor被覆盖的方法的名称都以`_`结尾。例如`x.copy_(y)`, `x.t_()`等。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 索引\n", "**NumPy中的索引方法可以使用:**" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([0.0200, 0.4981, 0.2466, 0.7497, 0.8315])\n" ] } ], "source": [ "print(x[:, 1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Resizing \n", "想要改变tensor的规模,可以使用`torch.view`。" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])\n" ] } ], "source": [ "x = torch.randn(4, 4)\n", "y = x.view(16)\n", "z = x.view(-1, 8) # the size -1 is inferred from other dimensions\n", "print(x.size(), y.size(), z.size())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 取值\n", "如果你有一个单元素的tensor,`.item()`方法可以取值。" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([-0.7093])\n", "-0.709314227104187\n" ] } ], "source": [ "x = torch.randn(1)\n", "print(x)\n", "print(x.item())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 与NumPy的沟通桥梁\n", "将Torch张量转换为NumPy数组很容易,反之亦然。\n", "Torch张量将会和NumPy数组共享同一个内存位置(Torch张量在CPU上的情况下),其中一个发生改变,另一个也会随之改变。\n", "## 将Torch Tensor转换为NumPy数组" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([1., 1., 1., 1., 1.])\n", "[1. 1. 1. 1. 1.]\n", "tensor([2., 2., 2., 2., 2.])\n", "[2. 2. 2. 2. 2.]\n" ] } ], "source": [ "a = torch.ones(5)\n", "print(a)\n", "b = a.numpy()\n", "print(b)\n", "a.add_(1)\n", "print(a)\n", "print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 将NumPy数组转换为Torch Tensor" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2. 2. 2. 2. 2.]\n", "tensor([2., 2., 2., 2., 2.], dtype=torch.float64)\n" ] } ], "source": [ "import numpy as np\n", "a = np.ones(5)\n", "b = torch.from_numpy(a)\n", "np.add(a, 1, out=a)\n", "print(a)\n", "print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "除了CharTensor,其他在CPU上的Torch张量均支持与NumPy数组的相互转换。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# CUDA Tensors\n", "使用`.to()`方法,可以将张量转移到其他设备。" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([0.2907], device='cuda:0')\n", "tensor([0.2907], dtype=torch.float64)\n" ] } ], "source": [ "if torch.cuda.is_available():\n", " device = torch.device(\"cuda\") # 创建CUDA设备对象\n", " y = torch.ones_like(x, device=device) # 直接在GPU上\n", " x = x.to(device)\n", " # x = x.to(\"cuda\") 也可以这么写\n", " z = x + y\n", " print(z)\n", " print(z.to(\"cpu\", torch.double)) # ``.to`` 方法可以同时转换数据类型" ] } ], "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.7.0" } }, "nbformat": 4, "nbformat_minor": 2 }