昇思25天學習打卡營第19天 | ResNet50遷移學習再續

訓練模型部分代碼解析

構建Resnet50網絡

兩行初始化代碼

weight_init = Normal(mean=0, sigma=0.02)

這行代碼定義了一個初始化器weight_init,它將使用均值為0,標準差為0.02的正態分布來初始化網絡中的權重。這種初始化策略有助于在網絡的初始階段避免梯度消失或爆炸的問題,因為權重被初始化為接近于0但又不至于太小的值。

gamma_init = Normal(mean=1, sigma=0.02)

這行代碼定義了一個初始化器gamma_init,通常用于初始化批量歸一化(Batch Normalization)層中的尺度參數(gamma)。批量歸一化是一種常用的技術,用于加速神經網絡的訓練過程,并通過提高穩定性來改善性能。在這種情況下,gamma參數的初始化通常設置為接近1的值,因為它們在批量歸一化層中起到縮放的作用,初始化為1意味著在初始階段不會改變激活的尺度。

class ResidualBlockBase(nn.Cell):expansion: int = 1  # 最后一個卷積核數量與第一個卷積核數量相等def __init__(self, in_channel: int, out_channel: int,stride: int = 1, norm: Optional[nn.Cell] = None,down_sample: Optional[nn.Cell] = None) -> None:super(ResidualBlockBase, self).__init__()if not norm:self.norm = nn.BatchNorm2d(out_channel)else:self.norm = normself.conv1 = nn.Conv2d(in_channel, out_channel,kernel_size=3, stride=stride,weight_init=weight_init)self.conv2 = nn.Conv2d(in_channel, out_channel,kernel_size=3, weight_init=weight_init)self.relu = nn.ReLU()self.down_sample = down_sampledef construct(self, x):"""ResidualBlockBase construct."""identity = x  # shortcuts分支out = self.conv1(x)  # 主分支第一層:3*3卷積層out = self.norm(out)out = self.relu(out)out = self.conv2(out)  # 主分支第二層:3*3卷積層out = self.norm(out)if self.down_sample is not None:identity = self.down_sample(x)out += identity  # 輸出為主分支與shortcuts之和out = self.relu(out)return out

這段代碼定義了一個名為ResidualBlockBase的類,它是一個殘差塊(Residual Block)的基礎實現。殘差塊是殘差網絡的基本構建塊,它允許網絡在增加層數的同時,仍然能夠通過反向傳播有效地訓練。

函數解析:

  1. __init__:
    • 作用:這是一個構造函數,用于初始化殘差塊。它定義了殘差塊的基本結構和操作,包括卷積層、批量歸一化層和ReLU激活函數。
    • 參數:
      • in_channel:輸入通道數。
      • out_channel:輸出通道數。
      • stride:卷積層的步幅。
      • norm:可選的規范化層,默認為None,此時會使用批量歸一化。
      • down_sample:可選的下采樣層,用于匹配輸入和輸出的維度,默認為None
    • 代碼邏輯:
      • 調用父類的構造函數:super(ResidualBlockBase, self).__init__()
      • 判斷是否提供了自定義的規范化層,如果沒有,則使用批量歸一化:nn.BatchNorm2d(out_channel)
      • 定義兩個卷積層conv1conv2,其中conv1可能包含步幅stride用于降采樣。
      • 定義ReLU激活函數relu
      • 保存可選的下采樣層down_sample
  2. construct:
    • 作用:這是執行前向傳播的函數,用于定義輸入數據通過殘差塊的流程。
    • 參數:
      • x:輸入數據,通常是特征圖。
    • 代碼邏輯:
      • 保存輸入數據x作為身份映射(shortcuts分支)。
      • 通過第一個卷積層conv1處理輸入數據,然后進行規范化、ReLU激活。
      • 通過第二個卷積層conv2處理激活后的數據,然后進行規范化。
      • 判斷是否存在下采樣層down_sample,如果存在,則對身份映射進行下采樣以匹配輸出的維度。
      • 將主分支的輸出out與身份映射identity相加,實現跳躍連接(skip connection)。
      • 對相加的結果應用ReLU激活函數。
      • 返回最終的輸出out
        殘差塊通過跳躍連接允許梯度直接流過身份映射,這有助于解決深度網絡中的梯度消失問題,并允許網絡學習更復雜的函數。
class ResidualBlockBase(nn.Cell):expansion: int = 1  # 最后一個卷積核數量與第一個卷積核數量相等def __init__(self, in_channel: int, out_channel: int,stride: int = 1, norm: Optional[nn.Cell] = None,down_sample: Optional[nn.Cell] = None) -> None:super(ResidualBlockBase, self).__init__()if not norm:self.norm = nn.BatchNorm2d(out_channel)else:self.norm = normself.conv1 = nn.Conv2d(in_channel, out_channel,kernel_size=3, stride=stride,weight_init=weight_init)self.conv2 = nn.Conv2d(in_channel, out_channel,kernel_size=3, weight_init=weight_init)self.relu = nn.ReLU()self.down_sample = down_sampledef construct(self, x):"""ResidualBlockBase construct."""identity = x  # shortcuts分支out = self.conv1(x)  # 主分支第一層:3*3卷積層out = self.norm(out)out = self.relu(out)out = self.conv2(out)  # 主分支第二層:3*3卷積層out = self.norm(out)if self.down_sample is not None:identity = self.down_sample(x)out += identity  # 輸出為主分支與shortcuts之和out = self.relu(out)return out
---------------------------------------------------------------------------NameError                                 Traceback (most recent call last)Cell In[3], line 1
----> 1 class ResidualBlockBase(nn.Cell):2     expansion: int = 1  # 最后一個卷積核數量與第一個卷積核數量相等4     def __init__(self, in_channel: int, out_channel: int,5                  stride: int = 1, norm: Optional[nn.Cell] = None,6                  down_sample: Optional[nn.Cell] = None) -> None:NameError: name 'nn' is not defined

這段代碼定義了一個名為ResidualBlock的類,它也是殘差網絡(ResNet)中的一個殘差塊,但是與之前的基礎版殘差塊相比,這個類實現了更復雜的殘差學習結構,這個殘差塊包含了三個卷積層,其中第一個和第三個卷積層是1x1的,用于降維和升維,第二個卷積層是3x3的,用于提取特征。

函數解析

  1. __init__:
    • 作用:這是一個構造函數,用于初始化殘差塊。它定義了殘差塊的基本結構和操作,包括三個卷積層、三個批量歸一化層和ReLU激活函數。
    • 參數:
      • in_channel:輸入通道數。
      • out_channel:輸出通道數,這里的輸出通道數是指第一個卷積層之后的通道數,最終的輸出通道數將是這個數的4倍,由expansion變量控制。
      • stride:第二個卷積層的步幅,用于降采樣。
      • down_sample:可選的下采樣層,用于匹配輸入和輸出的維度,默認為None
    • 代碼邏輯:
      • 調用父類的構造函數:super(ResidualBlock, self).__init__()
      • 定義三個卷積層conv1conv2conv3,其中conv1conv3是1x1卷積,conv2是3x3卷積,conv2可能包含步幅stride用于降采樣。
      • 定義三個對應的批量歸一化層norm1norm2norm3
      • 定義ReLU激活函數relu
      • 保存可選的下采樣層down_sample
  2. construct:
    • 作用:這是執行前向傳播的函數,用于定義輸入數據通過殘差塊的流程。
    • 參數:
      • x:輸入數據,通常是特征圖。
    • 代碼邏輯:
      • 保存輸入數據x作為身份映射(shortcuts分支)。
      • 通過第一個卷積層conv1處理輸入數據,然后進行規范化、ReLU激活。
      • 通過第二個卷積層conv2處理激活后的數據,然后進行規范化、ReLU激活。
      • 通過第三個卷積層conv3處理激活后的數據,然后進行規范化。
      • 判斷是否存在下采樣層down_sample,如果存在,則對身份映射進行下采樣以匹配輸出的維度。
      • 將主分支的輸出out與身份映射identity相加,實現跳躍連接(skip connection)。
      • 對相加的結果應用ReLU激活函數。
      • 返回最終的輸出out
        這個殘差塊通過跳躍連接允許梯度直接流過身份映射,這有助于解決深度網絡中的梯度消失問題,并允許網絡學習更復雜的函數。這種結構在許多圖像識別任務中表現出色,并且是現代深度學習架構的重要組成部分。
def make_layer(last_out_channel, block: Type[Union[ResidualBlockBase, ResidualBlock]],channel: int, block_nums: int, stride: int = 1):down_sample = None  # shortcuts分支if stride != 1 or last_out_channel != channel * block.expansion:down_sample = nn.SequentialCell([nn.Conv2d(last_out_channel, channel * block.expansion,kernel_size=1, stride=stride, weight_init=weight_init),nn.BatchNorm2d(channel * block.expansion, gamma_init=gamma_init)])layers = []layers.append(block(last_out_channel, channel, stride=stride, down_sample=down_sample))in_channel = channel * block.expansion# 堆疊殘差網絡for _ in range(1, block_nums):layers.append(block(in_channel, channel))return nn.SequentialCell(layers)

這段代碼定義了一個名為make_layer的函數,它的作用是創建并堆疊多個殘差塊(Residual Blocks),形成殘差網絡(ResNet)中的一個層。這個函數可以根據給定的參數生成不同數量的殘差塊,并且可以處理不同層的輸入和輸出通道數不匹配的情況。

函數解析

  1. 函數參數:
    • last_out_channel:前一個層的輸出通道數。
    • block:殘差塊類型,可以是ResidualBlockBaseResidualBlock
    • channel:當前層的輸入通道數(對于第一個殘差塊)。
    • block_nums:要堆疊的殘差塊數量。
    • stride:第一個殘差塊的步幅,用于降采樣。
  2. 函數邏輯:
    • 首先定義一個down_sample變量,用于可能需要的下采樣操作。
    • 檢查是否需要下采樣,即如果stride不等于1或者last_out_channel不等于channel * block.expansion,則創建一個下采樣層,包括一個1x1的卷積層和一個批量歸一化層。
    • 初始化一個layers列表,并將第一個殘差塊添加到列表中,這個殘差塊使用down_sample作為其下采樣層。
    • 然后使用一個循環,將剩余的殘差塊添加到layers列表中,每個殘差塊的輸入通道數是前一個殘差塊的輸出通道數。
    • 最后,使用nn.SequentialCell(layers)將堆疊的殘差塊封裝為一個順序層(Sequential Layer),并返回這個層。
      這個函數是構建殘差網絡的關鍵部分,因為它允許開發者通過簡單地指定殘差塊的數量和配置來創建復雜的網絡結構。通過這種方式,可以很容易地增加網絡的深度,而不會遇到梯度消失問題,因為殘差塊的結構允許梯度直接流過身份映射。
from mindspore import load_checkpoint, load_param_into_netclass ResNet(nn.Cell):def __init__(self, block: Type[Union[ResidualBlockBase, ResidualBlock]],layer_nums: List[int], num_classes: int, input_channel: int) -> None:super(ResNet, self).__init__()self.relu = nn.ReLU()# 第一個卷積層,輸入channel為3(彩色圖像),輸出channel為64self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, weight_init=weight_init)self.norm = nn.BatchNorm2d(64)# 最大池化層,縮小圖片的尺寸self.max_pool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')# 各個殘差網絡結構塊定義,self.layer1 = make_layer(64, block, 64, layer_nums[0])self.layer2 = make_layer(64 * block.expansion, block, 128, layer_nums[1], stride=2)self.layer3 = make_layer(128 * block.expansion, block, 256, layer_nums[2], stride=2)self.layer4 = make_layer(256 * block.expansion, block, 512, layer_nums[3], stride=2)# 平均池化層self.avg_pool = nn.AvgPool2d()# flattern層self.flatten = nn.Flatten()# 全連接層self.fc = nn.Dense(in_channels=input_channel, out_channels=num_classes)def construct(self, x):x = self.conv1(x)x = self.norm(x)x = self.relu(x)x = self.max_pool(x)x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)x = self.avg_pool(x)x = self.flatten(x)x = self.fc(x)return xdef _resnet(model_url: str, block: Type[Union[ResidualBlockBase, ResidualBlock]],layers: List[int], num_classes: int, pretrained: bool, pretrianed_ckpt: str,input_channel: int):model = ResNet(block, layers, num_classes, input_channel)if pretrained:# 加載預訓練模型download(url=model_url, path=pretrianed_ckpt, replace=True)param_dict = load_checkpoint(pretrianed_ckpt)load_param_into_net(model, param_dict)return modeldef resnet50(num_classes: int = 1000, pretrained: bool = False):"ResNet50模型"resnet50_url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt"resnet50_ckpt = "./LoadPretrainedModel/resnet50_224_new.ckpt"return _resnet(resnet50_url, ResidualBlock, [3, 4, 6, 3], num_classes,pretrained, resnet50_ckpt, 2048)

函數部分解析:

  1. __init__:
    • 作用:這是一個構造函數,用于初始化ResNet模型。它定義了模型的所有層和操作。
    • 參數:
      • block:殘差塊類型,可以是ResidualBlockBaseResidualBlock
      • layer_nums:一個列表,指定每個殘差網絡結構塊中殘差塊的數量。
      • num_classes:輸出類別數,用于全連接層的輸出尺寸。
      • input_channel:全連接層的輸入通道數。
    • 代碼邏輯:
      • 調用父類的構造函數:super(ResNet, self).__init__()
      • 定義ReLU激活函數relu
      • 定義第一個卷積層conv1,用于處理輸入圖像。
      • 定義批量歸一化層norm
      • 定義最大池化層max_pool,用于縮小圖像尺寸。
      • 定義四個殘差網絡結構塊layer1layer4,每個塊由make_layer函數創建。
      • 定義平均池化層avg_pool
      • 定義Flatten層flatten,用于將特征圖展平為一維向量。
      • 定義全連接層fc,用于最終分類。
  2. construct:
    • 作用:這是執行前向傳播的函數,用于定義輸入數據通過整個ResNet模型的流程。
    • 參數:
      • x:輸入數據,通常是特征圖。
    • 代碼邏輯:
      • 通過第一個卷積層conv1處理輸入數據,然后進行批量歸一化和ReLU激活。
      • 通過最大池化層max_pool處理激活后的數據。
      • 通過四個殘差網絡結構塊layer1layer4處理數據。
      • 通過平均池化層avg_pool處理數據。
      • 通過Flatten層flatten將特征圖展平為一維向量。
      • 通過全連接層fc進行最終的分類。
      • 返回最終的輸出。
  3. _resnet:
    • 作用:這是一個輔助函數,用于創建并初始化ResNet模型,可以選擇是否加載預訓練的權重。
    • 參數:
      • model_url:預訓練模型的URL。
      • block:殘差塊類型。
      • layers:殘差塊的數量列表。
      • num_classes:輸出類別數。
      • pretrained:一個布爾值,指示是否加載預訓練模型。
      • pretrianed_ckpt:預訓練模型的本地路徑。
      • input_channel:全連接層的輸入通道數。
    • 代碼邏輯:
      • 創建ResNet模型model
      • 如果pretrained為True,則從model_url下載預訓練模型并將其加載到model中。
  4. resnet50:
    • 作用:這是一個工廠函數,用于創建ResNet50模型。
    • 參數:
      • num_classes:輸出類別數,默認為1000。
      • pretrained:一個布爾值,指示是否加載預訓練模型,默認為False。
    • 代碼邏輯:
      • 定義ResNet50模型的URL和本地檢查點路徑。
      • 調用_resnet函數創建并返回ResNet50模型,可以選擇是否加載預訓練的權重。

固定特征進行訓練

這部分代碼附有注釋,看代碼即可

import mindspore as ms
import matplotlib.pyplot as plt
import os
import timenet_work = resnet50(pretrained=True)# 全連接層輸入層的大小
in_channels = net_work.fc.in_channels
# 輸出通道數大小為狼狗分類數2
head = nn.Dense(in_channels, 2)
# 重置全連接層
net_work.fc = head# 平均池化層kernel size為7
avg_pool = nn.AvgPool2d(kernel_size=7)
# 重置平均池化層
net_work.avg_pool = avg_pool# 凍結除最后一層外的所有參數
for param in net_work.get_parameters():if param.name not in ["fc.weight", "fc.bias"]:param.requires_grad = False# 定義優化器和損失函數
opt = nn.Momentum(params=net_work.trainable_params(), learning_rate=lr, momentum=0.5)
loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')def forward_fn(inputs, targets):logits = net_work(inputs)loss = loss_fn(logits, targets)return lossgrad_fn = ms.value_and_grad(forward_fn, None, opt.parameters)def train_step(inputs, targets):loss, grads = grad_fn(inputs, targets)opt(grads)return loss# 實例化模型
model1 = train.Model(net_work, loss_fn, opt, metrics={"Accuracy": train.Accuracy()})

訓練和評估

訓練這塊之前有做過類似操作,不過多贅述

import mindspore as ms
import matplotlib.pyplot as plt
import os
import time
dataset_train = create_dataset_canidae(data_path_train, "train")
step_size_train = dataset_train.get_dataset_size()dataset_val = create_dataset_canidae(data_path_val, "val")
step_size_val = dataset_val.get_dataset_size()num_epochs = 5# 創建迭代器
data_loader_train = dataset_train.create_tuple_iterator(num_epochs=num_epochs)
data_loader_val = dataset_val.create_tuple_iterator(num_epochs=num_epochs)
best_ckpt_dir = "./BestCheckpoint"
best_ckpt_path = "./BestCheckpoint/resnet50-best-freezing-param.ckpt"
import mindspore as ms
import matplotlib.pyplot as plt
import os
import time
# 開始循環訓練
print("Start Training Loop ...")best_acc = 0for epoch in range(num_epochs):losses = []net_work.set_train()epoch_start = time.time()# 為每輪訓練讀入數據for i, (images, labels) in enumerate(data_loader_train):labels = labels.astype(ms.int32)loss = train_step(images, labels)losses.append(loss)# 每個epoch結束后,驗證準確率acc = model1.eval(dataset_val)['Accuracy']epoch_end = time.time()epoch_seconds = (epoch_end - epoch_start) * 1000step_seconds = epoch_seconds/step_size_trainprint("-" * 20)print("Epoch: [%3d/%3d], Average Train Loss: [%5.3f], Accuracy: [%5.3f]" % (epoch+1, num_epochs, sum(losses)/len(losses), acc))print("epoch time: %5.3f ms, per step time: %5.3f ms" % (epoch_seconds, step_seconds))if acc > best_acc:best_acc = accif not os.path.exists(best_ckpt_dir):os.mkdir(best_ckpt_dir)ms.save_checkpoint(net_work, best_ckpt_path)print("=" * 80)
print(f"End of validation the best Accuracy is: {best_acc: 5.3f}, "f"save the best ckpt file in {best_ckpt_path}", flush=True)

可視化模型預測

看代碼注釋即可

import matplotlib.pyplot as plt
import mindspore as msdef visualize_model(best_ckpt_path, val_ds):net = resnet50()# 全連接層輸入層的大小in_channels = net.fc.in_channels# 輸出通道數大小為狼狗分類數2head = nn.Dense(in_channels, 2)# 重置全連接層net.fc = head# 平均池化層kernel size為7avg_pool = nn.AvgPool2d(kernel_size=7)# 重置平均池化層net.avg_pool = avg_pool# 加載模型參數param_dict = ms.load_checkpoint(best_ckpt_path)ms.load_param_into_net(net, param_dict)model = train.Model(net)# 加載驗證集的數據進行驗證data = next(val_ds.create_dict_iterator())images = data["image"].asnumpy()labels = data["label"].asnumpy()class_name = {0: "dogs", 1: "wolves"}# 預測圖像類別output = model.predict(ms.Tensor(data['image']))pred = np.argmax(output.asnumpy(), axis=1)# 顯示圖像及圖像的預測值plt.figure(figsize=(5, 5))for i in range(4):plt.subplot(2, 2, i + 1)# 若預測正確,顯示為藍色;若預測錯誤,顯示為紅色color = 'blue' if pred[i] == labels[i] else 'red'plt.title('predict:{}'.format(class_name[pred[i]]), color=color)picture_show = np.transpose(images[i], (1, 2, 0))mean = np.array([0.485, 0.456, 0.406])std = np.array([0.229, 0.224, 0.225])picture_show = std * picture_show + meanpicture_show = np.clip(picture_show, 0, 1)plt.imshow(picture_show)plt.axis('off')plt.show()

2024-07-07 23:39:40 Mindstorm

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/44716.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/44716.shtml
英文地址,請注明出處:http://en.pswp.cn/web/44716.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java基礎之集合

集合和數組的類比 數組: 長度固定可以存基本數據類型和引用數據類型 集合: 長度可變只能存引用數據類型存儲基本數據類型要把他轉化為對應的包裝類 ArrayList集合 ArrayList成員方法 添加元素 刪除元素 索引刪除 查詢 遍歷數組

day30【LeetCode力扣】18.四數之和

day30【LeetCode力扣】18.四數之和 1.題目描述 給你一個由 n 個整數組成的數組 nums ,和一個目標值 target 。請你找出并返回滿足下述全部條件且不重復的四元組 [nums[a], nums[b], nums[c], nums[d]] (若兩個四元組元素一一對應,則認為兩個…

Linux: Mysql環境安裝

Mysql環境安裝(Centos) 前言一、卸載多余環境1.1 卸載mariadb1.2 查看并卸載系統mysql和mariadb安裝包 二、換取mysql官方yum源三、安裝并啟動mysql服務3.1 yum源加載3.2 安裝yum源3.3 安裝mysql服務3.3.1 安裝指令3.3.2 GPG密鑰問題解決方法3.3.3 查看是…

循環結構(一)——for語句【互三互三】

文章目錄 🍁 引言 🍁 一、語句格式 🍁 二、語句執行過程 🍁 三、語句格式舉例 🍁四、例題 👉【例1】 🚀示例代碼: 👉【例2】 【方法1】 🚀示例代碼: 【方法2】…

【C++ 編程】引用 - 給變量起別名、淺復制

基本語法:數據類型 &別名 原名int a 10; int &b a;引用必須初始化 (? int &b;),初始化后不可改變 (int c 5; b c:b 沒有變成c的別名,而是 a、b 對應的值變更為了 c 的值)本質是指針常量, 淺復制 【黑馬程序員匠…

Cartographer重入門到精通(二):運行作者demo及自己的數據集

在demo數據包上運行cartographer 現在Cartographer和Cartographer的Ros包已經都安裝好了,你可以下載官方的數據集到指定的目錄(比如在Deutsches Museum用背包采集的2D和3D 數據),然后使用roslauch來啟動demo。 注:la…

IO半虛擬化-Virtio學習筆記

參考:《深入淺出DPDK》及大佬們的各種博客 Virtio簡介&運行環境 Virtio 是一種用于虛擬化環境中的半虛擬化 I/O 框架,目的是在虛擬機和主機之間提供一種高效的 I/O 機制。關于什么是半虛擬化和全虛擬化:見SR-IOV學習筆記。 YES&#xf…

PDMS二次開發(二十二)——關于1.0.3.1版本升級內容的說明

目錄 1.更新內容介紹2.效果演示3.關于重構自動添加焊口功能的說明3.1錯誤示例 3.問題交流1.創建焊口提示失敗2.程序崩潰 1.更新內容介紹 在添加焊口之前先清除當前branch已有焊口;顯示清除焊口的個數和添加焊口的個數;重構了自動添加焊口功能&#xff0…

值得關注的數據資產入表

不錯的講解視頻,來自:第122期-杜海博士-《數據資源入表及數據資產化》-大數據百家講壇-廈門大學數據庫實驗室主辦第122期-杜海博士-《數據資源入表及數據資產化》-大數據百家講壇-廈門大學數據庫實驗室主辦-20240708_嗶哩嗶哩_bilibili

《A++ 敏捷開發》- 10 二八原則

團隊成員協作,利用項目數據,分析根本原因,制定糾正措施,并立馬嘗試,判斷是否有效,是改善的“基本功”。10-12章會探索里面的注意事項,13章會看兩家公司的實施情況和常見問題。 如果已經獲得高層…

Linq的常用方法

LINQ(Language Integrated Query)是.NET Framework中用于數據查詢的組件,它將查詢功能集成到C#等.NET語言中。LINQ提供了豐富的查詢操作符,這些操作符可以應用于各種數據源,如內存中的集合、數據庫、XML等。以下是一些…

java中的String 以及其方法(超詳細!!!)

文章目錄 一、String類型是什么String不可變的原因(經典面試題)String不可變的好處 二、String的常用構造形式1.使用常量串構造2.使用newString對象構造3.字符串數組構造 三、常用方法1. length() 獲取字符串的長度2. charAt() 獲取字符串中指定字符的值 (代碼單元)3. codePoin…

水的幾個科學問題及引發的思考

水的幾個科學問題及引發的思考 兩個相同的容器A和B,分別裝有同質量的水,然后,在A容器中加入水,在B容器中加入冰,如果加入水和冰的質量相同。問,容器B的水位將與容器A的水位相同嗎(假設冰未融化時…

Log4j的原理及應用詳解(二)

本系列文章簡介: 在軟件開發的廣闊領域中,日志記錄是一項至關重要的活動。它不僅幫助開發者追蹤程序的執行流程,還在問題排查、性能監控以及用戶行為分析等方面發揮著不可替代的作用。隨著軟件系統的日益復雜,對日志管理的需求也日…

MySQL和SQlServer的區別

MySQL和SQlServer的區別 說明:在一些常用的SQL語句中,MySQL和SQLServer存在有一些區別,后續我也會將我遇到的不同點持續更新在這篇博客中。 1. 獲取當前時間 SQLServer: -- SQLServer -- 1.獲取當前時間 SELECT GETDATE(); --…

Vue2切換圖片小案例

代碼中 v-show "index>0",是表示下標只有大于零時上一頁按鈕才會顯示v-show "index<list.length-1",是表示下標只有小于list數組的最大值才會顯示&#xff0c;反之隱藏。click "index--"和click "index",是點擊按鈕后加減數…

【ZooKeeper學習筆記】

1. ZooKeeper基本概念 Zookeeper官網&#xff1a;https://zookeeper.apache.org/index.html Zookeeper是Apache Hadoop項目中的一個子項目&#xff0c;是一個樹形目錄服務Zookeeper翻譯過來就是動物園管理員&#xff0c;用來管理Hadoop&#xff08;大象&#xff09;、Hive&…

AR0132AT 1/3 英寸 CMOS 數字圖像傳感器可提供百萬像素 HDR 圖像處理(器件編號包含:AR0132AT6R、AR0132AT6C)

AR0132AT 1/3 英寸 CMOS 數字圖像傳感器&#xff0c;帶 1280H x 960V 有效像素陣列。它能在線性或高動態模式下捕捉圖像&#xff0c;且帶有卷簾快門讀取。它包含了多種復雜的攝像功能&#xff0c;如自動曝光控制、開窗&#xff0c;以及視頻和單幀模式。它適用于低光度和高動態范…

QML界面控件加載與顯示順序

一、QML界面控件加載順序 QML在界面加載時的順序和我們認知的有很大的不同&#xff0c;有時候會對我們獲取參數以及界面實現造成很大的困擾 1、加載順序 import QtQuick 2.12 import QtQml 2.12 import QtQuick.Window 2.12 import QtQuick.VirtualKeyboard 2.4Window {id: …

Open3D點云算法與點云深度學習案例匯總(長期更新)

目錄 引言 Open3D算法匯總 Open3D快速安裝 測試點云資料 一、點云的讀寫與顯示 二、KD tree和八叉樹的應用 三、點云特征提取 四、點云濾波算法 五、點云配準算法 六、點云分割算法&#xff08;待更新&#xff09; 七、常用操作 八、數據轉換 九、常用小工具 三維…