#!/usr/bin/env python # coding: utf-8 # 正文开始: # # 1. 第一章 - 基本概念: Var # 目录: # * 1.1 Var 的基本介绍 # * 1.2 如何生成 Var # * 1.3 Var 的常见属性 # * 1.4 Var 的常见操作 # * 1.5 Var 的运算 # * 1.6 与 NumPy 的相互转化 # ## 1.1 Var 的基本介绍 # Var:计图的基本数据类型 # # 在计图 (Jittor) - 开源深度学习框架中,Var 类型是最基本的数据类型。计图的所有操作,都将基于 Var 进行。所以,学习并掌握 Var 是使用计图的第一步。请不要感到畏难,我们之所以引入 Var 类型,是为了优化深度学习的计算能力与效率,目的是方便您更加高效地进行开发,请您尽情享受。 # # 简单来说,Var 是一种特殊的数据结构,它与数组和矩阵非常相似。您可简单理解为,一维 Var 即是数组,二维 Var 即是矩阵。在计图中,我们使用 Var 来编码模型的输入和输出,以及模型的参数。 # # **计图的 Var 与 NumPy 的 ndarray 极其相似**,但 Var 可以在 GPU 或其他专用硬件上运行,以加速计算。如果您熟悉 ndarray,您就会十分熟悉 Var 的相关操作。如果没有,请按照本教程,对 Var 类型进行快速演练。本教程已覆盖 Var 的基础操作,可以基本满足您的开发需求。如您想要更加深入了解并灵活使用 Var,敬请查阅我们的 [API 文档](https://cg.cs.tsinghua.edu.cn/jittor/assets/docs/index.html)。 # # ## 1.2 如何生成 Var # 首先,我们在 Python 中导入计图: # In[1]: import jittor as jt # **从 “普通数据” 导入生成 Var** # In[5]: data = [[1, 2],[3, 4],[5, 6]] # 生成一个普通的列表 print("data: \n", data) var_data = jt.array(data) # 通过列表生成 Var print("var_data: \n", var_data) print("var_data的类型是:", type(var_data)) # 打印类型,可以发现生成的是jittor.Var var_data = jt.Var(data) # 当然,jittor.Var也可以直接使用 # **从 “NumPy 数组” 导入生成 Var** # In[3]: import numpy as np np_array = np.array([[1, 2],[3, 4],[5, 6]]) # 生成一个 NumPy 的数组 print("np_array: \n", np_array) var_np_array=jt.array(np_array) # 通过 NumPy 的数组生成 Var print("var_np_array: \n", var_np_array) # **从 “其他 Var 数据” 导入生成新的 Var** # In[7]: # 准备一个原始的 Var var_data = jt.Var([[1, 2],[3, 4],[5, 6]]) # 生成一个形状相同,元素全为 0 的 Var var_zeros = jt.zeros_like(var_data) print("Zeros Var: \n", var_zeros) # 生成一个形状相同,元素全为 1 的 Var var_ones = jt.ones_like(var_data) print("Ones Var: \n", var_ones) # 生成一个形状相同,并指定元素值的 Var var_full = jt.full_like(var_data, 5) print("full Var: \n", var_full) # 生成一个形状相同,元素为随机数的 Var var_rand = jt.rand(var_data.shape, dtype=jt.float) # 重写元素数据类型 print("Random Var: \n", var_rand) # **生成一些特定的 Var** # In[8]: shape = (3,4,) # 指定将要生成 Var 的形状 rand_var = jt.rand(shape) # 生成元素为随机数的 Var ones_var = jt.ones(shape) # 生成元素全为 1 的 Var zeros_var = jt.zeros(shape) # 生成元素全为 0 的 Var print("Random Var: \n", rand_var) print("Ones Var: \n", ones_var) print("Zeros Var: \n", zeros_var) arange_var1 = jt.arange(9) # 生成元素为等差数组的一维 Var (只指定一个结束参数) arange_var2 = jt.arange(0, 9, 2) # 生成元素为等差数组的一维 Var (指定起始、结束、步长) print("Arange Var 1: \n", arange_var1) print("Arange Var 2: \n", arange_var2) # ## 1.3 Var 的常见属性 # **Var 的形状:** 通过 var.shape 查看 # In[9]: var = jt.array([[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]]) print("Var: \n", var) print("Shape of Var: \n", var.shape) # **Var 的数据类型:** 通过 var.dtype 查看 # In[8]: var = jt.ones((3,4)) print("Var: \n", var) print("Datatype of Var: \n", var.dtype) # ## 1.4 Var 的常见操作 # **重塑形状 Reshape** # In[9]: var1 = jt.arange(27) # 创建一个元素为 0-26 的一维 Var1 print("Var1: \n", var1) print("Shape of Var1: \n", var1.shape) var2 = var1.reshape(3,3,3) # 将 Var1 重塑形状为 3*3*3 的 Var2 print("Var2: \n", var2) print("Shape of Var2: \n", var2.shape) var3 = var2.reshape(3,-1) # 参数值为 -1,代表将根据其他形状参数自动计算出合适的值,再进行重塑形状 print("Var3: \n", var3) print("Shape of Var3: \n", var3.shape) # **转置 Transpose** # * 矩阵转置 # In[10]: # (提示:这里我们用 arange 初始化一个 0 到 11 的一维 Var,然后通过 reshape 将其转化为 4*3 的 Var1。) var1 = jt.arange(12).reshape(4,3) # 创建一个 4*3 的二维矩阵 Var1 print("Var1: \n", var1) print("Shape of Var1: \n", var1.shape) var1_t = var1.transpose() # 矩阵转置成 3*4 的二维矩阵 Var1 Transpose print("Var1 Transpose: \n", var1_t) print("Shape of Var1 Transpose: \n", var1_t.shape) # * 指定轴转置(较难) # In[11]: var1 = jt.arange(24).reshape(2,3,4) # 创建一个 2*3*4 的三维 Var1 print("Var1: \n", var1) # 其含义为,第一个轴上 2 个元素;第二个轴上 3 个元素;第三个轴上 4 个元素。 print("Shape of Var1: \n", var1.shape) var1_t = var1.transpose(0,2,1) # 根据轴索引转置。三维轴索引为 0,1,2,调整索引顺序即代表对应轴调整顺序。 print("Var1 Transpose: \n", var1_t) # 从默认的“0,1,2”调整为“0,2,1”,即代表后两轴进行互换。 print("Shape of Var1 Transpose: \n", var1_t.shape) # 互换后,第一个轴上 2 个元素;第二个轴上 4 个元素;第三个轴上 3 个元素。 # **切片和索引** # In[12]: var = jt.arange(9).reshape(3,3) # 初始化一个 3*3 的 Var print(1, "Var: \n", var) var[:,1] = 0 # 利用切片,将任意行的第二个元素(即第二列)重置为 0 print(2, "Var: \n", var) line_2 = var[1] # 利用索引,拿到第二行元素 print(3, "Line 2 in Var: \n", line_2) # **原地操作** # 在计图中,我们使用 assign() 函数实现在原变量上直接操作。 # In[13]: var0 = jt.arange(6).reshape(2,3) # 初始化一个 2*3 的 Var0 print(0, "Var0: \n", var0) # 打印查看 Var0 var1 = var0.add(1) # 使 Var1 等于 Var0 上每个元素加 1 print(1, "Var1: \n", var1) # 打印发现 Var1 赋值成功 print(1, "Var0: \n", var0) # 但 Var0 并没有发生变化 var2 = var0.assign(var0.add(1)) # 利用 assign() 函数,使 Var2 等于 Var0 上每个元素加 1 print(2, "Var2: \n", var2) # 打印发现 Var2 赋值成功 print(2, "Var0: \n", var0) # 同时 Var0 也发生了改变 var3 = var0.transpose() # 使 Var3 等于 Var0 的转置 print(3, "Var3: \n", var3) # 打印发现 Var3 赋值成功 print(3, "Var0: \n", var0) # 但 Var0 并没有发生变化 var4 = var0.assign(var0.transpose()) # 利用 assign() 函数,使 Var4 等于 Var0 的转置 print(4, "Var4: \n", var4) # 打印发现 Var4 赋值成功 print(4, "Var0: \n", var0) # 同时 Var0 也发生了改变 # ## 1.5 Var 的运算 # **开启 GPU 加速** # 在计图中,开启 GPU 加速的方式非常简单。我们使用 jt.flags.use_cuda 表示是否使用 GPU 训练。 # # # * 如果 jt.flags.use_cuda = 0,表示使用 CPU 训练; # * 如果 jt.flags.use_cuda = 1,表示使用 GPU 训练。 # In[14]: jt.flags.use_cuda = 1 # 使用 GPU 训练 # **Var 的加法和连接** # In[15]: # 初始化两个Var var1 = jt.arange(9).reshape(3,3) var2 = jt.ones((3,3)) print("var1: \n", var1) print("var2: \n", var2) # In[16]: # Var 与实数相加 var3 = var1 + 3 print("var3: \n", var3) # 两个 Var 相加 var4 = var1 + var2 print("var4: \n", var4) # 连接两个 Var var5 = jt.concat([var1, var2], dim=1) print("var5: \n", var5) # **Var 的乘法:标量相乘 / 矩阵相乘** # In[17]: # 初始化两个Var var1 = jt.arange(9).reshape(3,3) var2 = jt.ones((3,3)) print("var1: \n", var1) print("var2: \n", var2) # * **Var 与实数相乘:** # In[18]: # Var 与实数相乘 var3 = var1 * 3 print("var3: \n", var3) # * **两个 Var 标量相乘:** # In[19]: # 标量相乘 方式一 var4 = var1 * var2 print("var4: \n", var4) # 标量相乘 方式二 var5 = var1.multiply(var2) print("var5: \n", var5) # 标量相乘 方式三 var6 = jt.multiply(var1, var2) print("var6: \n", var6) # * **两个 Var 矩阵相乘:** # In[20]: # 矩阵相乘 方式一 var7 = var1 @ var2 print("var7: \n", var7) # 矩阵相乘 方式二 var8 = var1.matmul(var2) print("var8: \n", var8) # 矩阵相乘 方式三 var9 = jt.matmul(var1, var2) print("var9: \n", var9) # ## 1.6 与 NumPy 的相互转化 # **从 Var 转化成 NumPy 数组** # In[21]: # 新建一个 Var var = jt.ones((4,5)) print("var: \n", var) print("type(var):", type(var)) # 将其转化为 NumPy 数组 ndarray = var.numpy() print("ndarray: \n", ndarray) print("type(ndarray):", type(ndarray)) # **从 NumPy 数组转化成 Var** # In[22]: # 新建一个 NumPy 数组 ndarray = np.ones((4,5)) print("ndarray: \n", ndarray) print("type(ndarray):", type(ndarray)) # 将其转化为 Var 类型 var = jt.array(ndarray) print("var: \n", var) print("type(var):", type(var)) # # 📣 # 至此,第一章 - 基本概念: Var - 结束! # # 恭喜您!已成功解锁了 Jittor (计图) 最核心、最基本的数据类型 - Var 类型的基本使用。 # # 在掌握了 Var 类型的基本操作之后,您只需要进一步熟悉神经网络训练的一般模式,便可以利用 Jittor 解决更高阶、更实战的问题。 # 请不要停下脚步,只差一点点,你就可以轻松地用 Jittor 来进行神经网络的训练啦!