Kaggle系列之识别狗的品种类别(深度残差网络模型ResNet-34)

news2025/7/13 10:41:32

我们来到这个比赛页面:https://www.kaggle.com/competitions/dog-breed-identification

这个数据集的目标是Determine the breed of a dog in an image(确定图像中狗的品种)

我们先下载数据集解压之后来看下(当然不手动解压,也可以使用),这里我放在一个DOG-BREED目录的dataset里面:

D:\DOG-BREED\dataset\train:10222张训练图
D:\DOG-BREED\dataset\test:10357张测试图
D:\DOG-BREED\dataset\labels.csv:10222行的id与breed,就是图片名称与对应的类别
D:\DOG-BREED\dataset\sample_submission.csv:提交的格式,121列,除了第一列的id,其余列是120个狗的品种分别对应的识别概率,10357行。
狗的品种之多属实超出我的想象:比如有㹴犬类、金毛猎犬、苏俄牧羊犬、马尔济斯犬、蓝色快狗、美洲赤狗等等

从下载的数据集来看是跟上一篇的Kaggle系列之CIFAR-10图像分类(残差网络模型ResNet-18)

的CIFAR-10数据集类似,区别就是图片尺寸更大了,尺寸也不是固定的大小。那对于熟悉了CIFAR-10分类方法来说,这节就显得比较容易了,大部分都差不多,对比上节来说有个新的知识点,就是图片大了,网络模型大了,我们使用预训练模型来获取特征,这个可以节省时间和训练期间存储参数的梯度的空间,对于配置低的伙伴们来说是最大的帮助了。

整理数据集

下载好之后,我们同样对数据集进行一些必要的整理,在原始训练数据集中切分出验证集,参数valid_ratio表示验证集中每类狗的样本数与原始训练集中数量最少一类的狗的样本数(66)之比。同一类狗的图像分别放到各自对应的目录中,便于后面的读取。

代码如下:

import collections
import d2lzh as d2l
import os
from mxnet import autograd,gluon,init,nd
from mxnet.gluon import data as gdata,loss as gloss,nn,model_zoo
import shutil
import time
import math

def reorg_train_valid(data_dir, train_dir, input_dir, valid_ratio, idx_label):
    # 选择训练集最少一类的狗的样本数
    min_n_train_per_label = (collections.Counter(idx_label.values()).most_common()[:-2:-1][0][1])
    #验证集中每类狗的样本数
    n_valid_per_label = math.floor(min_n_train_per_label*valid_ratio)
    label_count = {}
    for train_file in os.listdir(os.path.join(data_dir, train_dir)):
        idx = train_file.split('.')[0]
        label = idx_label[idx]
        d2l.mkdir_if_not_exist([data_dir, input_dir, 'train_valid', label])
        src1 = os.path.join(data_dir, train_dir, train_file)
        dst1 = os.path.join(data_dir, input_dir, 'train_valid', label)
        shutil.copy(src1, dst1)
        if label not in label_count or label_count[label] < n_valid_per_label:
            d2l.mkdir_if_not_exist([data_dir, input_dir, 'valid', label])
            src2 = os.path.join(data_dir, train_dir, train_file)
            dst2 = os.path.join(data_dir, input_dir, 'valid', label)
            shutil.copy(src2, dst2)
            label_count[label] = label_count.get(label, 0)+1
        else:
            d2l.mkdir_if_not_exist([data_dir, input_dir, 'train', label])
            src3 = os.path.join(data_dir, train_dir, train_file)
            dst3 = os.path.join(data_dir, input_dir, 'train', label)
            shutil.copy(src3, dst3)


def reorg_dog_data(data_dir, label_file, train_dir, test_dir, input_dir, valid_ratio):
    '''
    读取训练数据的标签,以及切分验证集并整理测试集
    '''
    with open(os.path.join(data_dir, label_file), 'r') as f:
        lines = f.readlines()[1:]
        tokens = [l.rstrip().split(',') for l in lines]
        idx_label = dict(((idx, label) for idx, label in tokens))
    reorg_train_valid(data_dir, train_dir, input_dir, valid_ratio, idx_label)
    # 整理测试集
    d2l.mkdir_if_not_exist([data_dir, input_dir, 'test', 'unknown'])
    for test_file in os.listdir(os.path.join(data_dir, test_dir)):
        src = os.path.join(data_dir, test_dir, test_file)
        dst = os.path.join(data_dir, input_dir, 'test', 'unknown')
        shutil.copy(src, dst)


data_dir, label_file, train_dir, test_dir = 'dataset', 'labels.csv', 'train', 'test'
input_dir, batch_size, valid_ratio = 'train_valid_test', 128, 0.1
reorg_dog_data(data_dir, label_file, train_dir, test_dir, input_dir, valid_ratio)

执行之后,我们将会在dataset目录看到生成了一个train_valid_test目录,在其下面创建了四个目录:trainvalidtrain_validtest

然后在这些目录里面分别生成120个目录(文件夹名称就是类别),里面是对应品种的狗的图片,本人电脑的目录如下:

D:\DOG-BREED\dataset\train_valid_test\train\[affenpinscher]...\[74张]....jpg
D:\DOG-BREED\dataset\train_valid_test\valid\[affenpinscher]...\6张.jpg
D:\DOG-BREED\dataset\train_valid_test\train_valid\[affenpinscher]...\[74+6张]....jpg
D:\DOG-BREED\dataset\train_valid_test\test\unknown\10357张.jpg

collections.Counter

其中有一个collections.Counter方法,简单介绍下,也是官方源码:

c=collections.Counter('wwaabbcdeg')

得到的是一组字典,并分别统计它们各自的数量

Counter({'w': 2, 'a': 2, 'b': 2, 'c': 1, 'd': 1, 'e': 1, 'g': 1})

元组组成的列表形式

c.most_common()
#[('w', 2), ('a', 2), ('b', 2), ('c', 1), ('d', 1), ('e', 1), ('g', 1)]

所以在代码中选择最少一类的狗的样本数就是最后一个元组的第二列

c.most_common()[-2:-1][0][1]

查看元素

list(c.elements())
#['w', 'w', 'a', 'a', 'b', 'b', 'c', 'd', 'e', 'g']

排序且去重

sorted(c)
#['a', 'b', 'c', 'd', 'e', 'g', 'w']

统计数量

sum(c.values())#10

查看单个元素的统计数

c['w']#2

添加一个计数器

d=collections.Counter('wwwpla')
c.update(d)
#Counter({'w': 5, 'a': 3, 'b': 2, 'c': 1, 'd': 1, 'e': 1, 'g': 1, 'p': 1, 'l': 1})

基本用法就这些,更多的用法示例可以查看其定义。

图像增广

这次的数据集的图片比CIFAR10要大很多,所以在图片增广方面,尽量选取更多有用的图像增广操作。

transform_train = gdata.vision.transforms.Compose([
    # 随机裁剪0.08~1倍,高宽比3/4~4/3,然后缩放为高宽为224像素的图像
    gdata.vision.transforms.RandomResizedCrop(224, scale=(0.08, 1.0), ratio=(3.0/4.0, 4.0/3.0)),
    # 随机左右翻转
    gdata.vision.transforms.RandomFlipLeftRight(),
    # 随机变化亮度、对比度、饱和度
    gdata.vision.transforms.RandomColorJitter(brightness=0.4, contrast=0.4, saturation=0.4),
    # 随机加噪声
    gdata.vision.transforms.RandomLighting(0.1),
    gdata.vision.transforms.ToTensor(),
    gdata.vision.transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])

#测试时,需要确定性的图像预处理操作
transform_test = gdata.vision.transforms.Compose([
    gdata.vision.transforms.Resize(256), gdata.vision.transforms.CenterCrop(224),
    gdata.vision.transforms.ToTensor(),
    gdata.vision.transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

ToTensor()的用法

在图像增广的方法里面我们可以看到,在做图像增广操作后标准化之前,都需要做一次ToTensor(),这里有两个作用:

1、将形状从H*W*C转换成C*H*W
2、里面的值的范围[0, 255]转换成[0,1)

我们来看个示例,官方源码:

transformer = gdata.vision.transforms.ToTensor()
image = mx.nd.random.uniform(0, 255, (4, 2, 3)).astype(dtype=np.uint8)
'''
[[[144 100 236]
  [213  18  86]]

 [[ 22 165   5]
  [ 93 212 244]]

 [[198  35 221]
  [221 249 120]]

 [[203 204 117]
  [132 199 173]]]
<NDArray 4x2x3 @cpu(0)>
'''
transformer(image)
'''
[[[0.5647059  0.8352941 ]
  [0.08627451 0.3647059 ]
  [0.7764706  0.8666667 ]
  [0.79607844 0.5176471 ]]

 [[0.39215687 0.07058824]
  [0.64705884 0.83137256]
  [0.13725491 0.9764706 ]
  [0.8        0.78039217]]

 [[0.9254902  0.3372549 ]
  [0.01960784 0.95686275]
  [0.8666667  0.47058824]
  [0.45882353 0.6784314 ]]]
<NDArray 3x4x2 @cpu(0)>
'''

读取整理好的数据集

将数据集做了分类存放以及图像增广操作之后,接下来就是对数据集的读取了,同样是使用ImageFolderDataset实例来去读

train_ds = gdata.vision.ImageFolderDataset(os.path.join(data_dir, input_dir, 'train'), flag=1)
valid_ds = gdata.vision.ImageFolderDataset(os.path.join(data_dir, input_dir, 'valid'), flag=1)
train_valid_ds = gdata.vision.ImageFolderDataset(os.path.join(data_dir, input_dir, 'train_valid'), flag=1)
test_ds = gdata.vision.ImageFolderDataset(os.path.join(data_dir, input_dir, 'test'), flag=1)

train_iter = gdata.DataLoader(train_ds.transform_first(transform_train), batch_size, shuffle=True, last_batch='keep')
valid_iter = gdata.DataLoader(valid_ds.transform_first(transform_test), batch_size, shuffle=True, last_batch='keep')
train_valid_iter = gdata.DataLoader(train_valid_ds.transform_first(transform_train), batch_size, shuffle=True, last_batch='keep')
test_iter = gdata.DataLoader(test_ds.transform_first(transform_test), batch_size, shuffle=False, last_batch='keep')

定义网络模型

数据集都做了预处理之后,我们就选择一个合适的网络模型,这里用ResNet-34模型,由于比赛数据集属于预训练数据集的子集(Gluon提供了很多的预训练模型),因此我们直接复用预训练模型在输出层的输入,即抽取的特征。然后自定义一个小型的输出网络即可,这样的好处就是不需要训练模型来抽取特征了,节省了训练时间,以及省去了存储参数梯度占用的空间。

def get_net(ctx):
    # 加载模型预训练的权重
    finetune_net = model_zoo.vision.resnet34_v2(pretrained=True)
    # 定义新的输出网络
    finetune_net.output_new = nn.HybridSequential(prefix='')
    finetune_net.output_new.add(nn.Dense(256, activation='relu'))
    # 狗的品种是120
    finetune_net.output_new.add(nn.Dense(120))
    # 初始化输入网络
    finetune_net.output_new.initialize(init.Xavier(), ctx=ctx)
    # 将模型参数分配到内存或显存上
    finetune_net.collect_params().reset_ctx(ctx)
    return finetune_net

loss=gloss.SoftmaxCrossEntropyLoss()

def evaluate_loss(data_iter, net, ctx):
    l_sum, n = 0.0, 0
    for X, y in data_iter:
        y = y.as_in_context(ctx)
        output_features = net.features(X.as_in_context(ctx))
        outputs = net.output_new(output_features)
        l_sum += loss(outputs, y).sum().asscalar()
        n += y.size
    return l_sum/n

训练模型

当数据集和模型准备好了之后,就开始来训练模型,先定义一个训练函数train:

def train(net, train_iter, valid_iter, num_epochs, lr, wd, ctx, lr_period, lr_decay):
    trainer = gluon.Trainer(net.output_new.collect_params(), 'sgd', {'learning_rate': lr, 'momentum': 0.9, 'wd': wd})
    for epoch in range(num_epochs):
        train_l_sum, n, start = 0.0, 0, time.time()
        if epoch > 0 and epoch % lr_period == 0:
            trainer.set_learning_rate(trainer.learning_rate*lr_decay)
        for X, y in train_iter:
            y = y.as_in_context(ctx)
            output_features = net.features(X.as_in_context(ctx))
            with autograd.record():
                outputs = net.output_new(output_features)
                l = loss(outputs, y).sum()
            l.backward()
            trainer.step(batch_size)
            train_l_sum += l.asscalar()
            n += y.size
        time_s = "time %.2f sec" % (time.time()-start)
        if valid_iter is not None:
            valid_loss = evaluate_loss(valid_iter, net, ctx)
            epoch_s = ("epoch %d,train loss %f,valid loss %f," %
                       (epoch+1, train_l_sum/n, valid_loss))
        else:
            epoch_s = ("epoch %d,train loss %f," % (epoch+1, train_l_sum/n))
        print(epoch_s+time_s+',lr '+str(trainer.learning_rate))


ctx, num_epochs, lr, wd = d2l.try_gpu(), 1, 0.01, 1e-4
lr_period, lr_decay, net = 10, 0.1, get_net(ctx)
net.hybridize()
train(net, train_iter, valid_iter, num_epochs,lr, wd, ctx, lr_period, lr_decay)

批处理batch_size大了,很容易内存溢出:

mxnet.base.MXNetError: [12:31:44] c:\jenkins\workspace\mxnet-tag\mxnet\src\storage\./pooled_storage_manager.h:157: cudaMalloc failed: out of memory

所以需要结合自己的硬件配置来调整这个批大小,将128调小,我这里调成16先运行下是否正常

epoch 1,train loss 1.784260,valid loss 0.756940,time 104.48 sec,lr 0.01

然后我们使用全部训练数据集(含验证集)来重新训练模型,并对测试集分类,生成提交文件submission.csv,这里我将batch_size调成64,num_epochs设置成10,全部代码如下:

import collections
import d2lzh as d2l
import os
from mxnet import autograd,gluon,init,nd
from mxnet.gluon import data as gdata,loss as gloss,nn,model_zoo
import shutil
import time
import math


def reorg_train_valid(data_dir, train_dir, input_dir, valid_ratio, idx_label):
    # 选择训练集最少一类的狗的样本数
    min_n_train_per_label = (collections.Counter(idx_label.values()).most_common()[:-2:-1][0][1])
    #验证集中每类狗的样本数
    n_valid_per_label = math.floor(min_n_train_per_label*valid_ratio)
    label_count = {}
    for train_file in os.listdir(os.path.join(data_dir, train_dir)):
        idx = train_file.split('.')[0]
        label = idx_label[idx]
        d2l.mkdir_if_not_exist([data_dir, input_dir, 'train_valid', label])
        src1 = os.path.join(data_dir, train_dir, train_file)
        dst1 = os.path.join(data_dir, input_dir, 'train_valid', label)
        shutil.copy(src1, dst1)
        if label not in label_count or label_count[label] < n_valid_per_label:
            d2l.mkdir_if_not_exist([data_dir, input_dir, 'valid', label])
            src2 = os.path.join(data_dir, train_dir, train_file)
            dst2 = os.path.join(data_dir, input_dir, 'valid', label)
            shutil.copy(src2, dst2)
            label_count[label] = label_count.get(label, 0)+1
        else:
            d2l.mkdir_if_not_exist([data_dir, input_dir, 'train', label])
            src3 = os.path.join(data_dir, train_dir, train_file)
            dst3 = os.path.join(data_dir, input_dir, 'train', label)
            shutil.copy(src3, dst3)


def reorg_dog_data(data_dir, label_file, train_dir, test_dir, input_dir, valid_ratio):
    '''
    读取训练数据的标签,以及切分验证集并整理测试集
    '''
    with open(os.path.join(data_dir, label_file), 'r') as f:
        lines = f.readlines()[1:]
        tokens = [l.rstrip().split(',') for l in lines]
        idx_label = dict(((idx, label) for idx, label in tokens))
    reorg_train_valid(data_dir, train_dir, input_dir, valid_ratio, idx_label)
    # 整理测试集
    d2l.mkdir_if_not_exist([data_dir, input_dir, 'test', 'unknown'])
    for test_file in os.listdir(os.path.join(data_dir, test_dir)):
        src = os.path.join(data_dir, test_dir, test_file)
        dst = os.path.join(data_dir, input_dir, 'test', 'unknown')
        shutil.copy(src, dst)


data_dir, label_file, train_dir, test_dir = 'dataset', 'labels.csv', 'train', 'test'
input_dir, batch_size, valid_ratio = 'train_valid_test', 64, 0.1
#reorg_dog_data(data_dir, label_file, train_dir, test_dir, input_dir, valid_ratio)

# -------- 图像增广 ------------
transform_train = gdata.vision.transforms.Compose([
    # 随机裁剪0.08~1倍,高宽比3/4~4/3,然后缩放为高宽为224像素的图像
    gdata.vision.transforms.RandomResizedCrop(224, scale=(0.08, 1.0), ratio=(3.0/4.0, 4.0/3.0)),
    # 随机左右翻转
    gdata.vision.transforms.RandomFlipLeftRight(),
    # 随机变化亮度、对比度、饱和度
    gdata.vision.transforms.RandomColorJitter(brightness=0.4, contrast=0.4, saturation=0.4),
    # 随机加噪声
    gdata.vision.transforms.RandomLighting(0.1),
    gdata.vision.transforms.ToTensor(),
    gdata.vision.transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])

#测试时,需要确定性的图像预处理操作
transform_test = gdata.vision.transforms.Compose([
    gdata.vision.transforms.Resize(256), gdata.vision.transforms.CenterCrop(224),
    gdata.vision.transforms.ToTensor(),
    gdata.vision.transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])


# -----读取数据集-------
train_ds = gdata.vision.ImageFolderDataset(os.path.join(data_dir, input_dir, 'train'), flag=1)
valid_ds = gdata.vision.ImageFolderDataset(os.path.join(data_dir, input_dir, 'valid'), flag=1)
train_valid_ds = gdata.vision.ImageFolderDataset(os.path.join(data_dir, input_dir, 'train_valid'), flag=1)
test_ds = gdata.vision.ImageFolderDataset(os.path.join(data_dir, input_dir, 'test'), flag=1)

train_iter = gdata.DataLoader(train_ds.transform_first(transform_train), batch_size, shuffle=True, last_batch='keep')
valid_iter = gdata.DataLoader(valid_ds.transform_first(transform_test), batch_size, shuffle=True, last_batch='keep')
train_valid_iter = gdata.DataLoader(train_valid_ds.transform_first(transform_train), batch_size, shuffle=True, last_batch='keep')
test_iter = gdata.DataLoader(test_ds.transform_first(transform_test), batch_size, shuffle=False, last_batch='keep')


# ----定义模型-----
def get_net(ctx):
    # 加载模型预训练的权重
    finetune_net = model_zoo.vision.resnet34_v2(pretrained=True)
    # 定义新的输出网络
    finetune_net.output_new = nn.HybridSequential(prefix='')
    finetune_net.output_new.add(nn.Dense(256, activation='relu'))
    # 狗的品种是120
    finetune_net.output_new.add(nn.Dense(120))
    # 初始化输入网络
    finetune_net.output_new.initialize(init.Xavier(), ctx=ctx)
    # 将模型参数分配到内存或显存上
    finetune_net.collect_params().reset_ctx(ctx)
    return finetune_net

loss=gloss.SoftmaxCrossEntropyLoss()

def evaluate_loss(data_iter, net, ctx):
    l_sum, n = 0.0, 0
    for X, y in data_iter:
        y = y.as_in_context(ctx)
        output_features = net.features(X.as_in_context(ctx))
        outputs = net.output_new(output_features)
        l_sum += loss(outputs, y).sum().asscalar()
        n += y.size
    return l_sum/n


def train(net, train_iter, valid_iter, num_epochs, lr, wd, ctx, lr_period, lr_decay):
    trainer = gluon.Trainer(net.output_new.collect_params(), 'sgd', {'learning_rate': lr, 'momentum': 0.9, 'wd': wd})
    for epoch in range(num_epochs):
        train_l_sum, n, start = 0.0, 0, time.time()
        if epoch > 0 and epoch % lr_period == 0:
            trainer.set_learning_rate(trainer.learning_rate*lr_decay)
        for X, y in train_iter:
            y = y.as_in_context(ctx)
            output_features = net.features(X.as_in_context(ctx))
            with autograd.record():
                outputs = net.output_new(output_features)
                l = loss(outputs, y).sum()
            l.backward()
            trainer.step(batch_size)
            train_l_sum += l.asscalar()
            n += y.size
        time_s = "time %.2f sec" % (time.time()-start)
        if valid_iter is not None:
            valid_loss = evaluate_loss(valid_iter, net, ctx)
            epoch_s = ("epoch %d,train loss %f,valid loss %f," %
                       (epoch+1, train_l_sum/n, valid_loss))
        else:
            epoch_s = ("epoch %d,train loss %f," % (epoch+1, train_l_sum/n))
        print(epoch_s+time_s+',lr '+str(trainer.learning_rate))


ctx, num_epochs, lr, wd = d2l.try_gpu(), 1, 0.01, 1e-4
lr_period, lr_decay, net = 10, 0.1, get_net(ctx)
net.hybridize()
#train(net, train_iter, valid_iter, num_epochs,lr, wd, ctx, lr_period, lr_decay)

num_epochs=10
train(net, train_valid_iter, None, num_epochs,lr, wd, ctx, lr_period, lr_decay)
preds = []
for data, label in test_iter:
    output_features = net.features(data.as_in_context(ctx))
    output = nd.softmax(net.output_new(output_features))
    preds.extend(output.asnumpy())
ids = sorted(os.listdir(os.path.join(data_dir, input_dir, 'test/unknown')))
with open('submission.csv', 'w') as f:
    f.write('id,'+",".join(train_valid_ds.synsets)+'\n')
    for i, output in zip(ids, preds):
        f.write(i.split('.')[0]+','+','.join([str(num) for num in output])+'\n')


'''
epoch 1,train loss 2.346387,time 105.90 sec,lr 0.01
epoch 2,train loss 1.054525,time 98.97 sec,lr 0.01
epoch 3,train loss 0.936225,time 100.72 sec,lr 0.01
epoch 4,train loss 0.882884,time 100.87 sec,lr 0.01
epoch 5,train loss 0.829612,time 98.21 sec,lr 0.01
epoch 6,train loss 0.820044,time 98.81 sec,lr 0.01
epoch 7,train loss 0.820517,time 101.82 sec,lr 0.01
epoch 8,train loss 0.789499,time 100.52 sec,lr 0.01
epoch 9,train loss 0.780991,time 98.92 sec,lr 0.01
epoch 10,train loss 0.742645,time 99.46 sec,lr 0.01
'''

将提交文件提交到Kaggle看下结果如何:

这个结果跟批处理大小和迭代次数有关,有兴趣的伙伴们可以调大点试试,当然还可以修改残差网络模型,加深层数看下效果会怎么样。

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

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

相关文章

超全 Vue3新特性总结

Vue3 应用-技术分享与交流 新特性篇 Vue3 组合式 API VS Vue2 选项式 API 选项式 API 面临的问题: 我们在处理业务逻辑时&#xff0c;需要在 data computed method watch 中分别进行代码编写&#xff0c;碎片化使得理解和维护复杂组件变得困难。选项的分离掩盖了潜在的逻辑问…

百度工程师浅谈分布式日志

作者 | 文库基础架构 导读 我们做软件开发时&#xff0c;或多或少的会记录日志。由于日志不是系统的核心功能&#xff0c;常常被忽视&#xff0c;定位问题的时候才想起它。本文由浅入深的探讨不起眼的日志是否重要&#xff0c;以及分布式架构下的日志运维工具应该具备哪些能力&…

【单目标优化算法】海鸥优化算法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

如何使用ODX描述诊断会话和安全等级

ODX 2.2是由ASAM&#xff08;自动化及测量系统标准协会&#xff09;提出的诊断标准&#xff0c;是一种基于XML语言的开放式诊断数据格式&#xff0c;已在国际上得到广泛使用。目前ODX诊断标准也已被国内各大OEM采用&#xff0c;但在ODX数据开发阶段&#xff0c;ODX诊断数据库的…

1.1 数据库简介

文章目录1.什么是数据库2.数据库分类3.关系型数据库和非关系型数据库4.关系型数据库4.1 Mysql数据库4.2 MySQL数据的存放1.什么是数据库 我们可以简单将数据库理解为一个存储数据&#xff0c;管理数据的仓库&#xff1b; 仓库中有许多的货架&#xff08;数据表&#xff09;&a…

JSP 字库销售管理系统myeclipse定制开发sqlserver数据库网页模式java编程jdbc

一、源码特点 JSP 字库销售管理系统是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为SQLServer2008&#x…

【RecBole-GNN/源码】RecBole-GNN中NCL源码解析

如果觉得我的分享有一定帮助&#xff0c;欢迎关注我的微信公众号 “码农的科研笔记”&#xff0c;了解更多我的算法和代码学习总结记录。或者点击链接扫码关注【RecBole-GNN/源码】RecBole-GNN中NCL源码解析 【RecBole-GNN/源码】RecBole-GNN中NCL源码解析 原文&#xff1a;ht…

【教程】GitStats代码统计工具(附GitLab API相关)

使用GitStats进行代码统计 官方文档&#xff1a;GitStats - git history statistics generator GitStats是基于Git的数据统计生成器&#xff0c;输出格式为HTML&#xff0c;可直接在浏览器打开查看&#xff0c;展现为图表形式的可视化数据&#xff0c;内容包括&#xff1a; 常…

Spring Boot MyBatis-Plus 连接 Oracle 数据库 自动生成代码

IDEA 创建SpringBoot项目 项目创建移步 IDEA创建SpringBoot项目 添加依赖 <!--MyBatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</vers…

归因分析笔记21 可解释的机器学习-李宏毅讲座

视频链接: https://www.bilibili.com/video/BV1Wv411h7kN/?p96&vd_source7259e29498a413d91ab48c04f9329855 课件链接: https://view.officeapps.live.com/op/view.aspx?srchttps%3A%2F%2Fspeech.ee.ntu.edu.tw%2F~hylee%2Fml%2Fml2021-course-data%2Fxai_v4.pptx&…

【数据结构与算法】数据结构的基本概念,时间复杂度

&#x1f349;内容专栏&#xff1a;【数据结构与算法】 &#x1f349;本文脉络&#xff1a;数据结构和算法的基本概念&#xff0c;时间复杂度 &#x1f349;本文作者&#xff1a;Melon西西 &#x1f349;发布时间 &#xff1a;2023.2.21 目录 一、引入&#xff1a; 二、数据结…

一键恢复和重装系统的区别是什么

如果电脑出现系统故障问题的时候&#xff0c;我们的电脑系统还原和系统重装都是很好的解决方法之一&#xff0c;不过是二者之间是有区别的。那么我们的电脑系统还原和系统重装有什么区别呢?现在就跟大家聊聊电脑一键恢复和重装系统的区别有哪些。 工具/原料&#xff1a; 系统…

P6软件应用的核心收益

卷首语 提供了多用户、多项目的功能模块&#xff0c;支持多层次项目等级划分&#xff0c;资源分配计划&#xff0c;记录实际数据&#xff0c;自定义视图&#xff0c;并具有用户定义字段的扩展功能。 利用最佳实践&#xff0c;建立企业模板库 P6软件支持用户使用模板编制项目…

Arduino-交通灯

LED交通灯实验实验器件&#xff1a;■ 红色LED灯&#xff1a;1 个■ 黄色LED灯&#xff1a;1 个■ 绿色LED灯&#xff1a;1 个■ 220欧电阻&#xff1a;3 个■ 面包板&#xff1a;1 个■ 多彩杜邦线&#xff1a;若干实验连线1.将3个发光二极管插入面包板&#xff0c;2.用杜邦线…

Sqoop介绍_以及安装_测试---大数据之Apache Sqoop工作笔记001

这个sqoop主要是用来,把数据从mysql中导入到hdoop中,去看看介绍吧. sql to hadoop 然后我们来看看sqoop,可以看到这里稳定版本是1.4.7 然后1.4.7 跟centos6.8 不是太好配置 这里用了1.4.6 但是如果用1.4.7 和centos7 还行 可以看看官网,这里sqoop1 跟sqoop2 这里标注了s…

【论文笔记】Manhattan-SDF == ZJU == CVPR‘2022 Oral

Neural 3D Scene Reconstruction with the Manhattan-world Assumption 本文工作&#xff1a;基于曼哈顿世界假设&#xff0c;重建室内场景三维模型。 1.1 曼哈顿世界假设 参考阅读文献&#xff1a;Structure-SLAM: Low-Drift Monocular SLAM in Indoor EnvironmentsIEEE IR…

【原创】java+swing+mysql宿舍管理系统设计与实现

今天我们主要来介绍如何使用swing图形化gui工具和mysql数据库去开发一个学生宿舍管理系统&#xff0c;这样一个比较经典的项目&#xff0c;学生宿舍管理系统&#xff0c;相信都很多人都不同程度的写过&#xff0c;从实现上来说不难。 功能分析&#xff1a; 学生宿舍管理系统&…

mysql中利用sql语句修改字段名称,字段长度等操作(亲测)

在网站重构中&#xff0c;通常会进行数据结构的修改&#xff0c;所以添加&#xff0c;删除&#xff0c;增加mysql表的字段是难免的&#xff0c;有时为了方便&#xff0c;还会增加修改表或字段的注释&#xff0c;把同字段属性调整到一块儿。这些操作可以在phpmyadmin或者别的mys…

Lazada选品推荐,这些爆品成了东南亚开年大赢家

小编今日整理了最新快消行业情报&#xff0c;带您解读东南亚市场玩具、母婴、美妆、食品、宠物类目的最新热销品类和发展方向&#xff0c;宠物。赶在大促前为商家朋友们助力一波&#xff01;STEM玩具、精细化拟人化宠物食品、便携香水……一大波商机正在赶来&#xff01;准备好…

编译链接实战(9)elf符号表

文章目录符号的概念符号表探索前面介绍了elf文件的两种视图&#xff0c;以及两种视图的各自几个组成部分&#xff1a;elf文件有两种视图&#xff0c;链接视图和执行视图。在链接视图里&#xff0c;elf文件被划分成了elf 头、节头表、若干的节&#xff08;section&#xff09;&a…