昇思25天學習打卡營第18天|ShuffleNet圖像分類

?一、簡介:

ShuffleNetV1是曠視科技提出的一種計算高效的CNN模型,和MobileNet, SqueezeNet等一樣主要應用在移動端,所以模型的設計目標就是利用有限的計算資源來達到最好的模型精度。ShuffleNetV1的設計核心是引入了兩種操作:Pointwise Group Convolution和Channel Shuffle,這在保持精度的同時大大降低了模型的計算量。因此,ShuffleNetV1和MobileNet類似,都是通過設計更高效的網絡結構來實現模型的壓縮和加速。如下圖所示,ShuffleNet在保持不低的準確率的前提下,將參數量幾乎降低到了最小,因此其運算速度較快,單位參數量對模型準確率的貢獻非常高。

?二、模型架構:

ShuffleNet最顯著的特點在于對不同通道進行重排來解決Group Convolution帶來的弊端。通過對ResNet的Bottleneck單元進行改進,在較小的計算量的情況下達到了較高的準確率。

1、Pointwise Group Convolution:

Group Convolution(分組卷積)原理如下圖所示,相比于普通的卷積操作,分組卷積的情況下,每一組的卷積核大小為in_channels/g*k*k,一共有g組,所有組共有(in_channels/g*k*k)*out_channels個參數,是正常卷積參數的1/g。分組卷積中,每個卷積核只處理輸入特征圖的一部分通道,其有點在于參數量會有所降低,但是輸出通道仍等于卷積核數量。

Depthwise Convolution(深度可分離卷積)將組數g分為和輸入通道相等的in_channels,然后對每一個in_channels做卷積操作,每個卷積核只處理一個通道,記卷積核大小為1*k*k,則卷積核參數量為:in_channels*k*k,得到的feature maps通道數與輸入通道數相等。

Pointwise Group Convolution(逐點分組卷積)在分組卷積的基礎上,令每一組的卷積核大小為1×1,卷積核參數量為(in_channels/g*1*1)*out_channels。

在進行下面的代碼實驗之前還是需要先安裝mindspore包,安裝過程可以參考:昇思25天學習打卡營第1天|快速入門。

from mindspore import nn
import mindspore.ops as ops
from mindspore import Tensorclass GroupConv(nn.Cell):def __init__(self, in_channels, out_channels, kernel_size,stride, pad_mode="pad", pad=0, groups=1, has_bias=False):super(GroupConv, self).__init__()self.groups = groupsself.convs = nn.CellList()for _ in range(groups):self.convs.append(nn.Conv2d(in_channels // groups, out_channels // groups,kernel_size=kernel_size, stride=stride, has_bias=has_bias,padding=pad, pad_mode=pad_mode, group=1, weight_init='xavier_uniform'))def construct(self, x):features = ops.split(x, split_size_or_sections=int(len(x[0]) // self.groups), axis=1)outputs = ()for i in range(self.groups):outputs = outputs + (self.convs[i](features[i].astype("float32")),)out = ops.cat(outputs, axis=1)return out

2、Channel Shuffle:

Group Convolution的弊端在于不同組別的通道無法進行信息交流,堆積GConv層后一個問題是不同組之間的特征圖是不通信的,這就好像分成了g個互不相干的道路,每一個人各走各的,這可能會降低網絡的特征提取能力。這也是Xception,MobileNet等網絡采用密集的1x1卷積(Dense Pointwise Convolution)的原因。為了解決不同組別通道“近親繁殖”的問題,ShuffleNet優化了大量密集的1x1卷積(在使用的情況下計算量占用率達到了驚人的93.4%),引入Channel Shuffle機制(通道重排)。這項操作直觀上表現為將不同分組通道均勻分散重組,使網絡在下一層能處理不同組別通道的信息。

如下圖所示,對于g組(也就是上文提到的g個互不相干的道路),每組有n個通道的特征圖,首先reshape成g行n列的矩陣,再將矩陣轉置成n行g列,最后進行flatten操作,得到新的排列。這些操作都是可微分可導的且計算簡單,在解決了信息交互的同時符合了ShuffleNet輕量級網絡設計的輕量特征。

?

?這里將channel_shuffle的代碼實現先展示出來,后面為了在shuffleNet中使用會再次重新實現

def channel_shuffle(self, x):batchsize, num_channels, height, width = ops.shape(x)group_channels = num_channels // self.groupx = ops.reshape(x, (batchsize, group_channels, self.group, height, width))x = ops.transpose(x, (0, 2, 1, 3, 4))x = ops.reshape(x, (batchsize, num_channels, height, width))return x

?三、構建ShuffleNet網絡:

1、ShuffleNet模塊:

如下圖所示,ShuffleNet對ResNet中的Bottleneck結構進行由(a)到(b), (c)的更改:

  1. 將開始和最后的1×1卷積模塊(降維、升維)改成Point Wise Group Convolution;

  2. 為了進行不同通道的信息交流,再降維之后進行Channel Shuffle;

  3. 降采樣模塊中,3×3?Depth Wise Convolution的步長設置為2,長寬降為原來的一般,因此shortcut中采用步長為2的3×3平均池化,并把相加改成拼接。

class ShuffleV1Block(nn.Cell):def __init__(self, inp, oup, group, first_group, mid_channels, ksize, stride):super(ShuffleV1Block, self).__init__()self.stride = stridepad = ksize // 2self.group = groupif stride == 2:outputs = oup - inpelse:outputs = oupself.relu = nn.ReLU()branch_main_1 = [GroupConv(in_channels=inp, out_channels=mid_channels,kernel_size=1, stride=1, pad_mode="pad", pad=0,groups=1 if first_group else group),nn.BatchNorm2d(mid_channels),nn.ReLU(),]branch_main_2 = [nn.Conv2d(mid_channels, mid_channels, kernel_size=ksize, stride=stride,pad_mode='pad', padding=pad, group=mid_channels,weight_init='xavier_uniform', has_bias=False),nn.BatchNorm2d(mid_channels),GroupConv(in_channels=mid_channels, out_channels=outputs,kernel_size=1, stride=1, pad_mode="pad", pad=0,groups=group),nn.BatchNorm2d(outputs),]self.branch_main_1 = nn.SequentialCell(branch_main_1)self.branch_main_2 = nn.SequentialCell(branch_main_2)if stride == 2:self.branch_proj = nn.AvgPool2d(kernel_size=3, stride=2, pad_mode='same')def construct(self, old_x):left = old_xright = old_xout = old_xright = self.branch_main_1(right)if self.group > 1:right = self.channel_shuffle(right)right = self.branch_main_2(right)if self.stride == 1:out = self.relu(left + right)elif self.stride == 2:left = self.branch_proj(left)out = ops.cat((left, right), 1)out = self.relu(out)return outdef channel_shuffle(self, x):batchsize, num_channels, height, width = ops.shape(x)group_channels = num_channels // self.groupx = ops.reshape(x, (batchsize, group_channels, self.group, height, width))x = ops.transpose(x, (0, 2, 1, 3, 4))x = ops.reshape(x, (batchsize, num_channels, height, width))return x

?2、網絡構建:

ShuffleNet網絡結構如下圖所示,以輸入圖像224×224,組數3(g = 3)為例,首先通過數量24,卷積核大小為3×3,stride為2的卷積層,輸出特征圖大小為112×112,channel為24;然后通過stride為2的最大池化層,輸出特征圖大小為56×56,channel數不變;再堆疊3個ShuffleNet模塊(Stage2, Stage3, Stage4),三個模塊分別重復4次、8次、4次,其中每個模塊開始先經過一次下采樣模塊(上圖(c)),使特征圖長寬減半,channel翻倍(Stage2的下采樣模塊除外,將channel數從24變為240);隨后經過全局平均池化,輸出大小為1×1×960,再經過全連接層和softmax,得到分類概率。

class ShuffleNetV1(nn.Cell):def __init__(self, n_class=1000, model_size='2.0x', group=3):super(ShuffleNetV1, self).__init__()print('model size is ', model_size)self.stage_repeats = [4, 8, 4]self.model_size = model_sizeif group == 3:if model_size == '0.5x':self.stage_out_channels = [-1, 12, 120, 240, 480]elif model_size == '1.0x':self.stage_out_channels = [-1, 24, 240, 480, 960]elif model_size == '1.5x':self.stage_out_channels = [-1, 24, 360, 720, 1440]elif model_size == '2.0x':self.stage_out_channels = [-1, 48, 480, 960, 1920]else:raise NotImplementedErrorelif group == 8:if model_size == '0.5x':self.stage_out_channels = [-1, 16, 192, 384, 768]elif model_size == '1.0x':self.stage_out_channels = [-1, 24, 384, 768, 1536]elif model_size == '1.5x':self.stage_out_channels = [-1, 24, 576, 1152, 2304]elif model_size == '2.0x':self.stage_out_channels = [-1, 48, 768, 1536, 3072]else:raise NotImplementedErrorinput_channel = self.stage_out_channels[1]self.first_conv = nn.SequentialCell(nn.Conv2d(3, input_channel, 3, 2, 'pad', 1, weight_init='xavier_uniform', has_bias=False),nn.BatchNorm2d(input_channel),nn.ReLU(),)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')features = []for idxstage in range(len(self.stage_repeats)):numrepeat = self.stage_repeats[idxstage]output_channel = self.stage_out_channels[idxstage + 2]for i in range(numrepeat):stride = 2 if i == 0 else 1first_group = idxstage == 0 and i == 0features.append(ShuffleV1Block(input_channel, output_channel,group=group, first_group=first_group,mid_channels=output_channel // 4, ksize=3, stride=stride))input_channel = output_channelself.features = nn.SequentialCell(features)self.globalpool = nn.AvgPool2d(7)self.classifier = nn.Dense(self.stage_out_channels[-1], n_class)def construct(self, x):x = self.first_conv(x)x = self.maxpool(x)x = self.features(x)x = self.globalpool(x)x = ops.reshape(x, (-1, self.stage_out_channels[-1]))x = self.classifier(x)return x

?四、模型的訓練核評估:

1、數據集準備:

采用CIFAR-10數據集對ShuffleNet進行預訓練。

from download import downloadurl = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz"download(url, "./dataset", kind="tar.gz", replace=True)# 數據預處理:
import mindspore as ms
from mindspore.dataset import Cifar10Dataset
from mindspore.dataset import vision, transformsdef get_dataset(train_dataset_path, batch_size, usage):image_trans = []if usage == "train":image_trans = [vision.RandomCrop((32, 32), (4, 4, 4, 4)),vision.RandomHorizontalFlip(prob=0.5),vision.Resize((224, 224)),vision.Rescale(1.0 / 255.0, 0.0),vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),vision.HWC2CHW()]elif usage == "test":image_trans = [vision.Resize((224, 224)),vision.Rescale(1.0 / 255.0, 0.0),vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),vision.HWC2CHW()]label_trans = transforms.TypeCast(ms.int32)dataset = Cifar10Dataset(train_dataset_path, usage=usage, shuffle=True)dataset = dataset.map(image_trans, 'image')dataset = dataset.map(label_trans, 'label')dataset = dataset.batch(batch_size, drop_remainder=True)return datasetdataset = get_dataset("./dataset/cifar-10-batches-bin", 128, "train")
batches_per_epoch = dataset.get_dataset_size()

2、模型訓練:

使用隨機初始化的參數做預訓練。首先調用ShuffleNetV1定義網絡,參數量選擇"2.0x",并定義損失函數為交叉熵損失,學習率經過4輪的warmup后采用余弦退火,優化器采用Momentum。最后用train.model中的Model接口將模型、損失函數、優化器封裝在model中,并用model.train()對網絡進行訓練。將ModelCheckpointCheckpointConfigTimeMonitorLossMonitor傳入回調函數中,將會打印訓練的輪數、損失和時間,并將ckpt文件保存在當前目錄下。

import time
import mindspore
import numpy as np
from mindspore import Tensor, nn
from mindspore.train import ModelCheckpoint, CheckpointConfig, TimeMonitor, LossMonitor, Model, Top1CategoricalAccuracy, Top5CategoricalAccuracydef train():mindspore.set_context(mode=mindspore.PYNATIVE_MODE, device_target="Ascend")net = ShuffleNetV1(model_size="2.0x", n_class=10)loss = nn.CrossEntropyLoss(weight=None, reduction='mean', label_smoothing=0.1)min_lr = 0.0005base_lr = 0.05lr_scheduler = mindspore.nn.cosine_decay_lr(min_lr,base_lr,batches_per_epoch*250,batches_per_epoch,decay_epoch=250)lr = Tensor(lr_scheduler[-1])optimizer = nn.Momentum(params=net.trainable_params(), learning_rate=lr, momentum=0.9, weight_decay=0.00004, loss_scale=1024)loss_scale_manager = ms.amp.FixedLossScaleManager(1024, drop_overflow_update=False)model = Model(net, loss_fn=loss, optimizer=optimizer, amp_level="O3", loss_scale_manager=loss_scale_manager)callback = [TimeMonitor(), LossMonitor()]save_ckpt_path = "./"config_ckpt = CheckpointConfig(save_checkpoint_steps=batches_per_epoch, keep_checkpoint_max=5)ckpt_callback = ModelCheckpoint("shufflenetv1", directory=save_ckpt_path, config=config_ckpt)callback += [ckpt_callback]print("============== Starting Training ==============")start_time = time.time()# 由于時間原因,epoch = 5,可根據需求進行調整model.train(5, dataset, callbacks=callback)use_time = time.time() - start_timehour = str(int(use_time // 60 // 60))minute = str(int(use_time // 60 % 60))second = str(int(use_time % 60))print("total time:" + hour + "h " + minute + "m " + second + "s")print("============== Train Success ==============")if __name__ == '__main__':train()

2、模型評估:

在已經劃分好的測試集上進行模型評估:

from mindspore import load_checkpoint, load_param_into_netdef test():mindspore.set_context(mode=mindspore.GRAPH_MODE, device_target="Ascend")dataset = get_dataset("./dataset/cifar-10-batches-bin", 128, "test")net = ShuffleNetV1(model_size="2.0x", n_class=10)param_dict = load_checkpoint("shufflenetv1-5_390.ckpt")load_param_into_net(net, param_dict)net.set_train(False)loss = nn.CrossEntropyLoss(weight=None, reduction='mean', label_smoothing=0.1)eval_metrics = {'Loss': nn.Loss(), 'Top_1_Acc': Top1CategoricalAccuracy(),'Top_5_Acc': Top5CategoricalAccuracy()}model = Model(net, loss_fn=loss, metrics=eval_metrics)start_time = time.time()res = model.eval(dataset, dataset_sink_mode=False)use_time = time.time() - start_timehour = str(int(use_time // 60 // 60))minute = str(int(use_time // 60 % 60))second = str(int(use_time % 60))log = "result:" + str(res) + ", ckpt:'" + "./shufflenetv1-5_390.ckpt" \+ "', time: " + hour + "h " + minute + "m " + second + "s"print(log)filename = './eval_log.txt'with open(filename, 'a') as file_object:file_object.write(log + '\n')if __name__ == '__main__':test()

?還是那句話,只要能跑,就不要動(doge)

五、模型預測:

在CIFAR-10的測試集上對模型進行預測,并將預測結果可視化:

import mindspore
import matplotlib.pyplot as plt
import mindspore.dataset as dsnet = ShuffleNetV1(model_size="2.0x", n_class=10)
show_lst = []
param_dict = load_checkpoint("shufflenetv1-5_390.ckpt")
load_param_into_net(net, param_dict)
model = Model(net)
dataset_predict = ds.Cifar10Dataset(dataset_dir="./dataset/cifar-10-batches-bin", shuffle=False, usage="train")
dataset_show = ds.Cifar10Dataset(dataset_dir="./dataset/cifar-10-batches-bin", shuffle=False, usage="train")
dataset_show = dataset_show.batch(16)
show_images_lst = next(dataset_show.create_dict_iterator())["image"].asnumpy()
image_trans = [vision.RandomCrop((32, 32), (4, 4, 4, 4)),vision.RandomHorizontalFlip(prob=0.5),vision.Resize((224, 224)),vision.Rescale(1.0 / 255.0, 0.0),vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),vision.HWC2CHW()]
dataset_predict = dataset_predict.map(image_trans, 'image')
dataset_predict = dataset_predict.batch(16)
class_dict = {0:"airplane", 1:"automobile", 2:"bird", 3:"cat", 4:"deer", 5:"dog", 6:"frog", 7:"horse", 8:"ship", 9:"truck"}
# 推理效果展示(上方為預測的結果,下方為推理效果圖片)
plt.figure(figsize=(16, 5))
predict_data = next(dataset_predict.create_dict_iterator())
output = model.predict(ms.Tensor(predict_data['image']))
pred = np.argmax(output.asnumpy(), axis=1)
index = 0
for image in show_images_lst:plt.subplot(2, 8, index+1)plt.title('{}'.format(class_dict[pred[index]]))index += 1plt.imshow(image)plt.axis("off")
plt.show()

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

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

相關文章

如何在centos7安裝Docker

在centOS7中我們可以使用火山引擎鏡像源鏡像安裝Docker,以下是具體的安裝步驟。 step 1: 安裝必要的一些系統工具 sudo yum install -y yum-utils Step 2: 添加軟件源信息 sudo yum-config-manager --add-repo https://mirrors.ivolces.com/docker/linux/centos/docker-ce.r…

力扣雙指針算法題目:二叉樹的層序遍歷(BFS)

目錄 1.題目 2.思路解析 3.代碼 1.題目 . - 力扣(LeetCode) 2.思路解析 對二叉樹進行層序遍歷,顧名思義,就是按每一層的順序對二叉樹一層一層地進行遍歷 思路如下 從第一層開始,先將二叉樹地頭放入隊列q&#xff0…

獨孤思維:副業被罵煞筆,割韭菜

做副業不要被外界干擾,不要被情緒牽絆。 不要因為別人的無心謾罵,隨口一評,就偃旗息鼓。 不要因為自己的情緒需要,找存在感,尋求人安慰。 他強任他強,清風拂山崗。 他橫由他橫,明月照大江。…

2007-2022年中國各企業數字化轉型與供應鏈效率

企業數字化轉型與供應鏈效率是現代企業管理和發展的兩個關鍵方面。以下是對中國各企業數字化轉型與供應鏈效率數據的介紹: 數據簡介 企業數字化轉型:指企業通過采用數字技術與創新方法,改造業務流程、組織結構和產品服務,以提升…

UCOS-III 系統移植

1. 移植前準備 1.1 源碼下載 UCOS-III Kernel Source: https://github.com/weston-embedded/uC-OS3.git Micriμm CPU Source : https://github.com/weston-embedded/uC-CPU.git Micriμm Lib Source: https://github.com/weston-embedded…

Nginx配置文件全解:從入門到設計

Nginx配置文件全解:從入門到架構設計 1. Nginx配置文件基礎 Nginx的主配置文件通常位于/etc/nginx/nginx.conf?。配置文件使用簡單的文本格式,由指令和指令塊組成。 1.1 基本語法規則 每個指令以分號(;)結束指令塊用大括號({})包圍配置文件支持使用…

多方SQL計算場景下,如何達成雙方共識,確認多方計算作業的安全性

安全多方計算在SQL場景下的限制 隨著MPC、隱私計算等概念的流行, 諸多政府機構、金融企業開始考慮參與到多方計算的場景中, 擴展數據的應用價值。 以下面這個場景為例, 銀行可能希望獲取水電局和稅務局的數據,來綜合計算得到各…

DolphinScheduler-3.1.9 資源中心實踐

前言 目前DolphinScheduler最新的穩定版本是 3.1.9 ,基于此做些探索,逐漸深化學習路徑,以便于加深理解。 3.2.1 是最新的版本。目前的穩定版本是 3.1.9 基礎環境:Hadoop3.3, Java 8, Python3, MacOS14.2.1 一、本地偽分布式安裝…

學習筆記——動態路由——IS-IS中間系統到中間系統(開銷)

四、IS-IS開銷 1、IS-IS 開銷簡介 在IS-IS協議剛面世時,互聯網網絡結構還非常簡單,因此IS-IS早期的版本中只使用了6bit來描述鏈路開銷,鏈路開銷的取值范圍是1-63。一條路由的開銷范圍只有10bit,取值范圍是0-1023。 隨著計…

前端實現無縫自動滾動動畫

1. 前言: 前端使用HTMLCSS實現一個無縫滾動的列表效果 示例圖: 2. 源碼 html部分源碼: <!--* Author: wangZhiyu <w3209605851163.com>* Date: 2024-07-05 23:33:20* LastEditTime: 2024-07-05 23:49:09* LastEditors: wangZhiyu <w3209605851163.com>* File…

【ubuntu】安裝(升級)顯卡驅動,黑屏|雙屏無法使用問題解決方法

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 ubuntu 安裝(升級)顯卡驅動&#xff0c;黑屏|雙屏無法使用問題解決方法 由于項目需要&#xff0c;對顯卡驅動進行升級。升級完就黑屏。。。。&#xff0…

Fast R-CNN(論文閱讀)

論文名&#xff1a;Fast R-CNN 論文作者&#xff1a;Ross Girshick 期刊/會議名&#xff1a;ICCV 2015 發表時間&#xff1a;2015-9 ?論文地址&#xff1a;https://arxiv.org/pdf/1504.08083 源碼&#xff1a;https://github.com/rbgirshick/fast-rcnn 摘要 這篇論文提出了一…

WordPress禁止用戶注冊某些用戶名

不管在任何網站&#xff0c;用戶注冊時都有一個屏蔽非法關鍵詞&#xff0c;就是禁止注冊某些用戶名&#xff0c;原因是因為防止用戶使用一些特定的用戶名&#xff0c;例如管理員、官方等用戶名&#xff0c;還有就是那些攻擊性的詞語了。 加網站添加了屏蔽非法關鍵詞&#xff0…

BAT-致敬精簡

什么是bat bat是windows的批處理程序&#xff0c;可以批量完成一些操作&#xff0c;方便快速。 往往我們可以出通過 winR鍵來打開指令窗口&#xff0c;這里輸入的就是bat指令 這里就是bat界面 節約時間就是珍愛生命--你能想象以下2分鐘的操作&#xff0c;bat只需要1秒鐘 我…

考慮數據庫粒度的設計-提升效率

目錄 概要 場景 設計思路 小結 概要 公開的資料顯示&#xff0c;數據庫粒度是&#xff1a;“在數據庫領域&#xff0c;特別是數據倉庫的設計中&#xff0c;粒度是一個核心概念&#xff0c;它直接影響到數據分析的準確性和存儲效率。粒度的設定涉及到數據的詳細程度和精度&…

【JVM基礎篇】Java的四種垃圾回收算法介紹

文章目錄 垃圾回收算法垃圾回收算法的歷史和分類垃圾回收算法的評價標準標記清除算法優缺點 復制算法優缺點 標記整理算法&#xff08;標記壓縮算法&#xff09;優缺點 分代垃圾回收算法&#xff08;常用&#xff09;JVM參數設置使用Arthas查看內存分區垃圾回收執行流程分代GC算…

【SpringBoot】IDEA查看spring bean的依賴關系

前因&#xff1a;在研究springcloud config組件時&#xff0c;我發現config-server包下的EnvironmentController可以響應客戶端的請求&#xff0c;但EnvironmentController并不在啟動類所在的包路徑下&#xff0c;所以我推測它是作為某個Bean方法在生效&#xff0c;尋找bean的依…

vue-router 源碼分析——9.別名

這是對vue-router 3 版本的源碼分析。 本次分析會按以下方法進行&#xff1a; 按官網的使用文檔順序&#xff0c;圍繞著某一功能點進行分析。這樣不僅能學習優秀的項目源碼&#xff0c;更能加深對項目的某個功能是如何實現的理解。這個對自己的技能提升&#xff0c;甚至面試時…

DAY1: 實習前期準備

文章目錄 VS Code安裝的插件C/CCMakeGitHub CopilotRemote-SSH收獲 VS Code 下載鏈接&#xff1a;https://code.visualstudio.com 安裝的插件 C/C 是什么&#xff1a;C/C IntelliSense, debugging, and code browsing. 為什么&#xff1a;初步了解如何在VS Code里使用C輸出…

https創建證書

需要下載httpd模塊&#xff1a;yum install httpd -y 前提需要先搭建一個虛擬主機來測試證書創建的效果&#xff0c;以下面www.hehe.com為例&#xff0c;可以參考創建&#xff1a; [rootlocalhost conf.d]# vim vhost.conf <directory /www> allowoverride none requi…