java-pytorch 使用手动下载FashionMNIST数据集进行测试

java-pytorch 使用手动下载FashionMNIST数据集进行测试

    • 先定义训练数据和测试数据的位置
    • 查看一下读取到的标签数据格式
    • 使用loc和iloc访问下数据,便于下面操作
    • 使用read_image函数查看下图片的数据大小
    • 开始写数据集
    • 使用DataLoader去加载我们自己的数据
      • 看下加载后的dataloader数据形状
      • 循环查看下dataloader每个数据的信息
    • 写一个简单的模型,由Linear组成
    • 定义损失函数和优化器
    • 编写测试和训练方法
    • 开始训练
    • 保存模型
    • 加载模型
    • 使用加载的模型进行预测
      • 图片处理
    • 预测
    • 其他
      • 图片灰度处理转tensor
      • 测试某一张图片

  1. 手动下载FashionMNIST数据集,通过https://blog.csdn.net/m0_60688978/article/details/137085740转换为实际的图片和标注
  2. 目的是为了模拟实际业务中,我们往往需要自己采集图片数据和打标签的过程
  3. 因为FashionMNIST数据集图片是28x28,和对应的一个图片和类型的记录文件output.txt

先定义训练数据和测试数据的位置

annotations_file="../data/imageandlableTrain/output.txt"
img_dire="../data/imageandlableTrain"

test_img_dire="../data/imageandlableTest"
test_annotations_file="../data/imageandlableTest/output.txt"

查看一下读取到的标签数据格式

import pandas as pd

lables=pd.read_csv(annotations_file,header=None)
lables.head(10)
01
0Ankleboot1.jpg9
1T-shirttop2.jpg0
2T-shirttop3.jpg0
3Dress4.jpg3
4T-shirttop5.jpg0
5Pullover6.jpg2
6Sneaker7.jpg7
7Pullover8.jpg2
8Sandal9.jpg5
9Sandal10.jpg5

使用loc和iloc访问下数据,便于下面操作

imageName,lable=lables.loc[3,:]
imageName,lable
('Dress4.jpg', 3)
lables.iloc[2,1]
0

使用read_image函数查看下图片的数据大小

from torchvision.io import read_image
image1=read_image("../data/imageandlableTrain/T-shirttop2.jpg")
type(image1),image1.size(),image1[0].size(),image1
(torch.Tensor,
 torch.Size([3, 28, 28]),
 torch.Size([28, 28]),
 tensor([[[ 0,  0,  1,  ...,  1,  8,  0],
          [13,  0,  0,  ..., 10,  0,  0],
          [ 0,  0, 22,  ..., 10,  0,  1],
          ...,
          [ 0,  0,  0,  ...,  0,  0,  0],
          [ 0,  0,  0,  ...,  0,  0,  0],
          [ 0,  0,  0,  ...,  0,  0,  0]],
 
         [[ 0,  0,  1,  ...,  1,  8,  0],
          [13,  0,  0,  ..., 10,  0,  0],
          [ 0,  0, 22,  ..., 10,  0,  1],
          ...,
          [ 0,  0,  0,  ...,  0,  0,  0],
          [ 0,  0,  0,  ...,  0,  0,  0],
          [ 0,  0,  0,  ...,  0,  0,  0]],
 
         [[ 0,  0,  1,  ...,  1,  8,  0],
          [13,  0,  0,  ..., 10,  0,  0],
          [ 0,  0, 22,  ..., 10,  0,  1],
          ...,
          [ 0,  0,  0,  ...,  0,  0,  0],
          [ 0,  0,  0,  ...,  0,  0,  0],
          [ 0,  0,  0,  ...,  0,  0,  0]]], dtype=torch.uint8))

开始写数据集

思路很简单,初始化的时候,将output.txt的数据读出来,然后在__getitem__返回单一图片的tensor数据和标签

这里需要注意的是:read_image的结果数据size是torch.Size([3, 28, 28]),而模型需要的[28,28],因此要返回image[0]

from torchvision.io import read_image
from torch.utils.data import Dataset

class CustomImageDataset(Dataset):
    def __init__(self):
#         获得所有的lables
        self.labels=pd.read_csv(annotations_file,header=None)
        self.imageDir=img_dire
        
    def __len__(self):
        return len(self.labels)
    
    def __getitem__(self, idx):
        imageName,lable=self.labels.loc[idx,:]
        image=read_image("{}/{}".format(img_dire,imageName))
        image=image[0]
        return image,lable
 
class CustomImageDatasetTest(Dataset):
    def __init__(self):
    #         获得所有的lables
        self.labels=pd.read_csv(test_annotations_file,header=None)
        self.imageDir=img_dire

    def __len__(self):
        return len(self.labels)

    def __getitem__(self, idx):
        imageName,lable=self.labels.loc[idx,:]
        image=read_image("{}/{}".format(test_img_dire,imageName))
        image=image[0]
        return image,lable

使用DataLoader去加载我们自己的数据

from torch.utils.data import DataLoader
train_dataloader = DataLoader(CustomImageDataset(), batch_size=2)
len(train_dataloader)
30000
test_dataloader = DataLoader(CustomImageDatasetTest(), batch_size=2)
len(test_dataloader)
5000

看下加载后的dataloader数据形状

for X, y in train_dataloader:
    print(f"Shape of X [N, C, H, W]: {X.shape}")
    print(f"Shape of y: {y.shape} {y.dtype}")
    break
Shape of X [N, C, H, W]: torch.Size([2, 28, 28])
Shape of y: torch.Size([2]) torch.int64

循环查看下dataloader每个数据的信息

for batch, (X, y) in enumerate(train_dataloader):
    print(X,batch,X.size(),y,type(y))
    if batch==2:
        break
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

Cell In[35], line 1
----> 1 for batch, (X, y) in enumerate(train_dataloader):
      2     print(X,batch,X.size(),y,type(y))
      3     if batch==2:


NameError: name 'train_dataloader' is not defined

写一个简单的模型,由Linear组成

import os
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),
            nn.ReLU(),
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10),
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits
model = NeuralNetwork().to("cpu")
print(model)
NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear_relu_stack): Sequential(
    (0): Linear(in_features=784, out_features=512, bias=True)
    (1): ReLU()
    (2): Linear(in_features=512, out_features=512, bias=True)
    (3): ReLU()
    (4): Linear(in_features=512, out_features=10, bias=True)
  )
)

定义损失函数和优化器

这里重点关注学利率,太低会爆

loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)

编写测试和训练方法

测试方法思路也很简单,就是在测试数据中逐一把数据传入到模型中,累计损失和正确率

这里要注意的是正确率的统计,就是预测正确的?累加(pred.argmax(1) == y).type(torch.float).sum().item()



训练思路:固定套路,直接copy

# 测试方法
def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in dataloader:
#             X, y = X.to(device), y.to(device)
            pred = model(X.float().unsqueeze(1))
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
def train():
    for batch,(onedatas,lable) in enumerate(train_dataloader):

        model.train()
        pred=model(onedatas.float().unsqueeze(1))

        loss=loss_fn(pred,lable)
        lossitem=loss.item()

        # Backpropagation
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        if batch % 100:
            print(f"loss {lossitem},batch is {batch}")
        

开始训练

思路就是套路照搬即可

#  训练
for t in range(10):
    print(f"Epoch {t+1}\n-------------------------------")
    train()
    test(test_dataloader, model, loss_fn)
print("Done!")

保存模型

# save model
torch.save(model.state_dict(),"model.pth")
print("Saved Model State to model.pth")
Saved Model State to model.pth
print(model)
NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear_relu_stack): Sequential(
    (0): Linear(in_features=784, out_features=512, bias=True)
    (1): ReLU()
    (2): Linear(in_features=512, out_features=512, bias=True)
    (3): ReLU()
    (4): Linear(in_features=512, out_features=10, bias=True)
  )
)

加载模型

model = NeuralNetwork().to("cpu")
model.load_state_dict(torch.load("model.pth"))
<All keys matched successfully>

使用加载的模型进行预测

图片处理

  1. 要求灰度 2. 要求28*28 3. 数据是tensor
from PIL import Image
 
# 打开原始图片
image = Image.open('lianxie.jpg')
 
# 调整图片大小
new_size = (28,28) # 新的宽高像素值
resized_image = image.resize(new_size)
 
# 转换成灰度图像
grayscaled_image = resized_image.convert("L")
grayscaled_image

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

transform_d = transforms.Compose([
    transforms.ToTensor()
])
image_t = transform_d(grayscaled_image)
plt.imshow(image_t[0])
<matplotlib.image.AxesImage at 0x1fabef58520>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测

可以看到output的最大值下表是5,即是预测结果,预实际相符

output=model(image_t)
output
tensor([[ 0.1207, -0.4304,  0.2356,  0.2038,  0.2823, -0.2736,  0.4910, -0.0614,
         -0.1314, -0.4034]], grad_fn=<AddmmBackward0>)

其他

图片灰度处理转tensor

import torch
import torchvision.transforms as transforms
from PIL import Image
 
# 定义转换管道
grayscale_transform = transforms.Grayscale(num_output_channels=1)  # 灰度转换
tensor_transform = transforms.ToTensor()  # Tensor转换
resized_transform=transforms.Resize((28,28))

# 读取图片
image = Image.open("lianxie.jpg")
 
# 应用转换
gray_image = grayscale_transform(image)

resized_gray_tensor = resized_transform(gray_image)
gray_tensor = tensor_transform(resized_gray_tensor)

gray_tensor,gray_tensor.size()
output=model(gray_tensor)
output
tensor([[ 0.1208, -0.4305,  0.2355,  0.2039,  0.2823, -0.2737,  0.4913, -0.0619,
         -0.1308, -0.4036]], grad_fn=<AddmmBackward0>)

测试某一张图片

# 排查

# Sandal13.jpg,5
# Sandal14.jpg,5

image=read_image("{}/Sandal13.jpg".format(img_dire))

imageData=image[0].unsqueeze(0)
print("unsqueeze: ",imageData)
print("unsqueeze after size : ",imageData.size())

print("original size: ",image.size())

output=model(imageData.float())

print("output content is ",output)

# argmax取值最大的下标
print(output.argmax(1))
# 结论
# 减少学习率即可
unsqueeze:  tensor([[[  0,   0,   0,   0,   0,   0,   0,   0,   1,   1,   0,   0,   3,   8,
            5,   0,   0,   0,   0,   0,   5,   0,   0,   3,   0,   4,   0,   0],
         [  0,   0,   0,   0,   0,   0,   0,   0,   2,   1,   0,   0,   0,   0,
            0,   0,   3,   5,   1,   1,   6,   1,   0,   0,   4,   0,   0,   4],
         [  0,   0,   0,   0,   0,   0,   0,   0,   3,   0,   0,   6,  12,   6,
            1,   3,   0,   1,   0,   0,   0,   1,   1,   0,   0,   0,   0,   4],
         [  0,   0,   0,   0,   0,   0,   0,   0,   7,   1,   0,   1,   1,   0,
            0,   0,   0,   0,   2,   0,   0,   0,   5,   3,   0,   2,   8,   0],
         [  0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   7,   0,   0,   0,
            5,  11,   2,   0,   6,   9,   0,   0,   3,   0,   7,   6,   5,   0],
         [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   3,   5,   5,
            0,   0,   7,   0,   0,   9,   2,   0,   4,   0,   0,   0,   0,   0],
         [  0,   0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   1,   0,   0,
            3,  29,  62,   3,   0,   3,   0,   0,   6,   0,   0,  20,   9,   0],
         [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   9,   0,   0,
           96, 209, 143,  51,   1,   3,   0,   0,   6,   0,   2,  76,  57,   0],
         [  6,   0,   5,   7,   4,   0,   0,   7,   4,   0,   0,  11,  19, 167,
          218, 176, 197, 184,   0,   5,   0,  11, 121, 134, 152, 117,  75,   0],
         [  0,   0,   0,   0,   6,   0,   4,   0,   0,   0,   0,   7,  56, 219,
          168, 160, 204, 246,  95,  31, 105, 175, 199, 115,  18,   0,   5,   0],
         [  0,   7,   2,   8,  18,   0,   2,   8,   0,   5,   2,   0,   1, 182,
          245, 152, 158, 185, 235, 200, 175,  78,   8,  17,  23,   2,  13,   0],
         [  0,  15,   0,   0,   0,  16,   5,   0,   4,   0,  21,  14,  11,  48,
          230, 251, 240, 185, 221,  71,   0,  10,   0,   0,   0,   0,  12,   0],
         [  3,   0,   0,  31,   0,   0,  25, 120, 194,   0,   0,   0,   0,  19,
          171, 225, 230, 205, 222, 150,   8,   0,   1,  37,  42,  43,  61,  38],
         [  4,   7,   0,   0,   2, 140, 194, 186, 201, 165,  13,   0,  11,   0,
            0,  89, 135, 208, 180, 241, 178, 124, 132, 135, 161, 141, 143, 113],
         [  0,   3,   0,   0,   2, 107, 235, 196, 167, 219,  18,   8,  11,   0,
            6,  49, 203, 221, 137, 170, 112,  65,  59,  75,  52,  55,  80,  59],
         [  9,  13,   3,   2,   0,  11, 184, 127,   5, 197, 111,   0,  14,  97,
          109, 127, 148, 100,  89,  93,  64, 126, 106, 115,  87, 105, 115,  53],
         [ 40, 109, 121, 120, 106,  91, 198, 207, 121, 187, 255, 127, 126,  96,
          110,  71,  60,  93,  73,  74,  74,  73,  93,  60,  85,  82,  99,  40],
         [ 41,  72,  36,  56,  64,  78,  99,  69,  92,  92, 109,  51,  76,  75,
           84,  79, 104, 102,  74,  94,  94,  76, 105, 107,  60,  63,  87,  22],
         [ 21,  95,  88, 115,  84, 105,  82,  83,  61,  64,  79,  88,  94,  89,
           72,  88,  98,  92,  75, 103, 102,  72,  87,  92, 103,  99, 105,  14],
         [ 17,  84,  79,  90,  66, 104,  73,  97,  75,  95,  96,  91,  75,  78,
           74,  94,  59,  75,  70,  80,  81,  74,  81,  66,  47,  54,  70,   0],
         [  0,  78, 122, 127, 108, 109,  70,  90,  93, 102,  94,  85, 103, 115,
          128, 129, 132, 146, 136, 126, 133, 154, 173, 164, 180, 153, 110,   9],
         [  0,   4,   6,  21,  70, 108, 103, 108, 105, 103,  95,  86,  98,  61,
           54,  37,  13,   7,   0,   0,   0,   8,  23,  31,  17,  21,  15,   0],
         [  0,   6,   2,   2,   0,   0,   0,   5,   0,   8,   0,   0,   5,   0,
            0,   0,  10,   0,   1,   3,   2,   0,   0,   4,   0,   9,   0,   0],
         [  0,   1,   0,  16,   0,   0,   3,   1,   0,  15,   0,   0,   2,   3,
           10,   0,   0,   0,   3,   0,   0,   3,   0,   0,   0,  10,   0,   9],
         [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
            0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
         [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
            0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
         [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
            0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0],
         [  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
            0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0]]],
       dtype=torch.uint8)
unsqueeze after size :  torch.Size([1, 28, 28])
original size:  torch.Size([3, 28, 28])
output content is  tensor([[-6.7115,  1.3163, -7.2377, -1.6586,  2.7382,  3.2748, -6.3696, -0.6497,
         -7.3979, -1.4042]], grad_fn=<AddmmBackward0>)
tensor([5])

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

游戏陀螺首条报道(一)|看完GDC 2024,我找到了网易数智引领游戏AI技术的关键!

经过近几年的爆发式增长&#xff0c;AI技术在游戏行业的应用取得了显著的进步。从去年多为“AI生成文字、图片、代码”等工具型应用&#xff0c;发展到了如今可以深入至游戏研发、运营的各个环节&#xff0c;这也让今年的游戏开发者大会&#xff08;GDC&#xff09;显得格外的热…

面试官:你是如何解决跨域的?

在近期的面试中&#xff0c;面试官针对我的项目&#xff0c;问到了 如何解决跨域&#xff1f; 没答好&#xff0c;我想通过这篇文章&#xff0c;巩固一下这方面的知识&#xff0c;分享一下我对于这个问题的理解&#xff0c;希望也能对大家有所帮助。 我的回答 跨域我们需要从浏…

javaWeb项目-火车票订票信息系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、Spring Boot框架 …

IP/TCP--解决为什么电脑连上了有线网就不能再连WIFI【转载】

文章目录 第一种情况&#xff1a;WIFI与有线网在同一网段下1、查看路由信息2、调整跃点数 第二种情况&#xff1a;WIFI与有线网不在同一网段下跃点数概念路由器设置入口 【注意适用情型&#xff1a;需要同时用到内网&#xff08;不能上公网的内部网络&#xff09;和互联网。】 …

Spring Cloud+Spring Alibaba笔记

Spring CloudSpring Alibaba 文章目录 Spring CloudSpring AlibabaNacos服务发现配置中心 OpenFeign超时机制开启httpclient5重试机制开启日志 SeataSentinel流量控制熔断降级热点控制规则持久化集成 OpenFeign集成 Gateway MicrometerZipKinGateway路由断言过滤器 Nacos 服务…

什么是广告可见性测量 如何测量广告可见性

广告可见性测量 & 如何测量广告可见性 --- 一起来来认识MOAT 现在是2024年&#xff0c;大家或许还记得大约8年前广告可见性&#xff08;Ad viewability&#xff09;成为数字媒体世界的一种货币以来&#xff0c;出版商一直处于不利地位。当广告商用不同的工具和技术武装自…

在微信上处理小程序用户反馈具体的方法

想必大家在开发小程序的时候&#xff0c;一定遇到这种情况&#xff1a; 为了用户有更好的体验&#xff0c;我们会定期登陆微信小程序来查看用户反馈并对用户的问题进行回复和处理&#xff0c;但是这种方法的缺点就是最多间隔48小时要进行登陆一次以及回复用户不及时。 这样的话…

2月运动鞋行业线上电商数据分析:国产品牌高歌猛进,占据热榜90%

随着天气回暖&#xff0c;踏青出行的人越来越多&#xff0c;运动鞋市场呈现出繁荣状态&#xff0c;尤其是国产品牌。 根据鲸参谋数据显示&#xff0c;2024年2月在京东平台的运动鞋销量表现强劲&#xff0c;累计约233万件&#xff0c;同比上个月涨幅了58%&#xff1b;销售额累计…

泛型的通配符及擦除机制详解

目录 一、通配符解决什么问题 二、通配符上界 三、通配符下界 ​编辑 四、泛型类的擦除机制 引言&#xff1a; 在这篇文章中&#xff0c;我主要介绍前一篇泛型没介绍完整的泛型通配符和泛型的擦除机制Java中泛型的详细介绍 ? 用于在泛型的使用&#xff0c;即为通配符 一、通…

Qt+OpenGL入门教程(二)——OpenGL渲染管线

渲染管线是图形学不可或缺的&#xff0c;在学习它之前&#xff0c;我们先了解一下什么是管线&#xff1f; 管线/流水线 当我们谈到管线时&#xff0c;我们指的是一个由多个阶段组成的过程&#xff0c;每个阶段都完成任务的一部分。在现实世界中&#xff0c;流水线的概念在许多…

小白了解Pinia第2集 · 三大核心状态Getters、Actions以及Plugins 插件

三大核心状态 state 第1集有详细讲解&#xff1a;https://blog.csdn.net/qq_51463650/article/details/137137080?spm1001.2014.3001.5501 getters Getter 完全等同于 Store 状态的 计算值。 它们可以用 defineStore() 中的 getters 属性定义。 他们接收“状态”作为第一个…

C++从入门到精通——缺省参数

缺省参数 前言一、缺省参数概念二、缺省参数分类位置参数的缺省参数全缺省参数半缺省参数 关键字参数的缺省参数函数指针的缺省参数lambda表达式 三、缺省参数的具体代码展示main.cpp 前言 缺省参数是在函数定义时指定的默认值&#xff0c;当调用函数时未提供该参数的值时&…

统信 UOS V20 一键安装 Oracle 12CR2(220118)单机版

Oracle 一键安装脚本&#xff0c;演示 统信 UOS V20 一键安装 Oracle 12CR2&#xff08;220118&#xff09;单机版过程&#xff08;全程无需人工干预&#xff09;&#xff1a;&#xff08;脚本包括 ORALCE PSU/OJVM 等补丁自动安装&#xff09; ⭐️ 脚本下载地址&#xff1a;…

云主机8核16G配置租用优惠价格1198元1年、4688元三年

京东云8核16G租用优惠价格1198元1年、4688元三年&#xff0c;配置为8C16G-270G SSD系统盘-5M带宽-500G月流量&#xff0c;华北-北京地域。京东云8核16G服务器活动页面 atengyun.com/go/jd 京东云8核16G租用优惠价格 京东云&#xff1a;轻量云主机CPU内存&#xff1a;8C16G公网带…

AIGC重塑金融 | 大模型在金融行业的应用场景和落地路径

作者&#xff1a;林建明 来源&#xff1a;IT阅读排行榜 本文摘编自《AIGC重塑金融&#xff1a;AI大模型驱动的金融变革与实践》&#xff0c;机械工业出版社出版 目录 01 大模型在金融领域的 5 个典型应用场景 02 大模型在金融领域应用所面临的风险及其防范 03 AIGC 技术的科…

职场沟通教训 程序汪改了一行代码,导致测试和开发大战

本文章有视频的&#xff0c;请到B站 我是程序汪 观看 程序汪改了一行代码&#xff0c;导致测试和开发大战&#xff0c;职场沟通教训 程序汪改了一行代码&#xff0c;导致测试和开发大战 鸡汤文 每个人都会在沟通上出问题 工作上沟通出问题可能让你郁闷一天、丢了客户、损失金…

解决Nginx请求转发将POST变为GET的问题

先说问题 我配置了Nginx代理&#xff0c;目的是将请求转发到指定的后端&#xff0c;对于普通的JSON数据&#xff0c;没有什么问题。 但是有文件上传的就不一样了&#xff0c;我需要指定到第3方的地址。然而常规的配置完成后,Nginx实际的转发动作改变了我的请求方式 location …

鸿蒙开发人才紧缺!这份《HarmonyOS教学视频》帮你更快上手鸿蒙

去年9月&#xff0c;华为宣布鸿蒙原生应用全面启动&#xff0c;基于开源鸿蒙开发的 HarmonyOS NEXT 鸿蒙星河版将在今年秋天正式和消费者见面。该版本系统底座将由华为全线自研&#xff0c;去掉传统安卓 AOSP 代码。 这意味着&#xff0c;鸿蒙星河版将不再兼容安卓应用&#xf…

系统分析师-参考模型

前言 网络术语中的参考模型指的是OSI参考模型&#xff0c;由ISO&#xff08;国际标准化组织&#xff09;制定的一套普遍适用的规范集合&#xff0c;以使得全球范围的计算机平台可进行开放式通信。 ISO创建了一个有助于开发和理解计算机的通信模型&#xff0c;即开放系统互联OS…

SQL复习专题

请结合B站-技术蛋老师 视频学习 核心语法 一、增&#xff1a;数据库/表格 create create database 数据库名&#xff1b;#创建表&#xff08;列名类型&#xff09; mysql> create table eggs_record(-> id int,-> egg_name varchar(10),-> sold date-> ); 这…