#!/usr/bin/env python
# coding: utf-8

# [![下载Notebook](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.9.0/resource/_static/logo_notebook.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/r2.9.0/tutorials/zh_cn/beginner/mindspore_tensor.ipynb)&emsp;[![下载样例代码](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.9.0/resource/_static/logo_download_code.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/r2.9.0/tutorials/zh_cn/beginner/mindspore_tensor.py)
# &emsp;[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/r2.9.0/resource/_static/logo_source.svg)](https://atomgit.com/mindspore/docs/blob/r2.9.0/tutorials/source_zh_cn/beginner/tensor.ipynb)
# 
# [基本介绍](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/introduction.html) || [快速入门](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/quick_start.html) || **张量 Tensor** || [数据加载与处理](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/dataset.html) || [网络构建](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/model.html) || [函数式自动微分](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/autograd.html) || [模型训练](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/train.html) || [保存与加载](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/save_load.html) || [Graph Mode加速](https://www.mindspore.cn/tutorials/zh-CN/r2.9.0/beginner/accelerate_with_static_graph.html) ||

# # 张量 Tensor
# 
# 张量（Tensor）是一个多线性函数，可用于表示矢量、标量和其他张量之间的线性关系。常见的线性关系包括内积、外积、线性映射以及笛卡儿积等。张量的坐标在 $n$ 维空间内，有  $n^{r}$ 个分量，每个分量都是坐标的函数。在坐标变换时，这些分量也依照某些规则作线性变换。$r$ 称为该张量的秩或阶（与矩阵的秩和阶无关）。
# 
# 张量是一种特殊的数据结构，与数组和矩阵非常相似。张量（[Tensor](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore/mindspore.Tensor.html)）是MindSpore网络运算中的基本数据结构，本教程主要介绍张量的属性及用法。

# In[1]:


import numpy as np
import mindspore
from mindspore import Tensor


# ## 创建张量
# 
# 张量的创建方式有多种，构造张量时，支持传入`Tensor`、`float`、`int`、`bool`、`tuple`、`list`和`numpy.ndarray`类型。
# 
# - **根据数据直接生成**
# 
#     可以根据数据创建张量。数据类型可以手动设置，也可以由框架自动推断。

# In[2]:


data = [1, 0, 1, 0]
x_data = mindspore.tensor(data)
print(x_data, x_data.shape, x_data.dtype)


# - **从NumPy数组生成**
# 
#     可以从NumPy数组创建张量。

# In[ ]:


np_array = np.array(data)
x_from_np = mindspore.tensor(np_array)
print(x_from_np, x_from_np.shape)


# - **使用init初始化器构造张量**
# 
#     当使用`init`初始化器对张量进行初始化时，支持传入的参数有`init`、`shape`、`dtype`。
# 
#     - `init`: 支持传入[initializer](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.common.initializer.html)的子类。如：下方示例中的 [One()](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.common.initializer.html#mindspore.common.initializer.One) 和 [Normal()](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore.common.initializer.html#mindspore.common.initializer.Normal)。
# 
#     - `shape`: 支持传入 `list`、`tuple`、 `int`。
# 
#     - `dtype`: 支持传入[mindspore.dtype](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore/mindspore.dtype.html#mindspore.dtype)。

# In[ ]:


from mindspore.common.initializer import One, Normal

# Initialize a tensor with ones
tensor1 = mindspore.tensor(shape=(2, 2), dtype=mindspore.float32, init=One()).init_data()
# Initialize a tensor from normal distribution
tensor2 = mindspore.tensor(shape=(2, 2), dtype=mindspore.float32, init=Normal()).init_data()

print("tensor1:\n", tensor1)
print("tensor2:\n", tensor2)


# `init`主要用于并行模式下的延后初始化。在正常情况下，不建议使用init对参数进行初始化。
# 
# - **继承另一个张量的属性，形成新的张量**

# In[5]:


from mindspore import ops

x_ones = ops.ones_like(x_data)
print(f"Ones Tensor: \n {x_ones} \n")

x_zeros = ops.zeros_like(x_data)
print(f"Zeros Tensor: \n {x_zeros} \n")


# ## 张量的属性
# 
# 张量的属性包括形状、数据类型、转置张量、单个元素大小、占用字节数量、维数、元素个数和每一维步长。
# 
# - 形状（shape）：`Tensor`的shape，为tuple类型。
# 
# - 数据类型（dtype）：`Tensor`的dtype，是MindSpore的一个数据类型。
# 
# - 单个元素大小（itemsize）： `Tensor`中每一个元素占用字节数，为整数类型。
# 
# - 占用字节数量（nbytes）： `Tensor`占用的总字节数，为整数类型。
# 
# - 维数（ndim）： `Tensor`的秩，也就是len(tensor.shape)，为整数类型。
# 
# - 元素个数（size）： `Tensor`中所有元素的个数，为整数类型。
# 
# - 每一维步长（strides）： `Tensor`每一维所需要的字节数，为tuple类型。

# In[6]:


x = mindspore.tensor(np.array([[1, 2], [3, 4]]), mindspore.int32)

print("x_shape:", x.shape)
print("x_dtype:", x.dtype)
print("x_itemsize:", x.itemsize)
print("x_nbytes:", x.nbytes)
print("x_ndim:", x.ndim)
print("x_size:", x.size)
print("x_strides:", x.strides)


# ## 张量索引
# 
# Tensor索引与Numpy索引类似。索引从0开始编制，负索引表示按倒序编制。冒号`:`和 `...`用于对数据进行切片。

# In[7]:


tensor = mindspore.tensor(np.array([[0, 1], [2, 3]]).astype(np.float32))

print("First row: {}".format(tensor[0]))
print("value of bottom right corner: {}".format(tensor[1, 1]))
print("Last column: {}".format(tensor[:, -1]))
print("First column: {}".format(tensor[..., 0]))


# ## 张量运算
# 
# 张量之间有很多运算，包括算术、线性代数、矩阵处理（转置、标引、切片）、采样等。张量运算的使用方式和NumPy类似，下面介绍其中几种操作。
# 
# > 普通算术运算包括：加（+）、减（-）、乘（\*）、除（/）、取模（%）、整除（//）。

# In[8]:


x = mindspore.tensor(np.array([1, 2, 3]), mindspore.float32)
y = mindspore.tensor(np.array([4, 5, 6]), mindspore.float32)

output_add = x + y
output_sub = x - y
output_mul = x * y
output_div = y / x
output_mod = y % x
output_floordiv = y // x

print("add:", output_add)
print("sub:", output_sub)
print("mul:", output_mul)
print("div:", output_div)
print("mod:", output_mod)
print("floordiv:", output_floordiv)


# [concat](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/ops/mindspore.ops.concat.html)将给定维度上的一系列张量连接起来。

# In[9]:


data1 = mindspore.tensor(np.array([[0, 1], [2, 3]]).astype(np.float32))
data2 = mindspore.tensor(np.array([[4, 5], [6, 7]]).astype(np.float32))
output = ops.concat((data1, data2), axis=0)

print(output)
print("shape:\n", output.shape)


# [stack](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/ops/mindspore.ops.stack.html) 则是从另一个维度上将两个张量合并起来。

# In[10]:


data1 = mindspore.tensor(np.array([[0, 1], [2, 3]]).astype(np.float32))
data2 = mindspore.tensor(np.array([[4, 5], [6, 7]]).astype(np.float32))
output = ops.stack([data1, data2])

print(output)
print("shape:\n", output.shape)


# ## Tensor与NumPy转换
# 
# Tensor可以和NumPy进行互相转换。
# 
# ### Tensor转换为NumPy
# 
# 可以使用 [Tensor.asnumpy()](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore/Tensor/mindspore.Tensor.asnumpy.html) 将MindSpore的Tensor转换为NumPy数据。

# In[11]:


t = mindspore.tensor([1., 1., 1., 1., 1.])
print(f"t: {t}", type(t))
n = t.asnumpy()
print(f"n: {n}", type(n))


# ### NumPy转换为Tensor
# 
# 使用 [Tensor.from_numpy()](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore/Tensor/mindspore.Tensor.asnumpy.html) 将NumPy数据转换为MindSpore的Tensor。此方法不拷贝数据，共用数据存储地址，速度较快，但NumPy数据需为连续（用numpy.iscontiguous()判断）。

# In[12]:


n = np.ones(5)
t = Tensor.from_numpy(n)


# In[13]:


np.add(n, 1, out=n)
print(f"n: {n}", type(n))
print(f"t: {t}", type(t))


# 使用 [mindspore.tensor](https://www.mindspore.cn/docs/zh-CN/r2.9.0/api_python/mindspore/mindspore.tensor.html) 直接创建，此方法会对数据进行拷贝。

# In[14]:


n = np.ones(5)
t = mindspore.tensor(n)


# In[15]:


np.add(n, 1, out=n)
print(f"n: {n}", type(n))
print(f"t: {t}", type(t))

