深度学习-线性回归+基础优化算法

news2024/12/23 20:14:10

目录

  • 线性模型
  • 衡量预估质量
  • 训练数据
  • 参数学习
    • 训练损失
    • 最小化损失来学习参数
    • 显式解
  • 总结
  • 基础优化
    • 梯度下降
      • 选择学习率
    • 小批量随机梯度下降
      • 选择批量大小
  • 总结
  • 线性回归的从零开始实现
    • 实现一个函数读取小批量效果展示
      • 这里可视化看一下
    • 线性回归从零开始实现
    • 线性回归的简洁实现效果展示
    • 线性回归的简洁实现
  • 问题总结

线性模型

在这里插入图片描述
线性模型可以看做是单层神经网络

在这里插入图片描述




衡量预估质量

在这里插入图片描述




训练数据

在这里插入图片描述

参数学习

训练损失

在这里插入图片描述
这里的b应该加粗,原先b是标量然后通过广播机制变为一列,即向量b。

最小化损失来学习参数

在这里插入图片描述

显式解

加入一列全一的特征,加入X中。即:
在这里插入图片描述
将偏差加入权重。即:
在这里插入图片描述


损失函数:

在这里插入图片描述


示范过程:

在这里插入图片描述
在这里插入图片描述

因为是线性模型:所以损失是凸函数,所以最优解满足
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述




总结

1、线性回归是对n维输入的加权,外加偏差。
2、使用平方损失来衡量预测值和真实值的差异。
3、线性回归有显示解。
4、线性回归可以看做是单层神经网络。



基础优化

梯度下降

当一个模型没有显式解的时候

在这里插入图片描述

选择学习率

在这里插入图片描述




小批量随机梯度下降

在这里插入图片描述

选择批量大小

在这里插入图片描述




总结

在这里插入图片描述




线性回归的从零开始实现

我们将从零开始实现整个方法,包括数据流水线、模型、损失函数和小批量随机梯度下降优化器。
在这里插入图片描述
在这里插入图片描述

import torch
def synthetic_data(w, b, num_examples):
    """生成y=Xw+b+噪声。"""
    X = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))


true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
print('features:', features[0], '\nlabel:', labels[0])

正态分布函数:normal()
1、normal(0,1,(num_examples,len(w)))表示均值为0,方差为1的随机数,它的大小是说有num_examples个样本,列数是w的长度

2、矩阵乘法:matmul()

3、y.reshape((-1, 1)中的-1表示维度的大小自动计算,第二个维度是1表示新数组将有一个列。
例如:

import torch
y = torch.tensor([1, 2, 3, 4, 5])
print(y.reshape((-1, 1)))

结果:
在这里插入图片描述

在这个例子中,-1被自动替换为5,因为y有5个元素,并且你想要一个只有一列的二维数组。所以,根据另一个维度(这里是1)自动计算这个维度的大小。

4、features是特征,features中的每一行都包含一个二维数据样本,labels中的每一行包含一维标签值(一个标量)

在这里插入图片描述

在这里插入图片描述

import torch
from d2l import torch as d2l
import matplotlib.pyplot as plt


def synthetic_data(w, b, num_examples):
    """生成y=Xw+b+噪声。"""
    X = torch.normal(0, 1, (num_examples, len(w)))#方差为0,均值为1,num_examples个样本,列数是w的长度
    y = torch.matmul(X, w) + b #这里的y是一个行向量
    y += torch.normal(0, 0.01, y.shape) 
    #意思是给 y 加上一个符合正态分布的随机噪声。torch.normal(0, 0.01, y.shape) 生成一个与 y 形状相同的张量,
    #其中的元素是从均值为 0、标准差为 0.01 的正态分布中随机抽取的。
    #然后,这个随机生成的张量会被加到 y 上。
    return X, y.reshape((-1, 1)) #这里的y目的是转换为列向量


true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

d2l.set_figsize() #用于设置Matplotlib图像的大小,可以接受两个参数宽度和高度
d2l.plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1) #detach()分离出数值,不再含有梯度
plt.show()

d2l.plt.scatter(): 使用 scatter 函数绘制散点图。
第一个参数是x轴的数据(即 features 的第二列)。
第二个参数是y轴的数据(即 labels)。
第三个参数1: 这是散点的大小。在这里,所有散点的大小都被设置为1。

features[:, 1].detach().numpy():
features[:, 1]:从 features 数组中选择所有行的第二列
.detach(): features 是一个PyTorch张量,.detach() 方法用于创建一个新的张量,从当前计算图中分离出来,这样它就不会计算梯度。这对于绘图来说通常是必要的,因为我们不需要对绘图数据进行反向传播。
.numpy(): 将PyTorch张量转换为NumPy数组,因为 matplotlib 通常与NumPy数组一起使用。

结果:
在这里插入图片描述




实现一个函数读取小批量效果展示

import random
import torch


def synthetic_data(w, b, num_examples):
    """生成y=Xw+b+噪声。"""
    X = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))


true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)


def data_iter(batch_size, features, labels):
    num_examples = len(features) #多个样本
    indices = list(range(num_examples)) #从0到n-1
    # 这些样本是随机读取的,没有特定的顺序
    random.shuffle(indices)  # 将列表中的元素打乱顺序
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(
            indices[i:min(i + batch_size, num_examples)]
        )
        yield features[batch_indices], labels[batch_indices]
		#yield相当于返回一个可迭代对象

batch_size = 10
for X, y in data_iter(batch_size, features, labels):
    print(X, '\n', y)
    break

indices 是一个从0到 num_examples-1 的整数列表,代表所有样本的索引。

i:min(i + batch_size, num_examples) 是一个切片操作,用于从 indices 中选择一部分索引。从 i 开始,选取到 i + batch_size 或者 num_examples(取两者中较小的一个)结束。是为了确保在最后一个批次中不会超出索引范围。例如,如果总共有1000个样本,批大小为100,当 i 为900时,i + batch_size 会超出索引范围,因此 min(i + batch_size, num_examples) 会确保只选取到最后一个索引。

将上面通过切片操作得到的索引列表转换为一个PyTorch张量

data_iter 函数是一个数据迭代器,它接收批大小 batch_size、特征 features 和标签 labels 作为输入。它首先计算样本数量 num_examples,并创建一个从0到 num_examples-1 的索引列表。然后,它打乱索引列表的顺序,以便在每次迭代时随机选择样本。最后,它使用这些随机索引从特征和标签中抽取小批量数据,并使用 yield 语句返回这些数据。yield 使得这个函数成为一个生成器,每次调用时返回一批数据。设置批大小为10,并使用 data_iter 函数迭代数据和标签。在循环中,每次迭代都会打印出一个小批量的特征 X 和标签 y。由于循环后面有一个 break 语句,所以只会打印出第一批数据。

结果:
在这里插入图片描述

这里可视化看一下

import random
import torch
from d2l import torch as d2l
import matplotlib.pyplot as plt


def synthetic_data(w, b, num_examples):
    """生成y=Xw+b+噪声。"""
    X = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))


true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)


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):
        batch_indices = torch.tensor(
            indices[i:min(i + batch_size, num_examples)]
        )
        yield features[batch_indices], labels[batch_indices]


batch_size = 10
for X, y in data_iter(batch_size, features, labels):
    print(X, '\n', y)
    break

# 获取一个批次的数据
X_batch, y_batch = next(data_iter(batch_size, features, labels))

# 绘制批次数据的散点图
d2l.plt.scatter(X_batch[:, 0].numpy(), y_batch.numpy())
d2l.plt.show()

在这里插入图片描述
在这里插入图片描述




线性回归从零开始实现

import random
import torch

def synthetic_data(w, b, num_examples):
    """生成y=Xw+b+噪声。"""
    X = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))


true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)


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):
        batch_indices = torch.tensor(
            indices[i:min(i + batch_size, num_examples)]
        )
        yield features[batch_indices], labels[batch_indices]


batch_size = 10

# 定义初始化模型参数,需要w,b进行更新,所以才将requires_grad设置为True
w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True)
#size=(2, 1)生成的张量 w 是一个形状为 2x1 的二维张量,即它有 2 行和 1 列。
b = torch.zeros(1, requires_grad=True)
#这里的 1 意味着 b 是一个一维张量,它只有一个元素,并且这个元素的值为 0。
#在 PyTorch 中,一维张量通常可以看作是一个向量。
#因此,b 是一个只包含一个元素(值为 0)的向量。


# 定义模型
def linreg(X, w, b):
    """线性回归模型。"""
    return torch.matmul(X, w) + b


# 定义损失函数,其中y_hat是预测值y是真实值
def squared_loss(y_hat, y):
    """均方损失。均方误差公式"""
    return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2


# 定义优化算法
def sgd(params, lr, batch_size):
    """小批量随机梯度下降。"""
    with torch.no_grad():#不需要计算梯度,使用 torch.no_grad() 可以减少内存消耗,并提高运行速度。
        for param in params:#其中param可能是w也可能是b
            param -= lr * param.grad / batch_size
            param.grad.zero_()


lr = 0.03
num_epochs = 3 #意思是把整个数据扫三遍
net = linreg #定义的模型
loss = squared_loss#均方损失
for epoch in range(num_epochs): #每一次对数据扫一遍
    for X, y in data_iter(batch_size, features, labels):
        l = loss(net(X, w, b), y)  #一个长为批量大小的损失
        # 因为’1‘形状是(’batch_size‘,1),而不是一个标量。'1'中的所有元素被加到
        # 并以此计算关于['w','b']的梯度
        l.sum().backward()
        sgd([w, b], lr, batch_size)  # 使用参数的梯度更新
    with torch.no_grad():
        train_l = loss(net(features, w, b), labels)
        print(f'epoch{epoch + 1},loss{float(train_l.mean()):f}')#:f确保train_l.mean()的结果以浮点数形式被格式化并嵌入到字符串中
print(f'w的估计误差:{true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差:{true_b - b}')

在这里插入图片描述
说明 param -= lr * param.grad / batch_size中param.grad / batch_size的含义。是用来计算平均梯度的。
示例:

import torch
 
X = torch.tensor([[1.0, 2.0], [2.0, 3.0], [3.0, 4.0]])
w = torch.tensor([[1.0], [2.0]], dtype=torch.float32, requires_grad=True)
b = torch.tensor([0.0], requires_grad=True)
y = torch.tensor([[0.0], [1.0], [2.0]])
 
y_hat = torch.matmul(X, w) + b
l = (y_hat - y)**2 / 2
l.sum().backward()
 
print(w.grad)
print(b.grad)

运行结果:

tensor([[46.],
        [67.]])
tensor([21.])

计算过程:
在这里插入图片描述
计算损失函数时,对它调用.backward()会将自动求导计算的梯度累积存在param.grad中。当一个批次包含batch_size个样本时,并且每个样本都贡献一个梯度给模型参数。那么调用backward()后,paramgrad中存储的就是这些梯度的和。这就是为什么在更新参数时,需要将param.grad除以batch_size。这样做可以得到一个平均梯度。
这样,w.grad / batch_size和b.grad / batch_size相当于在batch_size中取平均值。
然后这整句公式的含义:是进行梯度下降
在这里插入图片描述




学习率不能太高也不能太低。
当学习率很低时

#当lr = 0.03改为0.001时
lr = 0.001

跑完三次后损失还是很大
在这里插入图片描述

多跑几遍看看

#num_epochs由3改为10
num_epochs = 10

在这里插入图片描述
跑完十次后损失还是很大
学习率很高时

#lr 从0.03改为10时
lr = 10

在这里插入图片描述
这种情况是求导的时候会除0或者是无限的值,然后超出了浮点类型的计算范围。




线性回归的简洁实现效果展示

import torch
from torch.utils import data
from d2l import torch as d2l

def load_array(data_arrays, batch_size, is_train=True):
    """构造一个PyTorch数据迭代器。"""
    #在PyTorch中,data.TensorDataset是一个用于包装数据张量(tensors)的数据集类。
    #*data_arrays 是一个解包操作,它将data_arrays这个元组(或列表)中的每个元素作为单独的参数传递给TensorDataset。
    #data_arrays是一个包含特征张量features和标签张量labels的元组,那么*data_arrays的效果等同于直接传递这两个张量作为参数
    dataset = data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset, batch_size, shuffle=is_train) #每一次随机从中挑选batch_size个样本,并随机打乱顺序


true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)
batch_size = 10
data_iter = load_array((features, labels),batch_size)
print(next(iter(data_iter)))#iter() 函数用于获取一个迭代器对象。next() 函数用于获取迭代器对象的下一个元素。

结果:
在这里插入图片描述




# ’nn‘ 是神经网络的缩写
from torch import nn
#使用框架预定义好的层
net = nn.Sequential(nn.Linear(2, 1))#输入的维度是2,输出的维度是1
#这意味着这个线性层接受一个形状为[batch_size, 2]的张量作为输入,并输出一个形状为[batch_size, 1]的张量。

#初始化模型参数
print(net[0].weight.data.normal_(0, 0.01))#net 是一个 nn.Sequential 的实例,它包含了一个 nn.Linear 层。
#.weight表示该层的权重参数。对于 nn.Linear(2, 1),这个权重参数是一个形状为 [2, 1] 的二维张量。
#.data:这是访问张量底层数据的方式。在这里,我们仅用它来初始化权重。
#normal_(0, 0.01):它会将张量的值替换为从均值为0、标准差为0.01的正态分布中抽取的随机值。这里的下划线 _ 表示这是一个原地操作,它会直接修改调用它的张量,而不是返回一个新的张量。
print(net[0].bias.data.fill_(0))#.bias表示该层的偏置参数。对于nn.Linear(2, 1),这个偏置参数是一个形状为[1]的一维张量。
#fill_(0):它会将张量的所有值设置为给定的标量值,这里是0。


结果:在这里插入图片描述

net = nn.Sequential(nn.Linear(2, 1))的使用示例:

import torch  
import torch.nn as nn  
  
# 定义网络模型  
model = nn.Sequential(nn.Linear(2, 1))  
  
# 创建一个输入张量,形状为 [batch_size, 2]  
input_tensor = torch.randn(3, 2)  # 这里batch_size是3  
  
# 通过网络模型传递输入张量  
output_tensor = model(input_tensor)  
  
# 输出张量的形状将是 [batch_size, 1]  
print(output_tensor.shape)  # 输出: torch.Size([3, 1])



线性回归的简洁实现

# ’nn‘ 是神经网络的缩写
import torch.optim
from torch import nn
from torch.utils import data
from d2l import torch as d2l

def load_array(data_arrays, batch_size, is_train=True):
    """构造一个PyTorch数据迭代器。"""
    #在PyTorch中,data.TensorDataset是一个用于包装数据张量(tensors)的数据集类。
    #*data_arrays 是一个解包操作,它将data_arrays这个元组(或列表)中的每个元素作为单独的参数传递给TensorDataset。
    #data_arrays是一个包含特征张量features和标签张量labels的元组,那么*data_arrays的效果等同于直接传递这两个张量作为参数
    dataset = data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset, batch_size, shuffle=is_train) #每一次随机从中挑选batch_size个样本,并随机打乱顺序


true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)
batch_size = 10
data_iter = load_array((features, labels),batch_size)

#使用框架预定义好的层
net = nn.Sequential(nn.Linear(2, 1))#输入的维度是2,输出的维度是1
#这意味着这个线性层接受一个形状为[batch_size, 2]的张量作为输入,并输出一个形状为[batch_size, 1]的张量。

#初始化模型参数
net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)

#计算均方误差使用的是MSELoss类,也称为平方范数
loss = nn.MSELoss()
#实例化SGD实例,torch.optim.SGD 是一个用于实现随机梯度下降(Stochastic Gradient Descent, SGD)优化算法的类。
trainer = torch.optim.SGD(net.parameters(), lr=0.03)#net.parameters():拿出所有的参数(即权重w和偏置b)。

#训练过程代码和从零开始实现类似
num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:
        l = loss(net(X), y)#这里net自带了模型参数,不需要w和b弄进去了
        trainer.zero_grad()#trainer优化器梯度清零
        l.backward()#这里不需要求和,因为pytorch自动求和了
        trainer.step()#进行模型的更新和从零开始的sgd函数类似
    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')

结果:在这里插入图片描述




问题总结

1、为啥使用平方损失而不是绝对差值呢
区别不大,但绝对差值是个不可导的函数

2、损失为什么要求平均?
求不求平均本质上没有关系,不求平均梯度的数值有点大,如果使用梯度下降的话,那么不除以n的话,就把学习率除以n。除以n的好处是说:不管批量和样本多大我的梯度都差不多,调学习率好调。

3、线性回归损失函数是不是通常都是MSE(均方损失误差)
是的

4、不管是gd(梯度下降)还是sgd(随机梯度下降)怎么找到合适的学习率?有什么好的方法吗?
两个办法
找到一个对学习率不那么敏感的算法,比如adam。
通过合理的参数的初始化

5、针对batchsize大小的数据集进行网络训练的时候,网络中每个参数更新时的减去的梯度是batchsize中每个样本对应参数梯度求和后取得平均值吗?
是的

6、detach()是什么作用?
告诉不要算梯度了

7、如果样本大小不是批量数的整数倍,那需要随机剔除多余的样本吗?
假设有100个样本,批量大小为60
第一次60,那么剩下40怎么办?
1、普遍做法是拿到一个小的样本,长为40的批量样本
2、把不完整的批量大小扔掉
3、从下一个里面补20个

8、本质上我们为什么要用SGD(随机梯度下降),是因为大部分的实际loss(损失函数)太复杂,推导不出导数为0的解么?只能逐个batch去逼近?
是的

9、l.backward()这里是调用pytorch自定义的back propogation(梯度反向传播)吗?
是的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1644405.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】学习笔记——vector_3

文章目录 七、vector3. vector的模拟实现4. vector实现代码整合 未完待续 七、vector 3. vector的模拟实现 上篇文章我们讲解了非常 玄幻 的拷贝构造函数&#xff0c;同样的方法&#xff0c;我们也能用这种方法来实现 赋值重载函数 。 void swap(vector<T>& v) {s…

哈尔滨等保测评模拟题

《中华人民共和国网络安全法》中规定计算机信息系统安全保护等级共分为五级。&#xff08; t &#xff09;2019年&#xff0c;随着标准GB/T22239的更新&#xff0c;等级保护进入2.0时代。&#xff08; t&#xff09;某单位信息系统的等级定义为S2A3G2&#xff0c;根据取高原则…

自学Python爬虫js逆向(二)chrome浏览器开发者工具的使用

js逆向中很多工作需要使用浏览器中的开发者工具&#xff0c;所以这里以chrome为例&#xff0c;先把开发者工具的使用总结一下&#xff0c;后面用到的时候可以回来查询。 Google Chrome浏览器的开发者工具是前端开发者的利器&#xff0c;它不仅提供了丰富的功能用于开发、调试和…

实验九 Java 语言网络通信程序设计练习(课内实验)

一、实验目的 本次实验的主要目的是练习网络通信程序的设计方法&#xff0c;并掌握计算机网络基 础知识、Java语言网络通信程序类库的结构和使用方法。 二、实验要求 1. 认真阅读实验内容&#xff0c;完成实验内容所设的题目。 2. 能够应用多种编辑环境编写Java语言源程序…

如何使用DEEPL免费翻译PDF

如何使用DEEPL免费翻译PDF 安装DEEPL取消PDF限制 安装DEEPL 安装教程比较多&#xff0c;这里不重复。 把英文pdf拖进去&#xff0c;点翻译&#xff0c;在下面的框中有已经翻译完毕的文档。 但是存在两个问题 问题1&#xff1a;这些文档是加密的。 问题2&#xff1a;带有DeepL标…

去掉antd design vue组件库中表格的分割线

前言&#xff1a; 最近在公司完成UI设计稿的时候&#xff0c;需要使用antd design vue组件库中表格&#xff0c;但是UI设计稿中并不需要表格分割线&#xff0c;尝试了多种方式最后实现如下&#xff1a; <style lang"scss" scoped>::v-deep .ant-table-cell::…

Django中如何让页面之间建立关系

今天给大家讲解两种让页面建立联系的方式 一、重定向 二、表单提交 先看第一种方式&#xff0c;重定向 首先需要了解客户端发起请求的过程 1、客户端向服务端发起请求,比如请求地址是&#xff1a;http://127.0.0.1:8000/lili/submit/ 2、程序根据路由找到视图函数 3、执行视…

汽车 - 什么是车轮抱死

车轮抱死分为两种情况&#xff0c;一种是车辆故障层面&#xff0c;另一种是驾驶过程中的物理现象。我们先来说最通俗的刹车车轮抱死吧。 刹车制动车轮抱死 车轮停止轴向转动就是抱死&#xff0c;有速度的情况下抱死车轮&#xff0c;如果车辆的惯性动能大于轮胎抓地力&#xff0…

How Linux Works I - How Linux Start Up

目录 Linux如何启动&#xff1f; 启动信息 内核启动初始化与启动选项 写在前面&#xff1a;上一个专栏中我写完了内核源码层面看Linux&#xff0c;我们把抽象层拉高一点&#xff0c;看看Linux是如何工作的&#xff01; Linux如何启动&#xff1f; BIOS&#xff08;Basic Inpu…

CSS探索之旅:定位

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文我们详细介绍 css中定位的相关知识点 定位的用处 先简单认识一下定位是做什么的。 其实&#xff0c;定位的功能就像他的名字一样&#xff0c;可以规定显示在网页的一个位置。 其他布局的效果 我们之前默认…

C语言:环形链表

1.例子1&#xff1a;环形链表 142. 环形链表 II - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;我们先定义两个变量slow和fast&#xff0c;slow每次走一步&#xff0c;fast每次走两步&#xff0c;如果链表是环形链表&#xff0c;那么必定存在fast不会走到链表的最后…

利用github pages建立Serverless个人博客

利用github pages建立Serverless个人博客 概述 使用github pages&#xff0c;可以在github上部署静态网站。利用这个功能&#xff0c;可以很方便地实现个人博客的发布托管。 比如我的个人博客&#xff1a;Buttering’s Blog 对应代码仓库&#xff1a;buttering/EasyBlog: 自…

从一到无穷大 #26 Velox:Meta用cpp实现的大一统模块化执行引擎

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 引言业务案例PrestoSparkXStreamDistributed messaging systemData IngestionData Pr…

【软件测试理论001】认识软件测试、测试分类、测试原则

目录 1 认识软件测试 1.1 什么是软件 1.2 什么是软件测试 1.3 软件测试的发展历程 1.4 为什么要进行软件测试 1.5 软件测试职业规划 2 软件测试的分类 2.1 按开发阶段划分 单元测试&#xff08;Unit Testing&#xff09; 集成测试&#xff08;Integration Testing&am…

【ChatGPT with Date】使用 ChatGPT 时显示消息时间的插件

文章目录 1. 介绍2. 使用方法2.1 安装 Tampermonkey2.2 安装脚本2.3 使用 3. 配置3.1 时间格式3.2 时间位置3.3 高级配置(1) 生命周期钩子函数(2) 示例 4. 反馈5. 未来计划6. 开源协议7. 供给开发者自定义修改脚本的文档7.1 项目组织架构7.2 定义新的 Component(1) 定义一个新的…

Vue2——前端笔记

Vue 一、Vue核心1.1、vue简介1.2、初始vue1.3、模板语法1.4、数据绑定1.5、el与data的两种写法1.6、MVVM模型1.7、Vue中的数据代理1.7.1、Object.defineProperty() 理解1.7.2、Vue中的数据代理 1.8、事件处理1.8.1、事件的基本用法1.8.2、事件修饰符1.8.3、键盘事件 1.9、计算属…

电商中文场景多模态测试prompt

魔搭社区汇聚各领域最先进的机器学习模型&#xff0c;提供模型探索体验、推理、训练、部署和应用的一站式服务。https://www.modelscope.cn/datasets 多模态大模型Yi-VL-plus体验 效果很棒 - 知乎最近测了一下零一万物的多模态大模型Yi-VL-plus的效果&#xff0c;发现多模态理解…

CNN实现卫星图像分类(tensorflow)

使用的数据集卫星图像有两类&#xff0c;airplane和lake&#xff0c;每个类别样本量各700张&#xff0c;大小为256*256&#xff0c;RGB三通道彩色卫星影像。搭建深度卷积神经网络&#xff0c;实现卫星影像二分类。 数据链接百度网盘地址&#xff0c;提取码: cq47 1、查看tenso…

【一刷《剑指Offer》】面试题 14:调整数组顺序使奇数位于偶数前面

力扣对应题目链接&#xff1a;LCR 139. 训练计划 I - 力扣&#xff08;LeetCode&#xff09; 牛客对应题目链接&#xff1a;调整数组顺序使奇数位于偶数前面(二)_牛客题霸_牛客网 (nowcoder.com) 核心考点&#xff1a;数组操作&#xff0c;排序思想的扩展使用。 一、《剑指Off…

LAME及 iOS 编译

文章目录 关于 LAME编译 for iOS 关于 LAME 官网&#xff1a;https://lame.sourceforge.io LAME是根据LGPL许可的高质量MPEG音频层III&#xff08;MP3&#xff09;编码器。 LAME的开发始于1998年年中左右。Mike Cheng 最开始将它作为针对8hz-MP3编码器源的补丁。在其他人提出…