用Pytorch构建一个喵咪识别模型

news2025/7/6 18:10:00

 本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052

目录

一、前言

二、问题阐述及理论流程

2.1问题阐述

2.2猫咪图片识别原理 

三、用PyTorch 实现 

3.1PyTorch介绍

3.2PyTorch 构建模型的五要素

3.3PyTorch 实现的步骤

3.3.1.数据

3.3.2模型

3.3.3损失函数

3.3.4优化器

3.3.5迭代训练

四、我用了哪些方法防止过拟合?

4.1控制网络规模

4.2数据增强

4.3正则化

4.4K 折交叉验证

五、用自己的图片验证

5.1输入数据

5.2代码实现 

5.3结果输出及分析

完整代码


一、前言

        舍友最近养了只猫咪,看起来很好看,但是你绝对想不到它拉的shi巨臭啊,哈哈哈哈,就很离谱。刚好最近在学习Pytorch,心血来潮,就用Pytorch来做个喵咪识别模型并,于是就有了本篇博文。

     

 

二、问题阐述及理论流程

2.1问题阐述

现一共有 259 张图片,总体分为两类:

有猫咪类

无猫咪类 

2.2猫咪图片识别原理 

三、用PyTorch 实现 

3.1PyTorch介绍

  PyTorch 是一个开源的深度学习框架,它的底层基于 Torch ,但实现与运用全部由 python 来完成。该框架主要用于人工智能领域的科学研究与应用开发。

3.2PyTorch 构建模型的五要素

1.数据:包括数据读取,数据清洗,进行数据划分和数据预处理。

2.模型:包括构建模型模块,组织复杂网络,初始化网络参数,定义网络层。

3.损失函数:包括创建损失函数,设置损失函数超参数,要根据不同任务选择合适的损失函数。

4.优化器:包括根据梯度使用某种优化器更新参数,管理模型参数,调整学习率。

5.迭代训练:组织上述 4 个模块进行反复训练。观察训练效果,绘制 Loss/ Accuracy 曲线或者用 TensorBoard 进行可视化分析。

3.3PyTorch 实现的步骤

3.3.1.数据

        在深度学习时会遇到各种不同形式的数据,如文本、图片、音频等,而每种数据又有多种文件类型。因此拿到数据,我们首先应该了解它的内部结构。

  h5py 文件是一种 " Dataset " 和 " Group " 二合一的容器:

  • 「Dataset」: 类似数组组织的数据的集合,像 numpy 数组一样工作;

  • 「Group」: 包含了其它 Dataset 和 其它 Group ,像字典一样工作。


读取下载好的 h5py 文件(以含有 209 张图片的测试集为例)

import h5py

f = h5py.File("/home/tian/dataset/catvnocat/train/train_catvnoncat.h5","r")#"r"代表读取模式
for key in f.keys():
    print(key)
 
#输出
#list_classes
#train_set_x
#train_set_y

依次打印出这三个" key "下的内容 

print(f["list_classes"])
print(f["train_set_x"])
print(f["train_set_y"])

#输出
#<HDF5 dataset "list_classes": shape (2,), type "|S7">
#<HDF5 dataset "train_set_x": shape (209, 64, 64, 3), type "|u1">
#<HDF5 dataset "train_set_y": shape (209,), type "<i8">

可以得到三个 Dataset 的相关信息:

  • list_classes:包含两个元素 ' non-cat ' 和' cat ',代表无猫和有猫这两个大类。

  • train_set_x :一个四维张量,形状为 209 * 64 * 64 * 3。代表一共有 209 张图片,其中每张图片以像素大小为 64 * 64 的三通道矩阵存储信息。

  • train_set_y :一个一维数组,元素全部存储着 209 张图片对应的标签,其中有猫为 1 ,无猫为 0 。


该 h5py 文件的结构如下图所示:

制作数据集

  从torch.utils.data中引入DatasetDataset是能够表示数据集的抽象类,一般有三个方法:

  • 「__init__方法」

    用于类的初始化,负责创建类的实例属性并进行赋值,并在实例化类后自动执行。这里我创建的 MyData 类中包含以下属性:

    • Archive:文件的路径及对文件的操作,只读或写入

    • Image:样本中的图片或者包含全部图片信息的像素矩阵

    • Label:样本中的标签

    • Transform:可能要对数据进行的变换或增强

  • 「__getitem__方法」

    所有子类都必须重写该方法,该方法通过索引(index)或键(key)访问样本,返回值为 样本和标签。

  • 「__len__方法」

    返回数据集的大小。

 

from torch.utils.data import Dataset

class MyDataset(Dataset):
    
    def __init__(self, archive , image , label , transform = None ):

        self.Archive = h5.File(archive, 'r')
        self.Images = self.Archive[image]
        self.Labels = self.Archive[label]
        self.Transform = transform
    
    def __getitem__(self,index):
                
        image = self.Images[index]
        label = self.Labels[index]
        if self.Transform is not None:
            image = self.Transforms(image)  
        return image ,label
    
    def __len__(self):
        return len(self.Labels)

train_dataset = MyDataset('/home/tian/dataset/catvnocat/train/train_catvnoncat.h5','train_set_x','train_set_y',train_transformer)
test_dataset = MyDataset('/home/tian/dataset/catvnocat/test/test_catvnoncat.h5','test_set_x','test_set_y',test_transformer)

读取数据集

  从torch.utils.data引入DataLoader,它帮助我们从Dataset中加载样本数据。它联合了数据集 Dataset 和采样器 Sampler,使其本身可以像一个迭代器一样工作。前者提供数据来源,后者提供索引。

from torch.utils.data import Dataloader

train_loader = DataLoader(train_dataset, batch_size = batch_size_train, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size = batch_size_test, shuffle=False)

shuffle = True指的是将样本打乱,一般只针对训练集。

3.3.2模型

  该神经网络采用简单的 2 隐藏层全连接的方式,并在每一层采用 ReLU 函数作为激活函数,最后通过 Softmax 函数输出预测概率,以达到二分类的目的。

class Net(nn.Module):

    def __init__(self, in_dim, n_hidden_1,n_hidden_2,out_dim):
        super(Net, self).__init__()
        self.layer1 = nn.Sequential(nn.Linear(in_dim, n_hidden_1),nn.BatchNorm1d(n_hidden_1), nn.ReLU(True),nn.Dropout(0.25))
        self.layer2 = nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2),nn.BatchNorm1d(n_hidden_2), nn.ReLU(True),nn.Dropout(0.25))
        self.layer3 = nn.Sequential(nn.Linear(n_hidden_2, out_dim), nn.Softmax(dim = 1))
     
    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        return x

3.3.3损失函数

  交叉熵损失函数是二分类问题常用的损失函数,可以直接在torch.nn里直接调用,其形式为:

criterion = nn.CrossEntropyLoss()

3.3.4优化器

  在 torch.optim中直接调用随机梯度下降法 SGD:

optimizer = optim.SGD(model.parameters(), lr = learning_rate, weight_decay = 1e-4)

3.3.5迭代训练

  一切准备工作就绪,进行迭代训练。也可以根据需要绘制 Loss/ Accuracy 曲线观察 train_loss 和 val_loss,并以此为依据来调试超参数。

for epoch in range(num_epoches+1):
    model.train()    
    for data in train_loader:
        img, label = data
        img = img.view(img.size(0), -1)  
        img = Variable(img)
        label = Variable(label)
        out = model(img.to(torch.float32))
        loss = criterion(out, label)
        _, pred = torch.max(out, 1)
        acc = (pred == label).sum().item() / (len(train_dataset))

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    model.eval()
    eval_loss = 0
    eval_acc = 0        
    for data in test_loader:
        img, label = data
        img = img.view(img.size(0), -1)
        out = model(img.to(torch.float32))
        loss_1 = criterion(out, label)
        eval_loss += loss_1.data.item()*label.size(0)
        _, pred = torch.max(out, 1)
        eval_acc += (pred == label).sum().item() / len(test_dataset)

    if epoch%50 == 0:
        train_losses.append(loss.data.item())
        train_acc.append(acc)
        test_losses.append(loss_1.data.item())
        test_acc.append(eval_acc)

        print('epoch: {}'.format(epoch))
        print('Train Loss: {:.4}, Train_Acc: {:.4}'.format(loss.data.item(), acc))
        print('Test Loss: {:.4f}, Test_Acc: {:.4f}'.format(eval_loss / (len(test_dataset)),eval_acc))


fig = plt.figure()
plt.plot(train_counter, train_losses, color='blue')
plt.plot(test_counter, test_losses, '--',color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('negative log likelihood loss')

fig = plt.figure()
plt.plot(train_counter, train_acc, color='blue')
plt.plot(test_counter, test_acc, '--',color='red')
plt.legend(['Train Acc', 'Test Acc'], loc='lower right')
plt.xlabel('number of training examples seen')
plt.ylabel('Acc')

plt.show()

「结果展示」

         可以看到,过拟合的情况没有发生,并且训练集和测试集的准确率都接近 90%,相对于原本的准确率有了较大的提高。

四、我用了哪些方法防止过拟合?

4.1控制网络规模

  当神经网络具有过多的神经元时,训练集中包含的有限信息量不足以训练隐藏层中的所有神经元,很可能导致过拟合。因此要控制网络规模,既不能太宽也不能太深。

4.2数据增强

  样本量少是造成过拟合的主要原因之一,但我们往往很难从源头上解决这一问题。数据增强通过对现有的样本(以图片为例)进行各种不同的变换(如随机自定义大小裁剪、随机翻转、随机旋转、增加色彩对比度等),然后适当增加训练迭代次数,从而达到样本量扩张的效果。

  本文采用了以下手段进行数据增强:

  • 对输入图片随机裁剪,将原本像素大小为64的图片裁剪成像素大小为48的图片

  • 在水平方向上对一半的图片进行随机翻转

  • 在垂直方向上对一半的图片进行随机翻转

  • 对图在一定角度内进行旋转

from torchvision import transforms

train_transformer = transforms.Compose([
    transforms.ToPILImage(),
    transforms.RandomResizedCrop(48),
    transforms.RandomHorizontalFlip(), 
    transforms.RandomRotation((-15, 15)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])

test_transformer = transforms.Compose([
    transforms.ToPILImage(),
    transforms.Resize(48),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])

 测试集大多数情况下不进行数据增强,这里为了适应训练集数据增强后的图片大小对测试集进行了尺寸缩放,同样变为像素大小为的图片。

4.3正则化

  • 「Drop_out」

  作为常用的预防过拟合的方法之一,它的主要思想是让隐藏层的节点在每次迭代时有一定几率失效,从而避免对某个节点的强依赖,让反向传播的修正值可以更加平衡的分布到各个参数上。也在一定程度上降低了网络复杂度。

  • 「weight_decay」

  过拟合时模型会拟合很多位置较偏的点,导致拟合函数在某些小区间剧烈变化,权重 w 的绝对值很大。此方法通过控制权重 w 的大小来缓解过拟合的情况。

4.4K 折交叉验证

  以模型调优的思路来缓解过拟合。在训练每种模型时,通过k折交叉验证得到k组不同的训练集和测试集,并将每组的误差平均作为衡量模型泛化能力的准则,从而选择出泛化能力最好的(即最不容易发生过拟合)的模型。

kf = KFold(n_splits = 7, shuffle=True)

五、用自己的图片验证

        训练神经网络最终的目的就是为了应用,因此最后一个环节我们用自己的图片来验证“猫咪识别器”的性能如何。


5.1输入数据

有猫咪类

 无猫咪类

 

5.2代码实现 

from PIL import Image
def trans_pic(img_dir,width,height):
 
    image = Image.open(img_dir) #打开图片
    resized_image = image.resize((width, height), Image.ANTIALIAS)
    data = np.asarray(resized_image)#转换为矩阵
    image = Image.fromarray(data)  #将之前的矩阵转换为图片
    #image.show()#调用本地软件显示图片,win10是叫照片的工具
    return data

path_cat = [r"/home/tian/Pictures/cat_1.jpg",
        r"/home/tian/Pictures/cat_2.jpg",
        r"/home/tian/Pictures/cat_3.jpg",
        r"/home/tian/Pictures/cat_4.jpg",
        r"/home/tian/Pictures/cat_5.jpg"]

path_nocat = [r"/home/tian/Pictures/nocat_1.jpg",
        r"/home/tian/Pictures/nocat_2.jpg",
        r"/home/tian/Pictures/nocat_3.jpg",
        r"/home/tian/Pictures/nocat_4.jpg",
        r"/home/tian/Pictures/nocat_5.jpg"]


for i in range(5): 
    
    a = test_transformer(trans_pic(path_cat[i],48,48)).view(1, -1)
    b = test_transformer(trans_pic(path_nocat[i],48,48)).view(1, -1)
    out_1 = model(a.to(torch.float32))
    out_2 = model(b.to(torch.float32))
    _, pred_1= torch.max(out_1, 1)
    _, pred_2= torch.max(out_2, 1) 
    
    if pred_1 == 1:
        print("第",i+1,"张猫咪图片识别正确")
    if pred_1 == 0:
        print("第",i+1,"张猫咪图片识别错误")
    if pred_2 == 1:
        print("第",i+1,"张非猫咪图片识别错误")
    if pred_2 == 0:
        print("第",i+1,"张非猫咪图片识别正确")
    print("\n")

5.3结果输出及分析

「结果输出」

第 1 张猫咪图片识别正确
第 1 张非猫咪图片识别正确


第 2 张猫咪图片识别正确
第 2 张非猫咪图片识别正确


第 3 张猫咪图片识别正确
第 3 张非猫咪图片识别错误


第 4 张猫咪图片识别正确
第 4 张非猫咪图片识别错误


第 5 张猫咪图片识别正确
第 5 张非猫咪图片识别正确

「结果分析」

  • 猫咪图片:都能识别正确。

  • 非猫咪图片:第三张、第四张图片出现了识别错误。

    • 对于风景图这种与猫咪图片差别很大的图片,识别器能轻松地辨别;

    • 对于老虎、老鼠这些与猫咪在特征上有很多相似地方的动物,猫咪识别器显然还不具备能力将他们很好地区分开来。

  因此在图片识别领域,我们总是需要更合适的网络结构、更大规模的数据以及更合适的超参数选择。

完整代码

import numpy as np
import h5py as h5
import torch
from torch.utils.data import Dataset,DataLoader
import torch.nn.functional as F
from torch import nn, optim
from torch.autograd import Variable
from torchvision import datasets, transforms
from matplotlib import pyplot as plt

batch_size_train = 209
batch_size_test = 50
learning_rate = 0.0075
num_epoches = 3500
momentum = 0.5


train_transformer = transforms.Compose([
    transforms.ToPILImage(),
    transforms.RandomResizedCrop(48),
    transforms.RandomHorizontalFlip(),
    
    transforms.RandomVerticalFlip(),
    transforms.RandomRotation((-15, 15)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])


test_transformer = transforms.Compose([
    transforms.ToPILImage(),
    transforms.Resize(48), 
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])

class MyDataset(Dataset):
    
    def __init__(self, archive,image,label,transform = None):

        self.archive = h5.File(archive, 'r')
        self.images = self.archive[image]
        self.labels = self.archive[label]
        self.transform = transform
    
    def __getitem__(self,index):
        
        
        image = self.images[index]
        label = self.labels[index]
        if self.transform is not None:
            image = self.transform(image)  
        return image ,label
    
    def __len__(self):
        return len(self.labels)
        
train_dataset = MyDataset('/home/tian/dataset/catvnocat/train/train_catvnoncat.h5','train_set_x','train_set_y',train_transformer)
test_dataset = MyDataset('/home/tian/dataset/catvnocat/test/test_catvnoncat.h5','test_set_x','test_set_y',test_transformer)
train_loader = DataLoader(train_dataset, batch_size=batch_size_train, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size_test, shuffle=False)



class Batch_Net(nn.Module):
    
    def __init__(self, in_dim, n_hidden_1,n_hidden_2,out_dim):
        super(Batch_Net, self).__init__()
        self.layer1 = nn.Sequential(nn.Linear(in_dim, n_hidden_1),nn.BatchNorm1d(n_hidden_1), nn.ReLU(True),nn.Dropout(0.25))#,nn.Dropout(0.3))
        self.layer2 = nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2),nn.BatchNorm1d(n_hidden_2), nn.ReLU(True),nn.Dropout(0.25))#,nn.Dropout(0.5))#,nn.Dropout(0.3))#,nn.Dropout(0.5))
        self.layer3 = nn.Sequential(nn.Linear(n_hidden_2, out_dim),nn.Softmax(dim = 1))
     
    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        
        return x

#构建模型实例 
model = Batch_Net(48*48*3,90,10,2)

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learning_rate,weight_decay= 1e-4)



train_losses = []
train_acc = []
train_counter = [i * len(train_loader)*50 for i in range(num_epoches // 50 + 1)]
test_losses = []
test_acc = []
test_counter = [i * len(test_loader)*50 for i in range(num_epoches // 50 + 1)]


for epoch in range(num_epoches+1):
    model.train()
    
    for data in train_loader:
        img, label = data
        img = img.view(img.size(0), -1)  
        img = Variable(img)
        label = Variable(label)
        out = model(img.to(torch.float32))
        loss = criterion(out, label)
        _, pred = torch.max(out, 1)
        acc = (pred == label).sum().item() / (len(train_dataset))

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    model.eval()
    eval_loss = 0
    eval_acc = 0
        
    for data in test_loader:
        img, label = data
        img = img.view(img.size(0), -1)
        out = model(img.to(torch.float32))
        loss_1 = criterion(out, label)
        eval_loss += loss_1.data.item()*label.size(0)
        _, pred = torch.max(out, 1)
        eval_acc += (pred == label).sum().item() / len(test_dataset)

    if epoch%50 == 0:
        train_losses.append(loss.data.item())
        train_acc.append(acc)
        test_losses.append(loss_1.data.item())
        test_acc.append(eval_acc)

        print('epoch: {}'.format(epoch))
        print('Train Loss: {:.4}, Train_Acc: {:.4}'.format(loss.data.item(), acc))
        print('Test Loss: {:.4f}, Test_Acc: {:.4f}'.format(eval_loss / (len(test_dataset)),eval_acc))


fig = plt.figure()
plt.plot(train_counter, train_losses, color='blue')
plt.plot(test_counter, test_losses, '--',color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('negative log likelihood loss')

fig = plt.figure()
plt.plot(train_counter, train_acc, color='blue')
plt.plot(test_counter, test_acc, '--',color='red')
plt.legend(['Train Acc', 'Test Acc'], loc='lower right')
plt.xlabel('number of training examples seen')
plt.ylabel('Acc')

plt.show()

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

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

相关文章

重新学习Vue,了解一下Vue的故事和核心特点

vueVue的由来Vue是什么1.响应的数据绑定2.可组合视图组件3.虚拟DOM4.MVVM模式5.声明式渲染总结Vue的由来 大家应该都知道VUE是尤大大尤雨溪开发出来的&#xff0c;尤大大专业不是计算机&#xff0c;而是室内艺术专业。后来尤大大到帕森斯设计学院进修艺术研究硕士学位&#xf…

猿创征文|【HTML】标签学习之路

&#x1f496;目录 一、HTML语法规范 1.基本语法概述 2.标签关系 二、HTML基本结构标签 1.第一个HTML页面 2.HTML基本结构标签总结 一、HTML语法规范 1.基本语法概述 html是由尖括号包围的关键词&#xff0c;列如&#xff1a;<html>。html标签通常是成对出现的&a…

前端微信小程序开发基础

文章参考&#xff08;黑马小程序教学视频&#xff09;仅供参考与学习 简介 小程序和普通页面开发的区别 运行环境不同 网页运行在浏览器中&#xff0c;小程序运行在微信环境中 API不同 由于运行环境不同&#xff0c;所以小程序中&#xff0c;无法调用DOM和BOM的API. 但是…

如何使用 CSS 使表格居中(快速指南)

在网页设计中使用表格有一段有趣的历史。在采用 CSS 之前&#xff0c;表格不仅仅用于以传统方式显示表格数据练习列表&#xff0c;而是更常用于控制完整的页面布局。 那时&#xff0c;HTML 表格用于定义网页的结构和视觉外观&#xff0c;其中表格的位置可以直接在 HTML 中指定…

input详解之文件上传

input 全部类型 常用的并且能为大多数浏览器所识别的类型大概有&#xff1a;text、password、number、button、reset、submit、hidden、radio、checkbox、file、image、color、range、date、month、week、time、datetime-local。 1、一般类型 <!-- text类型 文本框 默认…

Vue2 Element DatePicker组件设置默认日期、控制日期范围

文章目录前言一、设置默认日期1.不要用placeholder2.设置动态的默认日期二、限制日期选取1.方案2.举例总结前言 以前都是做练习, 上周拿到这个任务直接被卡住… 一、设置默认日期 1.不要用placeholder 依然不使用placeholder属性, 在v-model初始就绑定了时间的情况下, 组件可…

vue导入处理Excel表格详解

目录1. 前言2.vue导入Excel表格2.1 使用ElementUI中的upload组件2.2 使用input文件上传3. 总体代码与效果4. 总结1. 前言 最近遇到前端导入并处理excel表格的情况&#xff0c;趁此机会刚好研究一下vue导入并处理excel数据&#xff1b;当然自己手撸一个工具没有那么多时间&#…

vue3 使用tinymce编辑器实现单/多图片上传,附件上传,视频上传

安装: 我用的是tinymce最新版本v6 npm install tinymce -S npm install tinymce/tinymce-vue -S 2.安装语言包:Language Packages | Trusted Rich Text Editor | TinyMCE 3.在项目public文件夹下--新建tinymce文件夹,安装包解压在该文件夹下 封装组件TEditor.vue <templa…

微信小程序实现上拉加载下拉刷新(即粘即用)

前言 去年有出过一篇关于 vue 实现上拉加载下拉刷新的功能&#xff0c;最近微信小程序中也用到了这个功能&#xff0c;下面一起来看看微信小程序中是怎么实现这个小功能的吧。 实现效果如下&#xff1a; 实现思路&#xff1a; 1. 首先需要在使用到的 json 文件下配置 "ena…

vue项目遇见事件冒泡如何处理

开发环境 Win 10 element-ui "2.8.2" Vue 2.9.6 事件冒泡简介 如下图&#xff0c;当我们点击页面某个元素时&#xff0c;会产生点击事件&#xff0c;事件由外到内&#xff0c;逐层递进&#xff08;事件捕获阶段&#xff0c;途中的1->2->3->4&#xff09…

DVWA靶场搭建

1.靶场是什么&#xff0c;靶场的搭建 在学习web安全的过程中&#xff0c;靶场是必不可少的&#xff0c;毕竟在计算机界&#xff0c;任何理论知识都不如实操 靶场就是人为提供的带有安全漏洞的服务&#xff0c;每一个学习者都可以在本地快速搭建来实操&#xff0c;回溯漏洞的发…

超好玩的js页面效果---实现数值的动态变化

✅ 作者简介&#xff1a;一名普通本科大三的学生&#xff0c;致力于提高前端开发能力 ✨ 个人主页&#xff1a;前端小白在前进的主页 &#x1f525; 系列专栏 &#xff1a; node.js学习专栏 ⭐️ 个人社区 : 个人交流社区 &#x1f340; 学习格言: ☀️ 打不倒你的会使你更强&a…

JS实战——轮播图

目录 一、轮播图介绍 二、原理 三、轮播图基本htm布局 四、轮播图CSS布局 五、轮播图JS布局 六、轮播图效果 一、轮播图介绍 现在我们在很多网站上都能看到轮播图&#xff0c;像某东、某宝、某猫等等大小型网站上都有应用。下面就是某宝上的轮播图样式。 二、原理 将一些图…

【chatgpt谈前端三大主流框架】React、Vue和Angular的优缺点及如何选择

文章目录React优点缺点Vue优点缺点Angular优点缺点总结chatgpt号称无所不能&#xff0c;今天我们就来考考他&#xff0c;让他来对比下React、Vue和Angular。下面是chatgpt全部回答&#xff0c;大家觉得他分析得对吗&#xff1f;React、Vue和Angular都是目前最流行的前端框架&am…

【vue2】使用elementUI进行表单验证实操(附源码)

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;vue使用elementUI进行表单验证实操&#xff08;附源码&#xff09; 【前言】我们在构建一…

VUE 使用 vue create 命令 创建 vue2.0 项目

为了保证创建过程中避免出现因权限不足的原因 从而 导致创建失败的问题&#xff0c;我们使用 管理员身份 打开命令行 第一步&#xff0c;打开命令行后&#xff0c;首先进入我们想要创建项目的目录下 g: 表示切换进入G盘 cd git 表示打开 当前盘下的 git 文件夹 大家可以根据以上…

如何解决 npm 安装依赖报错 ERESOLVE unable to resolve dependency tree

现代前端项目开发中依赖管理已经是不可或缺的一环&#xff0c;然后由于各种问题&#xff0c;如历史原因、项目缺少维护等&#xff0c;前端项目在依赖管理中会遇到非常多的问题。本篇文章讨论其中一种&#xff0c;当 npm install 时遇到报错 ERESOLVE unable to resolve depende…

百度文心一言对标 ChatGPT,你怎么看?

文心一言 VS ChatGPT接受不完美 期待进步里程碑意义文心一言初体验✔ 文学创作✔ 商业文案创作✔ 数理逻辑推算✔ 中文理解✔ 多模态生成写在最后何为文心&#xff1f;“文”就是我们中华语言文字中的文&#xff0c;“心”是希望该语言模型可以用心的去理解语言&#xff0c;用心…

手把手教你基于HTML、CSS搭建我的相册(上)

The sand accumulates to form a pagoda写在前面HTML是什么&#xff1f;CSS是什么&#xff1f;demo搭建写在最后写在前面 其实有过一些粉丝咨询前端该从什么开始学&#xff0c;那当然是我们的前端基础三件套开始学起&#xff0c;HTML、CSS、javaScript&#xff0c;前端的大部分…

pnpm学习

1、pnpm是什么&#xff1f; 现代的包管理工具 pnpm&#xff08; performant npm &#xff09;&#xff0c;意思是高性能的 npm 它由 npm/yarn 衍生而来&#xff0c;但却解决了 npm/yarn 内部潜在的 bug&#xff0c;并且极大了地优化了性能 2、特性概览 &#xff08;1&#x…