"""
演示
    张量的形状操作
涉及到的API:
    reshape()       不改变张量内容/张量的连续性的前提下，改变张量的形状，不改变元素的顺序，从左到右从上到小的顺序
    unsqueeze()     在指定的轴/维度上增加一个维度（长度1），升维
    squeeze()       删除所有长度为1的维度，降维
    transpose()     交换维度/轴，只能交换两个维度/轴
    permute()       交换维度/轴，可以交换多个维度/轴
    view()          改变形状，要求是连续张量，张量中元素的顺序没有改变，
                    没有经过transpose或permute等操作
    contiguous()    将非连续张量转换为连续张量
    is_contiguous() 判断张量是否是连续张量

需要掌握：
    reshape()   改变形状，不改变张量内容，元素个数守恒
    unsqueeze() 在指定的轴/维度上增加一个维度/轴
    permute()   交换多个维度/轴, 改变了张量中元素顺序
    view()  CV计算机视觉中用的较多,要求连续张量

"""

# 导包
import torch

# 1.定义函数，演示 张量的形状操作，改变形状
def demo01():
    # 0.设置随机种子
    torch.manual_seed(28)
    # 1.创建一个张量，(3,4)
    t1 = torch.randint(0,10,(3,4))
    print(f"t1:\n{t1}, shape: {t1.shape}")
    # 2.使用reshape()方法，改变张量的形状，(4,3)
    # t2 = t1.reshape(4,3)
    # t2 = t1.reshape(2,6)
    # t2 = t1.reshape(-1,3)  # -1表示自动计算该维度的大小，元素个数守恒
    # print(f"t2:\n{t2}, shape: {t2.shape}")
    # 3.使用unsqueeze()方法，升维，添加一个新的维度/轴
    # t2 = t1.unsqueeze(0)    # (1,3,4)
    t2 = t1.unsqueeze(1).unsqueeze(0)    # (1,3,1,4)
    print(f"t2:\n{t2}, shape: {t2.shape}")
    # 4.使用squeeze()方法，降维，删除所有长度为1的维度
    # t3 = t2.squeeze()   # (3,4)
    t3 = t2.squeeze(dim=1)
    print(f"t3:\n{t3}, shape: {t3.shape}")

# 2.定义函数，演示 交换维度,view
def demo02():
    # 0.设置随机种子
    torch.manual_seed(28)
    # 1.创建一个张量，(3,4,5)
    t1 = torch.randint(0,10,(3,4,5))    # HWC
    print(f"t1:\n{t1}, shape: {t1.shape}")  # (3,4,5)
    print(f"t1是否是连续张量：{t1.is_contiguous()}")
    # # 2.使用permute()方法，交换维度 HWC(0,1,2) -> CHW(2,0,1),改变了张量的连续性，也就是改变了张量的元素顺序
    t2 = t1.permute(2,0,1)  # (5,3,4)
    print(f"t2:\n{t2}, shape: {t2.shape}")
    # 2.1 使用is_contiguous()方法，判断张量是否是连续张量
    print(f"t2是否是连续张量：{t2.is_contiguous()}")

    # 3.使用transpose()方法，交换维度
    # (3,4,5) -> (5,4,3)
    # t3 = t1.transpose(2,0)  # (5,4,3)
    # print(f"t3:\n{t3}, shape: {t3.shape}")
    # 4.使用view()方法，改变张量的形状，不改变张量的连续性/元素顺序，要求是连续张量
    # t4 = t2.view(10,2,3)
    # # 4.1 使用contiguous()方法，将非连续张量转换为连续张量
    # t4 = t2.contiguous()
    t4 = t2.contiguous().view(10,2,3)
    print(f"t4是否是连续张量：{t4.is_contiguous()}")
    # # # t4 = t2.reshape(3,4,5)
    print(f"t4:\n{t4}, shape: {t4.shape}")

# 测试
if __name__ == '__main__':
    # demo01()
    demo02()