当前位置: 首页 > news >正文

pytorch-把线性回归实现一下。原理到实现,python到pytorch

  • 线性回归

    • 线性回归输出是一个连续值,因此适用于回归问题。回归问题在实际中很常见,如预测房屋价格、气温、销售额等连续值的问题。

    • 与回归问题不同,分类问题中模型的最终输出是一个离散值。所说的图像分类、垃圾邮件识别、疾病检测等输出为离散值的问题都属于分类问题的范畴。softmax回归则适用于分类问题。

  • 线性回归分析(Linear Regression Analysis)是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。本质上说,这种变量间依赖关系就是一种线性相关性,线性相关性是线性回归模型的理论基础,线性回归分析(Linear Regression Analysis)是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。本质上说,这种变量间依赖关系就是一种线性相关性,线性相关性是线性回归模型的理论基础。

  • 以一个简单的房屋价格预测作为例子来解释线性回归的基本要素。这个应用的目标是预测一栋房子的售出价格(元)。我们知道这个价格取决于很多因素,如房屋状况、地段、市场行情等。为了简单起见,这里我们假设价格只取决于房屋状况的两个因素,即面积(平方米)和房龄(年)。接下来我们希望探索价格与这两个因素的具体关系。

    • 模型定义

      • 设房屋的面积为 x1x_1x1,房龄为 x2x_2x2,售出价格为yyy。需要建立基于输入x1x_1x1x2x_2x2 来计算输出yyy 的表达式,也就是模型(model)。顾名思义,线性回归假设输出与各个输入之间是线性关系:y^=x1w1+x2w2+b\hat{y} = x_1 w_1 + x_2 w_2 + by^=x1w1+x2w2+b其中 w1w_1w1w2w_2w2 是权重(weight),bbb是偏差(bias),且均为标量。它们是线性回归模型的参数(parameter)。模型输出y^\hat{y}y^ 是线性回归对真实价格 yyy的预测或估计。通常允许它们之间有一定误差。
    • 模型训练

      • 训练数据

        • 通常收集一系列的真实数据,例如多栋房屋的真实售出价格和它们对应的面积和房龄。我们希望在这个数据上面寻找模型参数来使模型的预测价格与真实价格的误差最小。在机器学习术语里,该数据集被称为训练数据集(training data set)或训练集(training set),一栋房屋被称为一个样本(sample),其真实售出价格叫作标签(label),用来预测标签的两个因素叫作特征(feature)。特征用来表征样本的特点。
        • 假设我们采集的样本数为 n,索引为 i 的样本的特征为 x1(i)x_1^{(i)}x1(i)x2(i)x_2^{(i)}x2(i),标签为 y(i)y^{(i)}y(i)。对于索引为 i 的房屋,线性回归模型的房屋价格预测表达式为y^(i)=x1(i)w1+x2(i)w2+b\hat{y}^{(i)} = x_1^{(i)} w_1 + x_2^{(i)} w_2 + by^(i)=x1(i)w1+x2(i)w2+b
      • 损失函数

        • 在模型训练中,我们需要衡量价格预测值与真实值之间的误差。通常我们会选取一个非负数作为误差,且数值越小表示误差越小。一个常用的选择是平方函数。它在评估索引为 i 的样本误差的表达式为ℓ(i)(w1,w2,b)=12(y^(i)−y(i))2\ell^{(i)}(w_1, w_2, b) = \frac{1}{2} \left(\hat{y}^{(i)} - y^{(i)}\right)^2(i)(w1,w2,b)=21(y^(i)y(i))2其中常数 12\frac 1 221使对平方项求导后的常数系数为1,这样在形式上稍微简单一些。

        • 显然,误差越小表示预测价格与真实价格越相近,且当二者相等时误差为0。给定训练数据集,这个误差只与模型参数相关,因此我们将它记为以模型参数为参数的函数。在机器学习里,将衡量误差的函数称为损失函数(loss function)。这里使用的平方误差函数也称为平方损失(square loss)。

        • 通常,用训练数据集中所有样本误差的平均来衡量模型预测的质量,即

          • ℓ(w1,w2,b)=1n∑i=1nℓ(i)(w1,w2,b)=1n∑i=1n12(x1(i)w1+x2(i)w2+b−y(i))2\ell(w_1, w_2, b) =\frac{1}{n} \sum_{i=1}^n \ell^{(i)}(w_1, w_2, b) =\frac{1}{n} \sum_{i=1}^n \frac{1}{2}\left(x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}\right)^2 (w1,w2,b)=n1i=1n(i)(w1,w2,b)=n1i=1n21(x1(i)w1+x2(i)w2+by(i))2
        • 在模型训练中,我们希望找出一组模型参数,记为 w1∗w_1^*w1, w2∗w_2^*w2, b∗b^*b,来使训练样本平均损失最小:

          • w1∗,w2∗,b∗=arg⁡min⁡w1,w2,bℓ(w1,w2,b)w_1^*, w_2^*, b^* = \underset{w_1, w_2, b}{\arg\min} \ell(w_1, w_2, b) w1,w2,b=w1,w2,bargmin(w1,w2,b)
      • 优化算法

        • 当模型和损失函数形式较为简单时,上面的误差最小化问题的解可以直接用公式表达出来。这类解叫作解析解(analytical solution)。本节使用的线性回归和平方误差刚好属于这个范畴。然而,大多数深度学习模型并没有解析解,只能通过优化算法有限次迭代模型参数来尽可能降低损失函数的值。这类解叫作数值解(numerical solution)。
        • 在求数值解的优化算法中,小批量随机梯度下降(mini-batch stochastic gradient descent)在深度学习中被广泛使用。它的算法很简单:先选取一组模型参数的初始值,如随机选取;接下来对参数进行多次迭代,使每次迭代都可能降低损失函数的值。在每次迭代中,先随机均匀采样一个由固定数目训练数据样本所组成的小批量(mini-batch)B\mathcal{B}B,然后求小批量中数据样本的平均损失有关模型参数的导数(梯度),最后用此结果与预先设定的一个正数的乘积作为模型参数在本次迭代的减小量。
        • 在训练线性回归模型的过程中,模型的每个参数将作如下迭代:
          • w1←w1−η∣B∣∑i∈B∂ℓ(i)(w1,w2,b)∂w1=w1−η∣B∣∑i∈Bx1(i)(x1(i)w1+x2(i)w2+b−y(i)),w2←w2−η∣B∣∑i∈B∂ℓ(i)(w1,w2,b)∂w2=w2−η∣B∣∑i∈Bx2(i)(x1(i)w1+x2(i)w2+b−y(i)),b←b−η∣B∣∑i∈B∂ℓ(i)(w1,w2,b)∂b=b−η∣B∣∑i∈B(x1(i)w1+x2(i)w2+b−y(i)).\begin{aligned} w_1 &\leftarrow w_1 - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \frac{ \partial \ell^{(i)}(w_1, w_2, b) }{\partial w_1} = w_1 - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}}x_1^{(i)} \left(x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}\right),\\ w_2 &\leftarrow w_2 - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \frac{ \partial \ell^{(i)}(w_1, w_2, b) }{\partial w_2} = w_2 - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}}x_2^{(i)} \left(x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}\right),\\ b &\leftarrow b - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}} \frac{ \partial \ell^{(i)}(w_1, w_2, b) }{\partial b} = b - \frac{\eta}{|\mathcal{B}|} \sum_{i \in \mathcal{B}}\left(x_1^{(i)} w_1 + x_2^{(i)} w_2 + b - y^{(i)}\right). \end{aligned} w1w2bw1BηiBw1(i)(w1,w2,b)=w1BηiBx1(i)(x1(i)w1+x2(i)w2+by(i)),w2BηiBw2(i)(w1,w2,b)=w2BηiBx2(i)(x1(i)w1+x2(i)w2+by(i)),bBηiBb(i)(w1,w2,b)=bBηiB(x1(i)w1+x2(i)w2+by(i)).
        • 在上式中,∣B∣|\mathcal{B}|B代表每个小批量中的样本个数(批量大小,batch size),η\etaη称作学习率(learning rate)并取正数。需要强调的是,这里的批量大小和学习率的值是人为设定的,并不是通过模型训练学出的,因此叫作超参数(hyperparameter)。通常所说的“调参”指的正是调节超参数,例如通过反复试错来找到超参数合适的值。在少数情况下,超参数也可以通过模型训练学出。
    • 模型预测

      • 模型训练完成后,将模型参数 w1,w2,bw_1, w_2, bw1,w2,b在优化算法停止时的值分别记作 w^1,w^2,b^\hat{w}_1, \hat{w}_2, \hat{b}w^1,w^2,b^。注意,这里得到的并不一定是最小化损失函数的最优解 w1∗,w2∗,b∗w_1^*, w_2^*, b^*w1,w2,b,而是对最优解的一个近似。然后,就可以使用学出的线性回归模型 x1w^1+x2w^2+b^x_1 \hat{w}_1 + x_2 \hat{w}_2 + \hat{b}x1w^1+x2w^2+b^来估算训练数据集以外任意一栋面积(平方米)为x1x_1x1、房龄(年)为x2x_2x2的房屋的价格了。这里的估算也叫作模型预测、模型推断或模型测试。
  • 线性回归的从零开始实现

    • 首先,导入本节中实验所需的包或模块,其中的matplotlib包可用于作图,且设置成嵌入显示。

    • %matplotlib inlineag-1-1gqbc4tp7
      import torch
      from IPython import display
      from matplotlib import pyplot as plt
      import numpy as np
      import random
      
    • 生成数据集:构造一个简单的人工训练数据集,它可以使我们能够直观比较学到的参数和真实的模型参数的区别。设训练数据集样本数为1000,输入个数(特征数)为2。给定随机生成的批量样本特征X∈R1000×2\boldsymbol{X} \in \mathbb{R}^{1000 \times 2}XR1000×2,使用线性回归模型真实权重 w=[2,−3.4]⊤\boldsymbol{w} = [2, -3.4]^\topw=[2,3.4] 和偏差 b=4.2b = 4.2b=4.2,以及一个随机噪声项ϵ\epsilonϵ 来生成标签y=Xw+b+ϵ\boldsymbol{y} = \boldsymbol{X}\boldsymbol{w} + b + \epsilony=Xw+b+ϵ其中噪声项ϵ\epsilonϵ 服从均值为0、标准差为0.01的正态分布。噪声代表了数据集中无意义的干扰。

    • num_inputs = 2
      num_examples = 1000
      true_w = [2, -3.4]
      true_b = 4.2
      features = torch.randn(num_examples, num_inputs,dtype=torch.float32)
      labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
      labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()),dtype=torch.float32)   
      print(features, features.shape)
      print(labels, labels.shape)
      
    • tensor([[ 0.6216, -0.1328],[-0.5391,  0.0832],[ 1.2280,  0.8949],...,[ 0.4977,  0.0283],[-0.2189, -0.4873],[ 1.5165,  0.0500]]) torch.Size([1000, 2])
      tensor([  5.8867,   2.8264,   3.6247,   8.8301,   6.4663,  -2.2984,   0.0459,...]) torch.Size([1000])
      
    • 通过生成第二个特征features[:, 1]和标签 labels 的散点图,可以更直观地观察两者间的线性关系。

    • def use_svg_display():# 用矢量图显示display.display_svg()
      def set_figsize(figsize=(3.5, 2.5)):use_svg_display()# 设置图的尺寸plt.rcParams['figure.figsize'] = figsize
      set_figsize()
      plt.scatter(features[:, 1].numpy(), labels.numpy(), 1);
      
    • 在这里插入图片描述

    • 读取数据:在训练模型的时候,我们需要遍历数据集并不断读取小批量数据样本。这里我们定义一个函数:它每次返回batch_size(批量大小)个随机样本的特征和标签。读取第一个小批量数据样本并打印。每个批量的特征形状为(10, 2),分别对应批量大小和输入个数;标签形状为批量大小。

      • def data_iter(batch_size, features, labels):num_examples = len(features)indices = list(range(num_examples))   # 生成下标列表random.shuffle(indices)  # 打乱下标列表,样本的读取顺序是随机的for i in range(0, num_examples, batch_size):j = torch.LongTensor(indices[i: min(i + batch_size, num_examples)]) # 最后一次可能不足一个batchyield  features.index_select(0, j), labels.index_select(0, j)
        batch_size = 10
        index = 0
        for X, y in data_iter(batch_size, features, labels):print(X, y)index += 1if index >2:break
        
      • tensor([[ 1.2572, -0.0569],[-1.0629,  0.5675],[ 0.2812,  1.1647],[ 1.3334, -0.3296],[ 0.6850, -1.2253],[ 0.6851,  0.4158],[ 0.0727,  0.9224],[-0.7991, -0.1419],[ 0.7741,  1.6103],[-0.2893, -0.7415]]) tensor([6.9151, 0.1457, 0.8034, 8.0023, 9.7363, 4.1549, 1.2025, 3.0689, 0.2749,6.1371])
        tensor([[ 1.4936,  1.5380],[ 0.0410,  0.4386],[ 0.4641, -0.3789],[-0.5353,  0.5551],[-1.2910, -0.8273],[ 0.4035, -0.5826],[-0.8060, -0.5223],[ 0.9478,  0.6716],[-1.7344,  0.2920],[-0.5045,  1.3026]]) tensor([ 1.9619,  2.7909,  6.4143,  1.2321,  4.4248,  6.9789,  4.3647,  3.8035,-0.2623, -1.2338])
        tensor([[-0.4643,  1.2070],[ 1.2244,  1.0575],[-0.5904, -0.8998],[ 0.3056, -0.4934],[ 0.1183,  0.1850],[-0.1599,  0.3071],[ 0.8133,  0.1455],[-0.8600, -0.5746],[ 0.9954,  1.7316],[-0.1285,  0.9870]]) tensor([-0.8267,  3.0593,  6.0694,  6.4741,  3.8124,  2.8426,  5.3399,  4.4488,0.2982,  0.5795])
        
    • 初始化模型参数:将权重初始化成均值为0、标准差为0.01的正态随机数,偏差则初始化成0。之后的模型训练中,需要对这些参数求梯度来迭代参数的值,因此我们要让它们的requires_grad=True

      • w = torch.tensor(np.random.normal(0, 0.01, (num_inputs, 1)), dtype=torch.float32)
        b = torch.zeros(1, dtype=torch.float32)
        w.requires_grad_(requires_grad=True)
        b.requires_grad_(requires_grad=True) 
        print(w,b)
        
      • tensor([[-0.0267],[ 0.0070]], requires_grad=True) tensor([0.], requires_grad=True)
        
    • 定义模型

      • 线性回归的矢量计算表达式的实现。使用mm函数做矩阵乘法。

        • torch.mul(a, b) 是矩阵a和b对应位相乘,a和b的维度必须相等,比如a的维度是(1, 2),b的维度是(1, 2),返回的仍是(1, 2)的矩阵;

        • torch.mm(a, b) 是矩阵a和b矩阵相乘,比如a的维度是(1, 2),b的维度是(2, 3),返回的就是(1, 3)的矩阵;

        • torch.bmm() 强制规定维度和大小相同;

        • torch.matmul() 没有强制规定维度和大小,可以用利用广播机制进行不同维度的相乘操作

      • def linreg(X, w, b): return torch.mm(X, w) + b
        
    • 定义损失函数

      • 评价指标是针对将相同的数据,输入不同的算法模型,或者输入不同参数的同一种算法模型,而给出这个算法或者参数好坏的定量指标

        • 均方误差(SSE):真实值-预测值 然后平方之后求和平均

          • 同样的数据集的情况下,SSE越小,误差越小,模型效果越好。

          • 缺点:SSE数值大小本身没有意义,随着样本增加,SSE必然增加,也就是说,不同的数据集的情况下,SSE比较没有意义。

          • SSE=∑(y^−y)2SSE=\sum(\hat{y}-y)^2 SSE=(y^y)2

          • 对SSE改进,MSE:对SSE求平均。是线性回归中最常用的损失函数,线性回归过程中尽量让该损失函数最小。那么模型之间的对比也可以用它来比较

          • MSE=1m∑(y^−y)2MSE=\frac{1}{m}\sum(\hat{y}-y)^2 MSE=m1(y^y)2

        • 均方根误差(标准误差 RMSE)

          • MSE是用来衡量一组数自身的离散程度,而RMSE是用来衡量观测值同真值之间的偏差,它们的研究对象和研究目的不同。它的意义在于开个根号后,误差的结果就与数据是一个级别的,可以更好地来描述数据。标准误差对一组测量中的特大或特小误差反映非常敏感,所以,标准误差能够很好地反映出测量的精密度。这正是标准误差在工程测量中广泛被采用的原因。

          • 当数据集中有一个特别大的异常值,这种情况下,### 数据倾斜,RMSE会被明显拉大。所以对RMSE低估值(under-predicted)的判罚明显小于估值过高(over-predicted)的情况。

          • RMSE=1m∑(y^−y)2RMSE=\sqrt{\frac{1}{m}\sum({\hat{y}-y})^2} RMSE=m1(y^y)2

        • 平均绝对误差(MAE)

          • 平均绝对误差是绝对误差的平均值,平均绝对误差能更好地反映预测值误差的实际情况.

          • MAE是一个线性的指标,所有个体差异在平均值上均等加权,所以它更加凸显出异常值。MSE和MAE适用于误差相对明显的时候,此时大的误差也有比较高的权重

          • MAE=1m∑∣y^−y∣MAE=\frac{1}{m}\sum|\hat{y}-y| MAE=m1y^y

        • R-square(决定系数)

          • 对于回归类算法而言,只探索数据预测是否准确是不足够的。除了数据本身的数值大小之外,还希望模型能够捕捉到数据的”规律“,比如数据的分布规律,单调性等等,而是否捕获了这些信息并无法使用MSE或者MAE来衡量.

          • R2=1−∑(y^i−yi)2∑(yˉ−yi)2R^2=1-\frac{\sum(\hat{y}^i-y^i)^2}{\sum(\bar{y}-y^i)^2} R2=1(yˉyi)2(y^iyi)2

            • 上面分子就是我们训练出的模型预测的误差和
            • 下面分母就是瞎猜的误差和。(通常取观测值的平均值)
            • 如果结果是0,就说明我们的模型跟瞎猜差不多
            • 如果结果是1。就说明我们模型无错误
            • 介于0~1之间,越接近1,回归拟合效果越好,一般认为超过0.8的模型拟合优度比较高
          • 数学理解:分母理解为原始数据的离散程度,分子为预测数据和原始数据的误差,二者相除可以消除原始数据离散程度的影响。

          • 分子分母同时除以m,那么分子就变成了我们的均方误差MSE,下面分母就变成了方差

          • R2=1−MSE(y^i,y)Var(y)R^2=1-\frac{MSE(\hat{y}^i,y)}{Var(y)} R2=1Var(y)MSE(y^i,y)

          • 方差的本质是任意一个值和样本均值的差异,差异越大,这些值所带的信息越多.在R2中,分子是真实值和预测值之差的差值,也就是我们的模型没有捕获到的信息总量,分母是真实标签所带的信息量,所以两者都衡量1 - 我们的模型没有捕获到的信息量占真实标签中所带的信息量的比例,所以,两者都是越接近1越好。数据集的样本越大,R²越大,因此,不同数据集的模型结果比较会有一定的误差。

        • Adjusted R-Square (校正决定系数)

          • Ra2=1−(1−R2)(n−1)n−p−1R_a^2=1-\frac{(1-R^2)(n-1)}{n-p-1} Ra2=1np1(1R2)(n1)

          • n为样本数量,p为特征数量。同时消除了样本数量和特征数量的影响

      • 这里使用上文描述的平方损失来定义线性回归的损失函数。在实现中,我们需要把真实值y变形成预测值y_hat的形状。以下函数返回的结果也将和y_hat的形状相同。

      • def squared_loss(y_hat, y):  # 注意这里返回的是向量, 另外, pytorch里的MSELoss并没有除以 2return (y_hat - y.view(y_hat.size())) ** 2 / 2
        
    • 定义优化算法

      • 以下的sgd函数实现了上文中介绍的小批量随机梯度下降算法。它通过不断迭代模型参数来优化损失函数。这里自动求梯度模块计算得来的梯度是一个批量样本的梯度和。将它除以批量大小来得到平均值。

      • def sgd(params, lr, batch_size): for param in params:param.data -= lr * param.grad / batch_size # 注意这里更改param时用的param.data
        
    • 训练模型

      • 在训练中,将多次迭代模型参数。在每次迭代中,根据当前读取的小批量数据样本(特征X和标签y),通过调用反向函数backward计算小批量随机梯度,并调用优化算法sgd迭代模型参数。由于我们之前设批量大小batch_size为10,每个小批量的损失l的形状为(10, 1)。由于变量l并不是一个标量,所以可以调用.sum()将其求和得到一个标量,再运行l.backward()得到该变量有关模型参数的梯度。注意在每次更新完参数后不要忘了将参数的梯度清零

      • 在一个迭代周期(epoch)中,将完整遍历一遍data_iter函数,并对训练数据集中所有样本都使用一次(假设样本数能够被批量大小整除)。这里的迭代周期个数num_epochs和学习率lr都是超参数,分别设10和0.03。在实践中,大多超参数都需要通过反复试错来不断调节。虽然迭代周期数设得越大模型可能越有效,但是训练时间可能过长。

      • lr = 0.03
        num_epochs = 10
        net = linreg
        loss = squared_loss
        for epoch in range(num_epochs):  # 训练模型一共需要num_epochs个迭代周期# 在每一个迭代周期中,会使用训练数据集中所有样本一次(假设样本数能够被批量大小整除)。X# 和y分别是小批量样本的特征和标签for X, y in data_iter(batch_size, features, labels):l = loss(net(X, w, b), y).sum()  # l是有关小批量X和y的损失l.backward()  # 小批量的损失对模型参数求梯度sgd([w, b], lr, batch_size)  # 使用小批量随机梯度下降迭代模型参数# 不要忘了梯度清零w.grad.data.zero_()b.grad.data.zero_()train_l = loss(net(features, w, b), labels)print('epoch %d, loss %f' % (epoch + 1, train_l.mean().item())) 
        
      • epoch 1, loss 0.032868
        epoch 2, loss 0.000126
        epoch 3, loss 0.000046
        epoch 4, loss 0.000046
        epoch 5, loss 0.000046
        epoch 6, loss 0.000046
        epoch 7, loss 0.000046
        epoch 8, loss 0.000046
        epoch 9, loss 0.000046
        epoch 10, loss 0.000046
        
    • 训练完成后,可以比较学到的参数和用来生成训练集的真实参数。仅使用Tensorautograd模块就可以很容易地实现一个模型。

      • print(true_w, '\n', w)
        print(true_b, '\n', b)
        
      • [2, -3.4] tensor([[ 2.0002],[-3.3997]], requires_grad=True)
        4.2 tensor([4.1999], requires_grad=True)
        
  • 上文从python的角度梳理了流程实现了回归任务,现在用pytorch重新做一遍。

    • 生成数据集:生成与上一节中相同分布的数据集。其中features是训练数据特征,labels是标签。

      • num_inputs = 2
        num_examples = 1000
        true_w = [2, -3.4]
        true_b = 4.2
        features = torch.tensor(np.random.normal(0, 1, (num_examples, num_inputs)), dtype=torch.float)
        labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
        labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()), dtype=torch.float) # 添加扰动噪声
        print(features[:3], features.shape)
        print(labels[:3], labels.shape)
        
      • tensor([[ 0.0060, -0.5646],[ 2.6077, -0.2698],[-1.2894, -1.1564]]) torch.Size([1000, 2])
        tensor([ 6.1333, 10.3299,  5.5643]) torch.Size([1000])
        
    • 读取数据

      • PyTorch提供了data包来读取数据。由于data常用作变量名,导入的data模块用Data代替。在每一次迭代中,将随机读取包含10个数据样本的小批量。
      • import torch.utils.data as Data
        batch_size = 10
        # 将训练数据的特征和标签组合
        dataset = Data.TensorDataset(features, labels)
        # 随机读取小批量
        data_iter = Data.DataLoader(dataset, batch_size, shuffle=True)
        iter_num = 0
        for X, y in data_iter:print(X, y)iter_num += 1if iter_num > 2:break
        
      • tensor([[ 0.0067,  0.1401],[-1.1505,  0.1468],[ 1.5391,  1.0936],[ 0.4877, -1.5252],[ 0.7110, -0.7665],[-0.3763,  1.2381],[ 1.0921, -1.0217],[-0.6782, -0.0704],[ 0.7332, -0.4158],[ 0.7919, -0.4500]]) tensor([ 3.7506,  1.3989,  3.5617, 10.3682,  8.2230, -0.7610,  9.8584,  3.0777,7.0842,  7.3240])
        tensor([[ 0.6080, -0.2581],[ 0.5077,  1.8393],[ 0.6369,  2.1997],[-0.6904, -1.0292],[-1.1829, -1.8127],[ 2.2175,  1.7429],[-0.7929, -0.8644],[-0.3622, -1.4727],[-2.0080,  1.4671],[ 0.1746,  0.5394]]) tensor([ 6.2746, -1.0449, -2.0096,  6.3014,  7.9963,  2.7291,  5.5671,  8.4808,-4.7977,  2.7139])
        tensor([[ 0.8790, -1.4681],[-0.8629, -0.3203],[-0.3763,  0.0022],[-0.8903, -0.6009],[ 0.4797, -0.6693],[ 0.5890, -0.5540],[-0.1996,  0.9864],[-0.9645,  1.6157],[ 1.0762, -0.0679],[-0.4368, -0.8553]]) tensor([10.9561,  3.5650,  3.4371,  4.4402,  7.4297,  7.2489,  0.4353, -3.2319,6.5702,  6.2362])
        
    • 定义模型

      • PyTorch提供了大量预定义的层,这使我们只需关注使用哪些层来构造模型。下面将介绍如何使用PyTorch更简洁地定义线性回归。
      • 首先,导入torch.nn模块。实际上,“nn”是neural networks(神经网络)的缩写。顾名思义,该模块定义了大量神经网络的层。之前我们已经用过了autograd,而nn就是利用autograd来定义模型。nn的核心数据结构是Module,它是一个抽象概念,既可以表示神经网络中的某个层(layer),也可以表示一个包含很多层的神经网络。在实际使用中,最常见的做法是继承nn.Module,撰写自己的网络/层。一个nn.Module实例应该包含一些层以及返回输出的前向传播(forward)方法。
      • import torch.nn as nn
        class LinearNet(nn.Module):def __init__(self, n_feature):super(LinearNet, self).__init__()self.linear = nn.Linear(n_feature, 1)# forward 定义前向传播def forward(self, x):y = self.linear(x)return y
        net = LinearNet(num_inputs)
        print(net) # 使用print可以打印出网络的结构
        
      • LinearNet((linear): Linear(in_features=2, out_features=1, bias=True)
        )
        
      • 事实上还可以用nn.Sequential来更加方便地搭建网络,Sequential是一个有序的容器,网络层将按照在传入Sequential的顺序依次被添加到计算图中。
      • # 写法一
        net = nn.Sequential(nn.Linear(num_inputs, 1)# 此处还可以传入其他层)
        print(net)
        print(net[0])
        # 写法二
        net = nn.Sequential()
        net.add_module('linear', nn.Linear(num_inputs, 1))
        # net.add_module ......
        print(net)
        print(net[0])
        # 写法三
        from collections import OrderedDict
        net = nn.Sequential(OrderedDict([('linear', nn.Linear(num_inputs, 1))# ......]))
        print(net)
        print(net[0])
        
      • Sequential((0): Linear(in_features=2, out_features=1, bias=True)
        )
        Linear(in_features=2, out_features=1, bias=True)
        Sequential((linear): Linear(in_features=2, out_features=1, bias=True)
        )
        Linear(in_features=2, out_features=1, bias=True)
        Sequential((linear): Linear(in_features=2, out_features=1, bias=True)
        )
        Linear(in_features=2, out_features=1, bias=True)
        
      • 可以通过net.parameters()来查看模型所有的可学习参数,此函数将返回一个生成器。
      • for param in net.parameters():print(param)
        
      • Parameter containing:
        tensor([[-0.4808, -0.0012]], requires_grad=True)
        Parameter containing:
        tensor([-0.4288], requires_grad=True)
        
      • 注意:torch.nn仅支持输入一个batch的样本不支持单个样本输入,如果只有单个样本,可使用input.unsqueeze(0)来添加一维。
    • 初始化模型参数

      • 在使用net前,需要初始化模型参数,如线性回归模型中的权重和偏差。PyTorch在init模块中提供了多种参数初始化方法。这里的initinitializer的缩写形式。通过init.normal_将权重参数每个元素初始化为随机采样于均值为0、标准差为0.01的正态分布。偏差会初始化为零。
      • from torch.nn import init
        init.normal_(net[0].weight, mean=0, std=0.01)
        init.constant_(net[0].bias, val=0)  # 也可以直接修改bias的data: net[0].bias.data.fill_(0)
        
      • Parameter containing:
        tensor([[-0.0059,  0.0122]], requires_grad=True)
        
      • 在实践中,权重是否合理的进行了初始化,决定着模型的很多走向,比如模型算法离最优解的距离远近或方向是否准确、是否会出现梯度爆炸或梯度消失从而导致训练无法收敛、同等效果下需要花多长时间来训练等。合理的权重初始化会让模型算法梯度更加正常且更加容易到达全局最优解。同样反过来,不合理权重初始化很容易让模型算法出现梯度问题,让模型算法陷入局部最优解导致训练失败等。
    • 定义损失函数

      • PyTorch在nn模块中提供了各种损失函数,这些损失函数可看作是一种特殊的层,PyTorch也将这些损失函数实现为nn.Module的子类。我们现在使用它提供的均方误差损失作为模型的损失函数。
      • loss = nn.MSELoss()
        
    • 定义优化算法

      • 同样,我们也无须自己实现小批量随机梯度下降算法。torch.optim模块提供了很多常用的优化算法比如SGD、Adam和RMSProp等。下面我们创建一个用于优化net所有参数的优化器实例,并指定学习率为0.03的小批量随机梯度下降(SGD)为优化算法。
      • import torch.optim as optim
        optimizer = optim.SGD(net.parameters(), lr=0.03)
        print(optimizer)
        
      • SGD (
        Parameter Group 0dampening: 0differentiable: Falseforeach: Nonelr: 0.03maximize: Falsemomentum: 0nesterov: Falseweight_decay: 0
        )
        
      • 还可以为不同子网络设置不同的学习率,这在finetune时经常用到。例:
      • optimizer =optim.SGD([# 如果对某个参数不指定学习率,就使用最外层的默认学习率{'params': net.subnet1.parameters()}, # lr=0.03{'params': net.subnet2.parameters(), 'lr': 0.01}], lr=0.03)
        
      • 有时候不想让学习率固定成一个常数,那如何调整学习率呢?主要有两种做法。一种是修改optimizer.param_groups中对应的学习率,另一种是更简单也是较为推荐的做法——新建优化器,由于optimizer十分轻量级,构建开销很小,故而可以构建新的optimizer。但是后者对于使用动量的优化器(如Adam),会丢失动量等状态信息,可能会造成损失函数的收敛出现震荡等情况。
      • # 调整学习率
        for param_group in optimizer.param_groups:param_group['lr'] *= 0.1 # 学习率为之前的0.1倍
        
    • 训练模型

      • 训练模型时,我们通过调用optim实例的step函数来迭代模型参数。按照小批量随机梯度下降的定义,我们在step函数中指明批量大小,从而对批量中样本梯度求平均。

      • num_epochs = 10
        for epoch in range(1, num_epochs + 1):for X, y in data_iter:output = net(X)l = loss(output, y.view(-1, 1))optimizer.zero_grad() # 梯度清零,等价于net.zero_grad()l.backward()optimizer.step()print('epoch %d, loss: %f' % (epoch, l.item()))
        
      • epoch 1, loss: 0.000135
        epoch 2, loss: 0.000071
        epoch 3, loss: 0.000055
        epoch 4, loss: 0.000074
        epoch 5, loss: 0.000086
        epoch 6, loss: 0.000182
        epoch 7, loss: 0.000060
        epoch 8, loss: 0.000148
        epoch 9, loss: 0.000115
        epoch 10, loss: 0.000139
        
      • 下面分别比较学到的模型参数和真实的模型参数。从net获得需要的层,并访问其权重(weight)和偏差(bias)。

      • dense = net[0]
        print(true_w, dense.weight)
        print(true_b, dense.bias)
        
      • [2, -3.4] Parameter containing:
        tensor([[ 1.9990, -3.3997]], requires_grad=True)
        4.2 Parameter containing:
        tensor([4.2000], requires_grad=True))
        
  • 使用PyTorch可以更简洁地实现模型。torch.utils.data模块提供了有关数据处理的工具,torch.nn模块定义了大量神经网络的层,torch.nn.init模块定义了各种初始化方法,torch.optim模块提供了很多常用的优化算法。
    epoch 10, loss: 0.000139
    ```

    • 下面分别比较学到的模型参数和真实的模型参数。从net获得需要的层,并访问其权重(weight)和偏差(bias)。

    • dense = net[0]
      print(true_w, dense.weight)
      print(true_b, dense.bias)
      
    • [2, -3.4] Parameter containing:
      tensor([[ 1.9990, -3.3997]], requires_grad=True)
      4.2 Parameter containing:
      tensor([4.2000], requires_grad=True))
      
  • 使用PyTorch可以更简洁地实现模型。torch.utils.data模块提供了有关数据处理的工具,torch.nn模块定义了大量神经网络的层,torch.nn.init模块定义了各种初始化方法,torch.optim模块提供了很多常用的优化算法。

相关文章:

pytorch-把线性回归实现一下。原理到实现,python到pytorch

线性回归 线性回归输出是一个连续值,因此适用于回归问题。回归问题在实际中很常见,如预测房屋价格、气温、销售额等连续值的问题。 与回归问题不同,分类问题中模型的最终输出是一个离散值。所说的图像分类、垃圾邮件识别、疾病检测等输出为离…...

js中判断数组的方式有哪些?

js中判断数组的方式有哪些?1.通过Object.prototype.toString.call来判断2.通过instanceof来判断3.通过constructor来判断4.通过原型链来判断5.通过ES6.Array.isAaary()来判断6.通过Array.prototype.isPrototypeOf来判断1.通过Object.prototype.toString.call来判断 …...

【2023unity游戏制作-mango的冒险】-5.攻击系统的简单实现

👨‍💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 收录于专栏:unity游戏制作 ⭐攻击系统的简单实现⭐ 文章目录⭐攻击系统的简单实现⭐👨‍&#x1…...

SpringMVC 面试题

1、什么是SpringMVC? SpringMVC是一个基于Java的实现了MVC设计模式的“请求驱动型”的轻量级WEB框架,通过把model,view,controller 分离,将web层进行职责的解耦,把复杂的web应用分成逻辑清晰的几个部分&am…...

布局三八女王节,巧借小红书数据分析工具成功引爆618

对于小红书“她”经济来说,没有比三八节更好的阵地了。伴随三八女王节逐渐临近,各大品牌蓄势待发,这场开春后第一个S级大促活动,看看品牌方们可以做什么? 洞察流量,把握节点营销时机 搜索小红书2023年的三…...

RISCV学习(1)基本模型认识

笔者来聊聊ARM的函数的调用规则 1、ARM函数调用规则介绍 首先介绍几个术语, AAPCS:Procedure Call Standard for the ARM ArchitectureAPCS:ARM Procedure Call StandardTPCS:Thumb Procedure Call StandardATPCS:AR…...

【java代码审计】命令注入

1 成因 开发者在某种开发需求时,需要引入对系统本地命令的支持来完成某些特定的功能,此时若未对用户的输入做严格的过滤,就可能发生命令注入。 2 造成命令注入的类或方法 Runtime类:提供调用系统命令的功能 ①Runtime.getRuntim…...

速锐得适配北汽EX系列电动汽车CAN总线应用于公务分时租赁

过去的几年,我们看到整个分时租赁业务出现断崖式下跌,这是我们看到这种市场情况,是必然,也是出乎意料。原本很多融资后的出行公司、大牌的出行服务商的分时租赁业务,受各种影响不得不转型成其他出行服务。例如&#xf…...

已解决ERROR: Failed building wheel for opencv-python-headless

已解决ERROR: Failed building wheel for opencv-python-headless Failed to build opencv-python-headless ERROR: Could not build wheels for opencv-python-headless, which is required to install pyproject.toml-based projects报错信息亲测有效 文章目录报错问题报错翻…...

每日获取安全资讯的网站,国内外共120个

国内 FreeBuf(https://www.freebuf.com/) 安全客(https://www.anquanke.com/) 雷锋网安全(https://www.leiphone.com/category/security) 先知社区(https://xz.aliyun.com/) CSDN安全…...

HUN工训中心:开关电路和按键信号抖动

工训中心的牛马实验 1.实验目的: 1) 认识开关电路,掌握按键状态判别、开关电路中逻辑电平测量、逻辑值和逻辑函数电路。 2) 掌握按键信号抖动简单处理方法。 3) 实现按键计数电路。 2.实验资源: HBE硬件基础电路实验箱、示波器、万用表…...

WordPress 主题 SEO 标题相关函数和过滤器教程wp_get_document_title()

WordPress 4.4.0 版本开始,加入了 wp_get_document_title(); 这个函数,而 wp_title(); 已经 deprecated 不推荐使用。因此,如果想要启用 WordPress 主题标题功能,在不安装 WordPress SEO 插件的情况下,可以使用以下代码…...

Qt 事件机制

【1】事件 事件是可以被控件识别的操作。如按下确定按钮、选择某个单选按钮或复选框。 每种控件有自己可识别的事件,如窗体的加载、单击、双击等事件,编辑框(文本框)的文本改变事件等等。 事件就是用户对窗口上各种组件的操作。…...

【Python】Numpy--np.linalg.eig()求对称矩阵的特征值和特征向量

【Python】Numpy–np.linalg.eig()求对称矩阵的特征值和特征向量 文章目录【Python】Numpy--np.linalg.eig()求对称矩阵的特征值和特征向量1. 介绍2. API3. 代码示例1. 介绍 特征分解(Eigendecomposition),又称谱分解(Spectral d…...

医疗床头卡(WIFI方案)

一、产品特性 7.5寸墨水屏显示WIFI无线通信,极简部署,远程控制按键及高亮LED指示灯指示800*480点阵屏幕锂电池供电,支持USB充电DIY界面支持文本/条码/二维码/图片超低功耗/超长寿命,一次充电可用一年基于现有Wifi环境&#xff0c…...

[YOLO] yolo博客笔记汇总(自用

pip下载速度太慢,国内镜像: 国内镜像解决pip下载太慢https://blog.csdn.net/weixin_51995286/article/details/113972534​​​​​​​ YOLO v2和V3 关于设置生成anchorbox,Boundingbox边框回归的过程详细解读 YOLO v2和V3 关于设置生成an…...

Linux 常用 API 函数

文章目录1. 系统调用与库函数1.1 什么是系统调用1.2 系统调用的实现1.3 系统调用和库函数的区别2. 虚拟内存空间3. 错误处理函数4. C 库中 IO 函数工作流程5. 文件描述符6. 常用文件 IO 函数6.1 open 函数6.2 close 函数6.3 write 函数6.4 read 函数6.5 lseek 函数7. 文件操作相…...

【转载】bootstrap自定义样式-bootstrap侧边导航栏的实现

bootstrap自带的响应式导航栏是向下滑动的,但是有时满足不了个性化的需求: 侧滑栏使用定位fixed 使用bootstrap响应式使用工具类 visible-sm visible-xs hidden-xs hidden-sm等对不同屏幕适配 侧滑栏的侧滑效果不使用jquery方法来实现,使用的是css3 tr…...

奇瑞x华为纯电智选车来了,新版ADS成本将大幅下降

作者 | 德新 编辑 | 于婷HiEV获悉,问界M5将在4月迎来搭载高阶辅助驾驶的新款,而M9将在今年秋天发布。 奇瑞一侧,华为将与奇瑞首先推出纯电轿车,代号EH3。新车将在奇瑞位于芜湖江北新区的智能网联超级二工厂组装下线。目前超级二工…...

机器学习的特征归一化Normalization

为什么需要做归一化? 为了消除数据特征之间的量纲影响,就需要对特征进行归一化处理,使得不同指标之间具有可比性。对特征归一化可以将所有特征都统一到一个大致相同的数值区间内。 为了后⾯数据处理的⽅便,归⼀化可以避免⼀些不…...

程序员看过都说好的资源网站,看看你都用过哪些?

程序员必备的相关资源网站一.图片专区1.表情包(1)发表情(2)逗比拯救世界(3)搞怪图片生成(4)哇咔工具2.图标库(1)Font Awesome(2)iconf…...

Win11的两个实用技巧系列之设置系统还原点的方法、安全启动状态开启方法

Win11如何设置系统还原点?Win11设置系统还原点的方法很多用户下载安装win11后应该如何创建还原点呢?现在我通过这篇文章给大家介绍一下Win11如何设置系统还原点?在Windows系统中有一个系统还原功能可以帮助我们在电脑出现问题的时候还原到设置的时间上&…...

【Linux】项目的自动化构建-make/makefile

💣1.背景会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的 规则来指定,哪些文件需要先编译&#xff…...

【Redis学习2】Redis常用数据结构与应用场景

Redis常用数据结构与应用场景 redis中存储数据是以key-value键值对的方式去存储的,其中key为string字符类型,value的数据类型可以是string(字符串)、list(列表)、hash(字典)、set(集合) 、 zset(有序集合)。 这5种数据类型在开发中可以应对大部分场景的…...

踩了大坑:https 证书访问错乱

文章目录一、问题排查及解决问题一:证书加载错乱问题二:DNS 解析污染问题问题三:浏览器校验问题二、终极解决方法2.1 可外网访问域名2.2 只能内网访问域名2.3 内网自动化配置2.4 错误解决一、问题排查及解决 今天遇到这样一个问题&#xff0…...

大数据技术之Hive(四)分区表和分桶表、文件格式和压缩

一、分区表和分桶表1.1 分区表partitionhive中的分区就是把一张大表的数据按照业务需要分散的存储到多个目录,每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择式选择查询所需要的分区,这样的查询效率辉提高很多。1.1.1 分区表基本语…...

环形缓冲区(c语言)

1、概念介绍 在我们需要处理大量数据的时候,不能存储所有的数据,只能先处理先来的,然后将这个数据释放,再去处理下一个数据。 如果在一个线性的缓冲区中,那些已经被处理的数据的内存就会被浪费掉。因为后面的数据只能…...

创建自助服务知识库的指南

在SaaS领域,自助文档是你可以在客户登录你的网站时为他们提供的最灵活的帮助方式,简单来说,一个自助知识库是一个可以帮助许多客户的文档,拥有出色的自助服务知识库,放在官网或者醒目的地方,借助自助服务知…...

分层测试(1)分层测试是什么?【必备】

1. 什么是分层测试? 分层测试是通过对质量问题分类、分层来保证整体系统质量的测试体系。 模块内通过接口测试保证模块质量,多模块之间通过集成测试保证通信路径和模块间交互质量,整体系统通过端到端用例对核心业务场景进行验证&#xff0c…...

开源ZYNQ AD9361软件无线电平台

(1) XC7Z020-CLG400 (2) AD9363 (3) 单发单收,工作频率400MHz-2.7GHz (4) 发射带PA,最大输出功率约20dbm (5) 接收带LNA,低…...

第四阶段-12关于Spring Security框架,RBAC,密码加密原则

关于csmall-passport项目 此项目主要用于实现“管理员”账号的后台管理功能,主要实现: 管理员登录添加管理员删除管理员显示管理员列表启用 / 禁用管理员 关于RBAC RBAC:Role-Based Access Control,基于角色的访问控制 在涉及…...

JPA——Date拓展之Calendar

Java Calendar 是时间操作类,Calendar 抽象类定义了足够的方法,在某一特定的瞬间或日历上,提供年、月、日、小时之间的转换提供方法 一、获取具体时间信息 1. 当前时间 获取此刻时间的年月日时分秒 Calendar calendar Calendar.getInstance(); int …...

一文吃透 Spring 中的 AOP 编程

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

Apple主推的智能家居是什么、怎么用?一篇文章带你从零完全入门 HomeKit

如果你对智能家居有所了解,那应该或多或少听人聊起过 HomeKit。由 Apple 开发并主推的的 HomeKit 既因为产品选择少、价格高而难以成为主流,又因其独特的优秀体验和「出身名门」而成为智能家居领域的焦点。HomeKit 究竟是什么?能做什么&#…...

SpringCloud系列知识快速复习 -- part 1(SpringCloud基础知识,Docker,RabbitMQ)

SpringCloud知识快速复习SpringCloud基础知识微服务特点SpringCloud常用组件服务拆分和提供者与消费者概念Eureka注册中心原理Ribbon负载均衡原理负载均衡策略饥饿加载Nacos注册中心服务分级存储模型权重配置环境隔离Nacos与Eureka的区别Nacos配置管理拉取配置流程配置热更新配…...

2023上半年北京/上海/广州/深圳NPDP产品经理认证报名

产品经理国际资格认证NPDP是国际公认的唯一的新产品开发专业认证,集理论、方法与实践为一体的全方位的知识体系,为公司组织层级进行规划、决策、执行提供良好的方法体系支撑。 【认证机构】 产品开发与管理协会(PDMA)成立于1979年…...

面试半年,总结了1000道2023年Java架构师岗面试题

半年前还在迷茫该学什么,怎样才能走出现在的困境,半年后已经成功上岸阿里,感谢在这期间帮助我的每一个人。 面试中总结了1000道经典的Java面试题,里面包含面试要回答的知识重点,并且我根据知识类型进行了分类&#xf…...

通过MySQL驱动拦截器实现执行sql耗时计算

文章目录背景具体实现MySQL5MySQL6MySQL8使用方法测试结果背景 公司的一个需求,公司既有的链路追踪日志组件要支持MySQL的sql执行时间打印,要实现链路追踪常用的手段就是实现第三方框架或工具提供的拦截器接口或者是过滤器接口,对于MySQL也不…...

易基因|独家分享:高通量测序后的下游实验验证方法——DNA甲基化篇

大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。此前,我们分享了DNA甲基化研究的测序数据挖掘思路(点击查看详情),进而鉴定出研究的目的基因或目标区域的DNA甲基化。做完测序后,…...

java基础系列(七) 同步和异步理解

一. 问题描述 同步传输和异步传输是web和数据库的重要知识点,会被很多老师强调。那么,它们有什么相同点和不同点?它们对于我们学习编程的意义在哪里? 二. 概念 首先什么是同步和异步? 这里的同步是指&…...

吉林大学 程序设计基础 2022级 OJ期末考试 2.23

本人能力有限,发出只为帮助有需要的人。 以下为实验课的复盘,内容会有大量失真,请多多包涵。 1.双手剑士的最优搭配 每把剑有攻击力和防御力两个属性。双手剑士可以同时拿两把剑,其得到攻击力为两把剑中的攻击力的最大值&#…...

【项目实战】SpringMVC拦截器实战 - 自定义拦截器防止重复提交

一、背景说明 如何能够实现防止重复提交呢?以下是一种可选的方式。 二、代码实战 2.1 注册重复提交拦截器到SpringMVC中 @Configuration @AllArgsConstructor public class ResourcesConfig implements WebMvcConfigurer {private final RepeatSubmitInterceptor repeatSu…...

C++ STL:容器 Container

文章目录1、序列容器1.1、容器共性1.2、vectorvector 结构* vector 扩容原理* vector 迭代器失效1.3、dequedeque 结构deque 迭代器deque 模拟连续空间1.4、listlist 特殊操作list 结构list 迭代器2、关联式容器2.1、容器共性2.2、容器特性3、无序关联式容器3.1、容器共性3.2、…...

urllib之urlopen和urlretrieve的headers传入以及parse、urlparse、urlsplit的使用

urllib库是什么?urllib库python的一个最基本的网络请求库,不需要安装任何依赖库就可以导入使用。它可以模拟浏览器想目标服务器发起请求,并可以保存服务器返回的数据。urllib库的使用:1、request.urlopen(1)只能传入url的方式from http.clie…...

【C++】二叉搜索树的模拟实现

一、概念 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值若它的右子树不为空,则右子树上所有节点的值都大于根节点的值它的左右子树也分别…...

HNU工训中心:元器件及测量基础实验报告

工训中心的牛马实验 1.实验目的 1.熟悉测量验证常用元器件参数、 并采用替代法(测量回路电流)测量其伏安特性的方法。 2.熟悉测量误差及减小测量误差注意事项 2.实验仪器和器材 1.实验仪器. 直流稳压电源型号:IT6302 台式多用表型号:UT805A 2.实验( 箱)器材 电路实验箱…...

博客系统--自动化测试

项目体验地址(账号:123,密码:123)http://120.53.20.213:8080/blog_system/login.html项目后端说明:http://t.csdn.cn/32Nnv项目码云Gitee地址:https://gitee.com/GoodManSS/project/tree/master…...

Day903.自增主键不能保证连续递增 -MySQL实战

自增主键不能保证连续递增 Hi,我是阿昌,今天学习记录的是关于自增主键不能保证连续递增的内容。 MySql保证了主键是自增,但不相对连续;帮助开发人员快速识别每个行的唯一性,并提高查询效率。 自增主键可以让主键索引…...

02-MyBatis查询-

文章目录Mybatis CRUD练习1,配置文件实现CRUD1.1 环境准备Debug01: 别名mybatisx报错1.2 查询所有数据1.2.1 编写接口方法1.2.2 编写SQL语句1.2.3 编写测试方法1.2.4 起别名解决上述问题1.2.5 使用resultMap解决上述问题1.2.6 小结1.3 查询详情1.3.1 编写接口方法1.…...

外盘国际期货招商:2023年3月关注日历,把握重要投资机会

2023年3月大事件日历 关注大事日历,把握重要投资机会 3月1日:马斯克推出特斯拉宏图第三篇章 3月1-2日:G20外长会议 3月4-5日:全国两会召开 3月9日:中国2月CPI、PPI数据 待定(前次进行日期&#xff1a…...