内射老阿姨1区2区3区4区_久久精品人人做人人爽电影蜜月_久久国产精品亚洲77777_99精品又大又爽又粗少妇毛片

【CNN】搭建AlexNet網(wǎng)絡(luò)——并處理自定義的數(shù)據(jù)集(貓狗分類)-創(chuàng)新互聯(lián)

前言

2012年,AlexNet橫空出世。它首次證明了學(xué)習(xí)到的特征可以超越手工設(shè)計(jì)的特征。它一舉打破了計(jì)算機(jī)視覺研究的現(xiàn)狀。AlexNet使用了8層卷積神經(jīng)網(wǎng)絡(luò),并以很大的優(yōu)勢贏得了2012ImageNet圖像識別挑戰(zhàn)賽。

成都創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站建設(shè)、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的羅甸網(wǎng)站設(shè)計(jì)、移動媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

論文地址:http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf

這里我用的是貓狗分類的數(shù)據(jù)集,如下圖所示:
在這里插入圖片描述
本博文完整數(shù)據(jù)集:鏈接:https://pan.baidu.com/s/1ySqPErgpnUdk_mqrQU-GTg?pwd=6666

一,介紹

AlexNet和LeNet的架構(gòu)非常相似,
在這里插入圖片描述
在這里插入圖片描述
AlexNetLeNet的設(shè)計(jì)理念非常相似,但也存在顯著差異。 首先,AlexNet比相對較小的LeNet5要深得多。AlexNet由八層組成:五個卷積層、兩個全連接隱藏層和一個全連接輸出層。
其次,AlexNet使用ReLU而不是sigmoid作為其激活函數(shù)。
AlexNet的第一層,卷積窗口的形狀是11 x 11。 由于ImageNet中大多數(shù)圖像的寬和高比MNIST圖像的多10倍以上,因此,需要一個更大的卷積窗口來捕獲目標(biāo)。 第二層中的卷積窗口形狀被縮減為5 x 5,然后是3 x 3。 此外,在第一層、第二層和第五層卷積層之后,加入窗口形狀為、步幅為2的大匯聚層。 而且,AlexNet的卷積通道數(shù)目是LeNet10倍。

在最后一個卷積層后有兩個全連接層,分別有4096個輸出。
但是,我們這里只有兩類需要輸出,所以,這里最后把全兩層拉成2個輸出。

二,代碼實(shí)現(xiàn)

按照卷積的計(jì)算公式和上面的超參數(shù),通過卷積的輸出計(jì)算公式搭建網(wǎng)絡(luò):
在這里插入圖片描述
項(xiàng)目中的目錄結(jié)構(gòu):
在這里插入圖片描述

2.1 數(shù)據(jù)處理

對網(wǎng)絡(luò)中的數(shù)據(jù)進(jìn)行處理,由于我們已經(jīng)得到了貓狗數(shù)據(jù),開始對模型中的數(shù)據(jù)進(jìn)行2:8開,

  • 訓(xùn)練集:8;
  • 驗(yàn)證集:2;
import os
from shutil import copy
import random

def mkfile(file):
    if not os.path.exists(file):
        os.makedirs(file)
# 獲取所有要分類的文件夾
file_path = "./raw_data/"
train_path = 'data/train/'
validate_path = 'data/validate/'
# 列出所有花的種類
flow_cases  = [clazz for clazz in os.listdir(file_path)]
# 創(chuàng)建出驗(yàn)證集和訓(xùn)練集文件夾,并由類名在其目錄下創(chuàng)建五個子目錄
mkfile(train_path)
mkfile(validate_path)
for clazz in flow_cases:
    mkfile(train_path + clazz)
    mkfile(validate_path + clazz)
# 按照比例來進(jìn)行劃分, 訓(xùn)練集和測試集 = 9 : 1
split_rate = 0.1
# 遍歷所有類別的全部圖像,并按照比例分成訓(xùn)練集合驗(yàn)證集
for clazz in flow_cases:
    clazz_path = file_path + '/' + clazz + '/' # 某一個類別的文件夾
    images = os.listdir(clazz_path) # images 列表存儲來目錄下的所有圖片的名稱
    num = len(images)
    sample_images = random.sample(images, k=int(num * split_rate)) # 從images列表隨機(jī)sample出k個樣本
    for index, image in enumerate(images):
        # sample_images保存的是所有取出來的圖片
        if image in sample_images:
            image_path = clazz_path + image
            new_path = validate_path + clazz
            copy(image_path, new_path)
        # 其他的所有圖片都保留在訓(xùn)練集中
        else:
            image_path = clazz_path + image
            new_path = train_path + clazz
            copy(image_path, new_path)
        print(f'\r[{clazz}] processing [{index + 1} / {num}]', end="") # process bar
    print()

print("processing done!")
2.2 模型的搭建

按照文章中的內(nèi)容,對模型進(jìn)行搭建

import torch.nn as nn
import torch


class AlexNet(nn.Module):
    def __init__(self, num_classes=1000, init_weights=False):
        super(AlexNet, self).__init__()
        # 用nn.Sequential()將網(wǎng)絡(luò)打包成一個模塊,精簡代碼
        self.features = nn.Sequential(  # 卷積層提取圖像特征
            nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2),  # input[3, 224, 224]  output[48, 55, 55]
            nn.ReLU(inplace=True),  # 直接修改覆蓋原值,節(jié)省運(yùn)算內(nèi)存
            nn.MaxPool2d(kernel_size=3, stride=2),  # output[48, 27, 27]
            nn.Conv2d(48, 128, kernel_size=5, padding=2),  # output[128, 27, 27]
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),  # output[128, 13, 13]
            nn.Conv2d(128, 192, kernel_size=3, padding=1),  # output[192, 13, 13]
            nn.ReLU(inplace=True),
            nn.Conv2d(192, 192, kernel_size=3, padding=1),  # output[192, 13, 13]
            nn.ReLU(inplace=True),
            nn.Conv2d(192, 128, kernel_size=3, padding=1),  # output[128, 13, 13]
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3, stride=2),  # output[128, 6, 6]
        )
        self.classifier = nn.Sequential(  # 全連接層對圖像分類
            nn.Dropout(p=0.5),  # Dropout 隨機(jī)失活神經(jīng)元,默認(rèn)比例為0.5
            nn.Linear(128 * 6 * 6, 2048),
            nn.ReLU(inplace=True),
            nn.Dropout(p=0.5),
            nn.Linear(2048, 2048),
            nn.ReLU(inplace=True),
            nn.Linear(2048, num_classes),
        )
        if init_weights:
            self._initialize_weights()

    # 前向傳播過程
    def forward(self, x):
        x = self.features(x)
        x = torch.flatten(x, start_dim=1)  # 展平后再傳入全連接層
        x = self.classifier(x)
        return x

    # 網(wǎng)絡(luò)權(quán)重初始化,實(shí)際上 pytorch 在構(gòu)建網(wǎng)絡(luò)時會自動初始化權(quán)重
    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):  # 若是卷積層
                nn.init.kaiming_normal_(m.weight, mode='fan_out',  # 用(何)kaiming_normal_法初始化權(quán)重
                                        nonlinearity='relu')
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)  # 初始化偏重為0
            elif isinstance(m, nn.Linear):  # 若是全連接層
                nn.init.normal_(m.weight, 0, 0.01)  # 正態(tài)分布初始化
                nn.init.constant_(m.bias, 0)  # 初始化偏重為0
2.3 開始訓(xùn)練

自定義數(shù)據(jù)的訓(xùn)練邏輯

TRAIN_ROOT = r'data/train'
VALIDATE_ROOT = 'data/validate'
# 進(jìn)行數(shù)據(jù)的處理,定義數(shù)據(jù)轉(zhuǎn)換
data_transform = {"train": transforms.Compose([transforms.RandomResizedCrop(224),       # 隨機(jī)裁剪,再縮放成 224×224
                                 transforms.RandomHorizontalFlip(p=0.5),  # 水平方向隨機(jī)翻轉(zhuǎn),概率為 0.5, 即一半的概率翻轉(zhuǎn), 一半的概率不翻轉(zhuǎn)
                                 transforms.ToTensor(),
                                 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),

    "validate": transforms.Compose([transforms.Resize((224, 224)),  # cannot 224, must (224, 224)
                               transforms.ToTensor(),
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}
# 加載數(shù)據(jù)集
train_dataset = ImageFolder(TRAIN_ROOT, transform=data_transform['train'])
validate_dataset = ImageFolder(VALIDATE_ROOT, transform=data_transform['validate'])
# 講數(shù)據(jù)進(jìn)行小批量處理
train_dataloader = DataLoader(train_dataset,
                              batch_size=32,
                              shuffle=True,
                              num_workers=0)
val_dataloader = DataLoader(validate_dataset,
                            batch_size=32,
                            shuffle=True,
                            num_workers=0)

device = 'cuda' if torch.cuda.is_available() else 'cpu'

model = AlexNet(num_classes=2).to(device)
# 定義一個損失函數(shù)
loss_fn = nn.CrossEntropyLoss()
# 定義一個優(yōu)化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# 學(xué)習(xí)率每隔10輪變?yōu)樵瓉淼?.5
lr_scheduler = lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5)
# 定義訓(xùn)練函數(shù)
def train(dataloader, model, loss_fn, optimizer):
    model.train()
    time_start = time.perf_counter()  # 對訓(xùn)練一個 epoch 計(jì)時
    loss, current, n = 0.0, 0.0, 0
    for batch, (x, y) in enumerate(dataloader):
        image, y = x.to(device), y.to(device)
        output = model(image)
        cur_loss = loss_fn(output, y)
        # 取大的哪個坐標(biāo)
        _, pred = torch.max(output, axis=1)
        cur_acc = torch.sum(y==pred) / output.shape[0]

        # 反向傳播
        optimizer.zero_grad()
        cur_loss.backward()
        optimizer.step()
        loss += cur_loss.item()
        current += cur_acc.item()
        n = n+1
        # 打印訓(xùn)練進(jìn)度(使訓(xùn)練過程可視化)
        rate = (batch + 1) / len(dataloader)  # 當(dāng)前進(jìn)度 = 當(dāng)前step / 訓(xùn)練一輪epoch所需總step
        a = "*" * int(rate * 50)
        b = "." * int((1 - rate) * 50)
        print("\r{:^3.0f}%[{}->{}]".format(int(rate * 100), a, b), end="")
    print('%f s' % (time.perf_counter() - time_start))
    # 返回平均的loss
    train_loss = loss / n
    train_acc = current / n
    print('train_loss' + str(train_loss))
    print('train_acc' + str(train_acc))
    return train_loss, train_acc

# 定義一個驗(yàn)證函數(shù)
def val(dataloader, model, loss_fn):
    # 將模型轉(zhuǎn)化為驗(yàn)證模型
    model.eval()
    loss, current, n = 0.0, 0.0, 0
    with torch.no_grad():
        for batch, (x, y) in enumerate(dataloader):
            image, y = x.to(device), y.to(device)
            output = model(image)
            cur_loss = loss_fn(output, y)
            _, pred = torch.max(output, axis=1)
            cur_acc = torch.sum(y == pred) / output.shape[0]
            loss += cur_loss.item()
            current += cur_acc.item()
            n = n + 1

    val_loss = loss / n
    val_acc = current / n
    print('val_loss' + str(val_loss))
    print('val_acc' + str(val_acc))
    return val_loss, val_acc

# 解決中文顯示問題
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 定義畫圖函數(shù)
def matplot_loss(train_loss, val_loss):
    plt.plot(train_loss, label='train_loss')
    plt.plot(val_loss, label='val_loss')
    plt.legend(loc='best')
    plt.ylabel('loss')
    plt.xlabel('epoch')
    plt.title("訓(xùn)練集和驗(yàn)證集loss值對比圖")
    plt.show()

def matplot_acc(train_acc, val_acc):
    plt.plot(train_acc, label='train_acc')
    plt.plot(val_acc, label='val_acc')
    plt.legend(loc='best')
    plt.ylabel('acc')
    plt.xlabel('epoch')
    plt.title("訓(xùn)練集和驗(yàn)證集acc值對比圖")
    plt.show()

# 開始訓(xùn)練
loss_train = []
acc_train = []
loss_val = []
acc_val = []


epoch = 20
min_acc = 0
for t in range(epoch):
    lr_scheduler.step()
    print(f"epoch{t+1}\n-----------")
    train_loss, train_acc = train(train_dataloader, model, loss_fn, optimizer)
    val_loss, val_acc = val(val_dataloader, model, loss_fn)

    loss_train.append(train_loss)
    acc_train.append(train_acc)
    loss_val.append(val_loss)
    acc_val.append(val_acc)

    # 保存最好的模型權(quán)重
    if val_acc >min_acc:
        folder = 'save_model'
        if not os.path.exists(folder):
            os.mkdir('save_model')
        min_acc = val_acc
        print(f"save best model, 第{t+1}輪")
        torch.save(model.state_dict(), 'save_model/best_model.pth')
    # 保存最后一輪的權(quán)重文件
    if t == epoch-1:
        torch.save(model.state_dict(), 'save_model/last_model.pth')

matplot_loss(loss_train, loss_val)
matplot_acc(acc_train, acc_val)
print('Done!')
2.4 最后對模型進(jìn)行驗(yàn)證
TRAIN_ROOT = 'data/train'
VALIDATE_ROOT = 'data/validate'
# 進(jìn)行數(shù)據(jù)的處理,定義數(shù)據(jù)轉(zhuǎn)換
data_transform = {"train": transforms.Compose([transforms.RandomResizedCrop(224),       # 隨機(jī)裁剪,再縮放成 224×224
                                 transforms.RandomHorizontalFlip(p=0.5),  # 水平方向隨機(jī)翻轉(zhuǎn),概率為 0.5, 即一半的概率翻轉(zhuǎn), 一半的概率不翻轉(zhuǎn)
                                 transforms.ToTensor(),
                                 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),

    "validate": transforms.Compose([transforms.Resize((224, 224)),  # cannot 224, must (224, 224)
                               transforms.ToTensor(),
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}
# 加載數(shù)據(jù)集
train_dataset = ImageFolder(TRAIN_ROOT, transform=data_transform['train'])
validate_dataset = ImageFolder(VALIDATE_ROOT, transform=data_transform['validate'])
# 講數(shù)據(jù)進(jìn)行小批量處理
train_dataloader = DataLoader(train_dataset,
                              batch_size=32,
                              shuffle=True,
                              num_workers=0)
val_dataloader = DataLoader(validate_dataset,
                            batch_size=32,
                            shuffle=True,
                            num_workers=0)

device = 'cuda' if torch.cuda.is_available() else 'cpu'

model = AlexNet(num_classes=2).to(device)

# 加載模型
model.load_state_dict(torch.load("save_model/best_model.pth", map_location='cpu'))
# 獲取預(yù)測結(jié)果
classes = [
    "cat",
    "dog",
]

# 把張量轉(zhuǎn)化為照片格式
show = ToPILImage()

# 進(jìn)入到驗(yàn)證階段
model.eval()
for i in range(10):
    x, y = validate_dataset[i][0], validate_dataset[i][1]
    show(x).show()
    x = Variable(torch.unsqueeze(x, dim=0).float(), requires_grad=True).to(device)
    x = torch.tensor(x).to(device)
    with torch.no_grad():
        pred = model(x)
        # 用argmax獲取概率大的一個物體
        predicted, actual = classes[torch.argmax(pred[0])], classes[y]
        print(f'predicted:"{predicted}", Actual:"{actual}"')
三,總結(jié)
  • 在每個卷機(jī)后面添加了Relu激活函數(shù),解決了Sigmoid的梯度消失問題,使收斂更快。
  • 使用隨機(jī)丟棄技術(shù)(dropout)選擇性地忽略訓(xùn)練中的單個神經(jīng)元,避免模型的過擬合(也使用數(shù)據(jù)增強(qiáng)防止過擬合)
  • 添加了歸一化LRNLocal Response Normalization,局部響應(yīng)歸一化)層,使準(zhǔn)確率更高。
  • 重疊大池化(overlapping max pooling),即池化范圍z與步長s存在關(guān)系z>s避免平均池化(average pooling)的平均效應(yīng)

完整代碼: https://github.com/fckey/DeepLearning_cases/tree/master/AlexNet

四,參考

https://zhuanlan.zhihu.com/p/116197079
https://blog.csdn.net/frighting_ing/article/details/120774252

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

分享文章:【CNN】搭建AlexNet網(wǎng)絡(luò)——并處理自定義的數(shù)據(jù)集(貓狗分類)-創(chuàng)新互聯(lián)
標(biāo)題網(wǎng)址:http://www.rwnh.cn/article38/csjdpp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)、網(wǎng)站設(shè)計(jì)公司、域名注冊、移動網(wǎng)站建設(shè)網(wǎng)站內(nèi)鏈、商城網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化
舞阳县| 黑龙江省| 黎川县| 澳门| 米泉市| 十堰市| 都安| 玛多县| 丘北县| 文登市| 北安市| 星座| 伊吾县| 西宁市| 阿巴嘎旗| 佛教| 新营市| 巴彦淖尔市| 临沭县| 芦溪县| 石楼县| 弥渡县| 咸丰县| 南丰县| 和林格尔县| 黄平县| 乾安县| 安龙县| 施秉县| 南和县| 久治县| 西城区| 鄢陵县| 南开区| 开江县| 石楼县| 修水县| 肥东县| 宜州市| 洞头县| 崇文区|