栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

(1)预备知识

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

(1)预备知识

目录

1.1 基础知识

1.1.1 入门 

 1.1.2 运算

 1.1.3 广播机制

1.1.4 索引和切片

1.1.5 转换为其他python对象

1.2 数据预处理

1.3 线性代数

1.4 微分

1.5 自动求导

1.6 概率


1.1.1 入门 
import torch 


# 使用arange创建一个行向量x
x = torch.arange(12)

# 访问张量的形状(沿每个轴的长度)
x.shape

# 张量中元素的总数number of element
x.numel()

# 想要改变张量的形状而不改变元素数量和元素值
# 其中,可以设置其中维度为-1,来自动推断维度
X = x.reshape(3,4)
X = x.reshape(-1,4)

# 使用全0数字初始化矩阵
torch.zeros((2,3,4))
# 使用全1数字初始化矩阵
torch.ones((2,3,4))

# 每个元素均值为0,标准差为1,形状(3,4)的张量
torch.randn(3,4)

# 通过列表初始化
torch.tensor([1,2,3,4])

 1.1.2 运算
#对于任意具有相同形状的张量,我们可以进行+-*/和**的元素基本运算
x + y
x - y
x * y
x / y
x ** y

# 按元素的求幂运算(e为底)(得到和x一样大小的e为底,x元素为指数的张量)
torch.exp(x)

# 多个张量的连结
X = torch.arange(12,dtype=torch.float32).reshape((3,4))
Y = torch.tensor([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
# 行连结
torch.cat((X,Y),dim=0)
# 列连结
torch.cat((X,Y),dim=1)

# 当进行逻辑运算时,得到的也是逻辑结果的张量
X == Y
X > 12

# 对张量的所有元素求和会得到只有一个元素的张量
X.sum()

 1.1.3 广播机制

在某些情况下,即使形状不同,我们可以调用广播机制执行元素操作。

首先,通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状。

其次,对生成的数组按元素操作。

可广播的张量需满足以下规则:

        1.每个张量至少一个维度

        2.从尾部开始,维度尺寸要么相等,要么其中一个张量维度尺寸为1,要么其中一个张量不存在这个维度

1.1.4 索引和切片
# X的最后一个元素
X[-1]

# 第二个和第三个元素
X[1:3]

# 通过索引将元素写入矩阵
X[1,2] = 9
X[0:2,:] = 12

1.1.5 转换为其他python对象
A = X.numpy()

B = torch.tensor(A)

# 要将大小为1的张量转换为python的标量,可以调用item函数或是python的内置函数
a = torch.tensor([5])

a.item()

float(a)

int(a)

1.2 数据预处理
# 操作系统接口模块
import os 
# os.path.join即简单的路径拼接
# exist_ok如果是False,那么如果目录已经存在则会Error
os.makedirs(os.path.join('..','data'),exist_ok=True)    #用于创建多层目录
data_file=os.path.join('..','data','house_tiny.csv')
with open(data_file,'w') as f:
    f.write('NumRooms,Alley,Pricen') # 列名
    f.write('NA,Pave,127500n') # 每行表示一个数据样本
    f.write('2,NA,106000n')
    f.write('4,NA,178100n')
    f.write('NA,NA,140000n')

# 导入pandas包调用read_csv函数,数据集四行三列,每行描述了房间数量(“NumRooms”)、巷子类型
# (“Alley”)和房屋价格(“Price”)。
import pandas as pd

data = pd.read_csv(data_file)
print(data)

# 处理缺失值
# loc和iloc都是对pandas Dataframe进行切片索引
# loc是通过字符型标签获得数据
# iloc和list一样通过索引获得数据
inputs,outputs = data.iloc[:,0:2],data.iloc[:,2]
inputs = inputs.fillna(inputs.mean())
print(inputs)

# 对于inputs中的类别值,pandas可以自动将此列转换为两列“Alley_Pave”和“Alley_nan”。巷子类型
# 为Pave会将“Alley_Pave”的值设为1,“Alley_nan”值设为0。get_dummies是将拥有不同值的变量转换
# 为0/1数值。
# 如果dummy_na = False表示忽略空缺值
inputs = pd.get_dummies(inputs, dummy_na=True)
print(inputs)

#转换为张量格式
import torch
X,y = torch.tensor(inputs.values),torch.tensor(outputs.values)

1.3 线性代数

标量:

import torch

x = torch.tensor([3.0])
y = torch.tensor([2.0])

x + y
x * y
x / y
x ** y

向量:

x = torch.arange(4) # tensor([0,1,2,3])
x[3]                # tensor(3)

# 长度,维度和形状
len(x)            # 4
x.shape             # torch.Size([4])

矩阵:

# 创建矩阵
A = torch.arange(20).reshape(5,4)

# 矩阵转置
A.T

张量:

# 创建张量
X = torch.arange(24).reshape(2,3,4)

A = torch.arange(20,dtype=torch.float32).reshape(5,4)
# 克隆张量A
B = A.clone()

# 元素按位运算
A * B
a = 2
a + X

# 降维
x = torch.arange(4,dtype=torch.float32)
x.sum()
# 默认情况下调用求和函数降低张量维度
# 可以指定某个轴的和
A_sum_axis0 = A.sum(axis=0)
A_sum_axis1 = A.sum(axis=1)
# 求平均值
A.mean()
A.sum()/A.numel()

# 非降维求和
sum_A = A.sum(axis=1,keepdims=True)
# 计算沿某一轴的累积总和
A.cumsum(axis=0) # 行

# 点积
y = torch.ones(4,dtype = torch.float32)
torch.dot(x,y)
# 其实就是按元素乘法进而求和来得到向量的卷积
torch.sum(x*y)

# 矩阵-向量积
# 代码中使用张量表示矩阵-向量积,我们使用与点积相同的dot函数,当我们为矩阵A和向量x调用
np.dot(A,x)时,即执行矩阵-向量积
torch.mv(A,x)

# 矩阵-矩阵积
torch.mm(A,B)

# 计算向量的范数
# 计算L2范数(根号下平方和)
u = torch.tensor([3.0,-4.0])
torch.norm(u)   # tensor(5)
# 计算L1范数(绝对值求和)
torch.abs(u).sum()

1.4 微分
# 使用svg格式在Jupyter中显示绘图
def use_svg_display(): 
    # 设置显示格式为svg
    display.set_matplotlib_formats('svg')

# 设置matplotlib图表大小
def set_figsize(figsize=(3.5,2.5)):
    use_svg_display()
    d2l.plt.rcParams['figure.figsize'] = figsize

# 设置由matplotlib生成图表的轴的属性
def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):
    axes.set_xlabel(xlabel)
    axes.set_ylabel(ylabel)
    axes.set_xscale(xscale)
    axes.set_yscale(yscale)
    axes.set_xlim(xlim)
    axes.set_ylim(ylim)
    if legend:
        axes.legend(legend)
    axes.grid()

# 绘制曲线
def plot(X, Y=None,xlabel=None,ylabel=None,legend=None,xlim=None,ylim=None,
xscale='linear',yscale='linear',
fmts=('-','m--','g-.','r:'),figsize=(3.5,2.5),axes=None):
    if legend is None:
        legend = []
    set_figsize(figsize)
    axes = axes if axes else d2l.plt.gca()
    #如何X有一个轴输出True
    def has_one_axis(X):
        return (hasattr(X,"ndim") and X.ndim == 1 or isinstance(X,list) and not 
hasattr(X[0],"__len__"))
    if has_one_axis(X):
        X = [X]
    if Y is None:
        X,Y = [[]]*len(X),X
    elif has_one_axis(Y):
        Y = [Y]
    if len(X) != len(Y):
        X = X * len(Y)
    axes.cla()
    for x,y,fmt in zip(X,Y,fmts):
        if len(x):
            axes.plot(x,y,fmt)
        else:
            axes.plot(y,fmt)
    set_axes(axes,xlabel,ylabel,xlim,ylim,xscale,yscale,legend)

绘制函数u = f(x)及其在x = 1处的切线y = 2x - 3

x = np.arange(0,3,0.1)
plot(x, [f(x), 2*x-3], 'x', 'f(x)', legend=['f(x)','Tangent line (x=1)'])

1.5 自动求导
# 对y=2xTx关于列向量x求导
import torch
x = torch.arange(4.0)
# 在计算y关于x的梯度之前,需要一个地方存储梯度,重要的是,我们不会每次对参数求导都分配新的
内存,因此会成千上万次更新相同的参数,每次分配新的内存会很快将内存耗尽
x.requires_grad_(True) #等价于 x = torch.arange(4.0,requires_grad=True)
x.grad # 默认值为None
# 计算y
y = 2 * torch.dot(x,x)
# 调用反向传播自动计算y关于x每个分量的梯度
y.backward()
# 打印梯度
x.grad

# 这时候如果计算x的另一个函数
# 默认情况下,pytorch会累积梯度,我们需要清楚之前的值
x.grad.zero_()
y = x.sum()
y.backward()
x.grad    # tensor([1,1,1,1])

如果y不是标量,那么向量y关于向量x的导数最自然解释是一个矩阵。而对于高阶和高维y和x,求导的结果可以是一个高阶张量。有待深入研究

# 对于非标量调用backward需要传入一个gradient参数,该参数指定微分函数关于self的梯度。在例子中
只是想求偏导数的和,所以传递1的梯度合适的
x.grad.zero_()
y = x * x
# 等价于y.backward(torch.ones(len(x)))
y.sum().backward()
x.grad

分离计算:想计算z关于x的梯度,希望视y为常数,并只考虑x在y被计算后的作用。

x.grad.zero_()
y = x * x
u = y.detach()
z = x * u
z.sum.backward()
x.grad == u        #[True,True,True,True]

x.grad.zero_()
y.sum().backward()
x.grad == 2 * x    #[True,True,True,True]

python控制流的梯度计算:

即使构建函数的计算图需要通过python控制流,我们仍然可以计算得到变量的梯度。

def f(a):
    b = a * 2
    while b.norm() < 1000:
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c
# 计算梯度
a = torch.randn(size=(),requires_grad=True)
d = f(a)
d.backward()

a.grad == d/a  # True

对于任何a,存在常量k使得f(a) = k*a,其中k的值取决于输入a,因此d/a可以验证梯度是否正确。

1.6 概率
%matplotlib inline
import torch
from torch.distributions import multinomial
from d2l import torch as d2l
# 为了抽取一个样本我们只需要传入一个概率向量
fair_probs = torch.ones([6])/6    # tensor([1,1,1,1,1,1])
# 1为取样次数,fair_probs为概率向量
multinomial.Multinomial(1,fair_probs).sample()

# 模拟1000次投掷
counts = multinomial.Multinomial(1000, fair_probs).sample()
counts/1000 # 相对频率作为估计值 

# 随着时间推移收敛到真实概率
counts = multinomial.Multinomial(10,fair_probs).sample((500,))
# 层层叠加
cum_count = count.cumsum(dim=0)
estimates = cum_counts / cum_counts.sum(dim=1,keepdims=True)

d2l.set_figsize((6,4.5))
for i in range(6):
    d2l.plt.plot(estimate[:,i].numpy(),
                label=("P(die=" + str(i+1) + ")"))
d2l.plt.axhline(y=0.167, color='black', linestyle='dashed')
d2l.plt.gca().set_xlabel('试验次数')
d2l.plt.gca().set_ylabel('估算概率')
d2l.plt.legend()

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/355146.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号