中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

網(wǎng)站建設(shè)調(diào)查報(bào)告范文seo是怎么優(yōu)化上去

網(wǎng)站建設(shè)調(diào)查報(bào)告范文,seo是怎么優(yōu)化上去,代賣平臺(tái)哪個(gè)好,廣州繼續(xù)教育平臺(tái)登錄入口打開深度學(xué)習(xí)的鎖 導(dǎo)言PS:神經(jīng)網(wǎng)絡(luò)的訓(xùn)練過程一、導(dǎo)入的包和說明二、數(shù)據(jù)的預(yù)處理2.1 數(shù)據(jù)集說明2.2 數(shù)據(jù)集降維度并且轉(zhuǎn)置2.3 數(shù)據(jù)預(yù)處理完整代碼 三、邏輯回歸3.1 線性回歸函數(shù)公式3.2 sigmoid函數(shù)公式 四、初始化函數(shù)五、構(gòu)建邏輯回歸的前向傳播和后向傳播5.1 損…

打開深度學(xué)習(xí)的鎖

  • 導(dǎo)言
  • PS:神經(jīng)網(wǎng)絡(luò)的訓(xùn)練過程
  • 一、導(dǎo)入的包和說明
  • 二、數(shù)據(jù)的預(yù)處理
    • 2.1 數(shù)據(jù)集說明
    • 2.2 數(shù)據(jù)集降維度并且轉(zhuǎn)置
    • 2.3 數(shù)據(jù)預(yù)處理完整代碼
  • 三、邏輯回歸
    • 3.1 線性回歸函數(shù)公式
    • 3.2 sigmoid函數(shù)公式
  • 四、初始化函數(shù)
  • 五、構(gòu)建邏輯回歸的前向傳播和后向傳播
    • 5.1 損失函數(shù)
    • 5.2 前向傳播
    • 5.3 后向傳播
      • 5.3.1 梯度下降算法
    • 5.4 前向傳播和后向傳播完整代碼
  • 六、代碼逐步擬合
    • 6.1 運(yùn)行梯度下降更新w和b
    • 6.2 實(shí)現(xiàn)預(yù)測(cè)函數(shù)(計(jì)算數(shù)據(jù)轉(zhuǎn)化的值)
    • 6.3 模型調(diào)用函數(shù)
    • 6.4 完整代碼和測(cè)試
    • 6.5 再玩一下?好的!
  • 寫在后面的話

導(dǎo)言

本篇知識(shí)背景來源于吳恩達(dá)教授的DeepLearning課程作業(yè)–第二節(jié),有興趣的同學(xué)可以自行搜索。
博客所用到的數(shù)據(jù)集和測(cè)試代碼已經(jīng)公開:Github

這篇博客本質(zhì)內(nèi)容吳恩達(dá)教授的DeepLearning的課程作業(yè)第二節(jié),是題解。個(gè)人覺得作為神經(jīng)網(wǎng)絡(luò)入門練習(xí)是一個(gè)很棒的契機(jī),故以此記錄。

博客中包含一點(diǎn)Python向量化(Vectorization)和導(dǎo)數(shù)(Derivative)及鏈?zhǔn)椒▌t(Chain rule)的內(nèi)容,如果看不明白也沒關(guān)系,別緊張也別怕。只需要明白以下的內(nèi)容即可:

1.Python向量化(Vectorization): 一種技術(shù),就是代替Python的for循環(huán),跑的比f(wàn)or循環(huán)快。

2.導(dǎo)數(shù)(Derivative)及鏈?zhǔn)椒▌t(Chain rule): 如果你知道 ?+A=B也就是知道"A增加導(dǎo)致B增加",它可以告訴我們它們之間是如何互相影響的。

這篇博客中用到的主要是NumPy庫(kù)中的函數(shù),但是我不會(huì)詳細(xì)的去講解每一個(gè)函數(shù)的功能,就是使用。

還有一點(diǎn)很重要,如果你是科班,之前只是說過“機(jī)器學(xué)習(xí)”、“深度學(xué)習(xí)”、“模型”這類詞匯,感覺中間的處理很黑盒,但是不了解到底是什么。

那么這些很重要:

所謂模型:是由很多同類型的數(shù)據(jù)產(chǎn)生的一個(gè)(組)參數(shù)適合函數(shù),得到這個(gè)函數(shù),方便處理其它同類型數(shù)據(jù)。

模型不是軟件!不是軟件!不是軟件!

所謂學(xué)習(xí):通過數(shù)據(jù)的輸入–>得到模型的預(yù)測(cè)值,將預(yù)測(cè)值和實(shí)際的標(biāo)簽比較,標(biāo)簽和預(yù)測(cè)值的差異稱為損失。通過之間的損失自動(dòng)調(diào)整公式里面參數(shù),最終找那個(gè)可以讓損失最小的、合適的公式的參數(shù)!

不是單純的輸入數(shù)據(jù)和輸入的標(biāo)簽學(xué)習(xí)映射關(guān)系!

好了,讓我們開始吧。

PS:神經(jīng)網(wǎng)絡(luò)的訓(xùn)練過程

放此圖在這里為了快速認(rèn)識(shí),也為了需要的時(shí)候快速查找。初次看的時(shí)候看不懂沒關(guān)系,可以先看下面的內(nèi)容。
在這里插入圖片描述

一、導(dǎo)入的包和說明

關(guān)于頭文件的說明:

#1.導(dǎo)入序列化必要函數(shù)
import numpy as np#2.導(dǎo)入生成圖片要的包
# 在 Python 中導(dǎo)入 matplotlib 庫(kù)的 pyplot 模塊并為其指定一個(gè)簡(jiǎn)稱 plt 的語(yǔ)句。matplotlib 是一個(gè)非常流行的 Python 數(shù)據(jù)可視化庫(kù),它提供了一套全面的繪圖工具來制作各種靜態(tài)、動(dòng)態(tài)或交互式的圖形。
# pyplot 是 matplotlib 的一個(gè)子模塊,通常被認(rèn)為是該庫(kù)的核心。它提供了一個(gè)類似于 MATLAB 的繪圖界面,使得創(chuàng)建圖形變得非常簡(jiǎn)單。
import matplotlib.pyplot as plt#導(dǎo)入針對(duì)數(shù)據(jù)格式的包,本篇中用到的數(shù)據(jù)集格式是.h5. 
# h5py 是一個(gè) Python 庫(kù),它提供了一種高效的方式來讀取和寫入 HDF5(h5) 格式的文件。
# HDF5(Hierarchical Data Format version 5)是一個(gè)流行的數(shù)據(jù)存儲(chǔ)格式,常用于大型數(shù)據(jù)集,如科學(xué)計(jì)算或深度學(xué)習(xí)中的訓(xùn)練數(shù)據(jù)。
# HDF5 文件可以包含大量的數(shù)據(jù)集并支持高效的并行IO操作,它提供了一種結(jié)構(gòu)化的方式來存儲(chǔ)數(shù)據(jù),其中數(shù)據(jù)可以被組織為不同的組和數(shù)據(jù)集。
import h5py#從lr_utils文件(或者稱為模塊,每一個(gè)py文件就是一個(gè)模塊)導(dǎo)入函數(shù)
from lr_utils import load_dataset

二、數(shù)據(jù)的預(yù)處理

2.1 數(shù)據(jù)集說明

在給出的文件lr_utils 中的load_dataset函數(shù)是對(duì)訓(xùn)練集和測(cè)試集的預(yù)處理,并且已經(jīng)封裝好了

import numpy as np
import h5pydef load_dataset():train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r")  train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set features#保存的是訓(xùn)練集里面的圖像數(shù)據(jù)(本訓(xùn)練集有209張64x64的圖像)。train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labels#保存的是訓(xùn)練集的圖像對(duì)應(yīng)的分類值(【0 | 1】,0表示不是貓,1表示是貓)。test_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set features#保存的是測(cè)試集里面的圖像數(shù)據(jù)(本訓(xùn)練集有50張64x64的圖像)。test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labels#保存的是測(cè)試集的圖像對(duì)應(yīng)的分類值(【0 | 1】,0表示不是貓,1表示是貓)。classes = np.array(test_dataset["list_classes"][:]) # the list of classes#保存的是以bytes類型保存的兩個(gè)字符串?dāng)?shù)據(jù),數(shù)據(jù)為:[b’non-cat’ b’cat’]。train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

我們直接在主文件里面使用即可

import numpy as np
import matplotlib.pyplot as plt
import h5py 
from lr_utils import load_dataset#全局變量
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes=load_dataset()

現(xiàn)在,我們擁有了數(shù)據(jù)集和測(cè)試集合,可以使用X.shape的方法查看一下它們的維度

print(train_set_x_orig.shape) #(209, 64, 64, 3) 維度說明:訓(xùn)練數(shù)據(jù)集是由209個(gè) 64*64的3色域圖片組成
print(train_set_y_orig.shape) #(1, 209) 標(biāo)簽,1維度的209個(gè)標(biāo)簽

我們注意到訓(xùn)練集是一個(gè)(209,64,64,3)維度的矩陣,那么這個(gè)是什么呢?

其實(shí)就是保存的209個(gè),大小為64*64像素的RGB的圖片

舉個(gè)例子:
在這里插入圖片描述

這里有一可愛的貓貓的圖片,假設(shè)它的大小是 5*5 個(gè)像素。(圖片來源:圖片)

我們知道,每一個(gè)圖片在計(jì)算機(jī)中存儲(chǔ)的形式都是由紅色(R)、綠色(G)、藍(lán)色(B)三個(gè)底色圖片構(gòu)成

在這里插入圖片描述
這三個(gè)底色圖片的參數(shù)都不一樣,因?yàn)椴灰粯?#xff0c;所以才可以構(gòu)成千顏萬(wàn)色。

對(duì)于當(dāng)前的步驟,我們不需要關(guān)心每一個(gè)矩陣中的參數(shù)是怎么樣的。

我們只需要知道,一個(gè)圖片,在計(jì)算機(jī)中完整的像素的個(gè)數(shù)是:高像素 X 寬像素 X 3
在這里插入圖片描述

所以,一個(gè)圖片的矩陣向量的表現(xiàn)形式就是 [ 高像素 , 寬像素 , 3 ] ,這條貓貓的矩陣向量的表現(xiàn)形式是[5,5,3]

在這里插入圖片描述
而在本題中,作為數(shù)據(jù)集,自然要有樣本的個(gè)數(shù),所以我們的train_set_x_orig矩陣多了一個(gè)209,代表樣本的個(gè)數(shù)。

print(train_set_x_orig.shape) #(209, 64, 64, 3) 維度說明:訓(xùn)練數(shù)據(jù)集是由209個(gè) 64*64的3色域圖片組成

為了證明我沒有胡說,我們打印兩個(gè)數(shù)據(jù)集中的圖片看看

第一個(gè):高貴的瓦坎達(dá)吉祥物

#打印測(cè)試單個(gè)
index=25
plt.imshow(train_set_x_orig[index])
plt.show()
# print("label:"+str(train_set_y_orig[:,index]))

在這里插入圖片描述

第二個(gè):非貓

#打印測(cè)試單個(gè)
index=26
plt.imshow(train_set_x_orig[index])
plt.show()
# # print("label:"+str(train_set_y_orig[:,index]))

在這里插入圖片描述

2.2 數(shù)據(jù)集降維度并且轉(zhuǎn)置

好了,將接下來我們需對(duì)于數(shù)據(jù)集降維度并且轉(zhuǎn)置。

為什么這樣做呢?

為了方便數(shù)據(jù)輸入到模型,我們希望統(tǒng)一訓(xùn)練集和測(cè)試集的格式。

我們剛剛提到的,測(cè)試了兩個(gè)數(shù)據(jù)集合的維度,可以看到它們是不匹配的

print(train_set_x_orig.shape) #(209, 64, 64, 3)表示樣本個(gè)數(shù)的209在第一維度,之后有三個(gè)維度的數(shù)據(jù)。
print(train_set_y_orig.shape) #(1, 209) 表示標(biāo)簽個(gè)數(shù)的209在第二個(gè)維度,之前有一個(gè)維度的數(shù)據(jù)。

所以,我們希望將第一個(gè)數(shù)據(jù)集的格式,轉(zhuǎn)化成和第二個(gè)數(shù)據(jù)集合一樣的個(gè)格式。

我們的目的是希望將 A(a,b,c,d) 的矩陣變成 A(b * c * d , a) 矩陣,公式為:

X_flatten =X.reshape(X.shape[0],-1).T 

代碼如下:

#Dimensionally reduce and Transpose the Training Data_set
# print(train_set_x_orig.shape) #(209, 64, 64, 3)
train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T
# print(train_set_x_flatten.shape) #(12288, 209)
#Dimensionally reduce and Transpose the Testing Data_Set
# print(test_set_x_orig.shape) #(50, 64, 64, 3)
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T
# print(test_set_x_flatten.shape) #(12288, 50)

下一步,我們希望標(biāo)準(zhǔn)化數(shù)據(jù),將每一行的值控制在0-1之間。標(biāo)準(zhǔn)化的方法有很多,但是因?yàn)樗械亩际菆D片的RGB,所以可以直接除以255

train_set_x=train_set_x_flatten/255
test_set_x=test_set_x_flatten/255

這個(gè)時(shí)候有小朋友就會(huì)問了:“ 前面不是已經(jīng)將除了”個(gè)數(shù)“以外的數(shù)據(jù)都相乘了嗎?只除以一個(gè)255夠了嗎?”

當(dāng)然,因?yàn)?code>reshape 函數(shù)允許我們重新組織數(shù)組的維度,但它 不會(huì) 更改數(shù)組元素的順序或值。

也就是說,只是維度被整合了,元素里面的值和內(nèi)容還是沒有改變。

并且,我們都知道在矩陣計(jì)算中乘除一個(gè)數(shù)就算對(duì)矩陣內(nèi)的所有元素進(jìn)行乘除,所以只寫一個(gè)/225就夠啦!

2.3 數(shù)據(jù)預(yù)處理完整代碼

#獲取數(shù)據(jù)集
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes=load_dataset()# 打印測(cè)試單個(gè)
index=25
plt.imshow(train_set_x_orig[index])
plt.show()
# print("label:"+str(train_set_y_orig[:,index]))#降維度
# print(train_set_x_orig.shape) #(209, 64, 64, 3)
train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T
# print(train_set_x_flatten.shape) #(12288, 209)
#Dimensionally reduce and Transpose the Testing Data_Set
# print(test_set_x_orig.shape) #(50, 64, 64, 3)
test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T
# print(test_set_x_flatten.shape) #(12288, 50)
#將每一行的值控制在0-1之間,因?yàn)樗械亩际菆D片的RGB,所以可以除以255
train_set_x=train_set_x_flatten/255
test_set_x=test_set_x_flatten/255

三、邏輯回歸

數(shù)據(jù)處理的部分完成了,接下來就是構(gòu)建神經(jīng)網(wǎng)絡(luò)。我們要處理的是二分類問題,而 “邏輯回歸” 是處理二分問題的一個(gè)算法。

邏輯回歸的目標(biāo):實(shí)際上是找到一個(gè)決策邊界,然后根據(jù)樣本點(diǎn)相對(duì)于這個(gè)邊界的位置來分類,對(duì)于線性邏輯回歸,這個(gè)決策邊界是一條直線(在二維空間中)或一個(gè)超平面(在更高的維度中),這取決于特征的數(shù)量。

就是說,找一條線,將數(shù)據(jù)劃分為兩個(gè)部分。
在這里插入圖片描述

如果維度高的話,是找一個(gè)面來劃分
在這里插入圖片描述
對(duì)于邏輯回歸的函數(shù),我們可以理解為:

邏輯回歸函數(shù)=線性回歸函數(shù) + sigmoid函數(shù)

3.1 線性回歸函數(shù)公式

Z = z ( i ) = w T ? x ( i ) + b Z = z^{(i)} = w^T \cdot x^{(i)} + b Z=z(i)=wT?x(i)+b

  1. x i x^i xi: 第i個(gè)樣本的特征向量
  2. w: 權(quán)重向量,表示當(dāng)前 x i x^i xi的權(quán)重比(權(quán)重用于決定決策邊界怎么畫)
  3. w.T: 是w的轉(zhuǎn)置,我們?yōu)榱擞?jì)算w與x的“點(diǎn)乘”,要求w的行向量 == x的列向量.如果你的 w 向量本來就是一個(gè)行向量,并且它的長(zhǎng)度(列數(shù))與 x 向量的長(zhǎng)度(行數(shù))相同,不需要再進(jìn)行轉(zhuǎn)置,但是,權(quán)重向量和特征向量通常都被定義為列向量,這是一種約束。
  4. b: 這是偏置項(xiàng),它是一個(gè)常數(shù)。
  5. z i z^i zi: 第i個(gè)樣本的線性輸出。輸入一個(gè) x i x^i xi,會(huì)得到一個(gè) z i z^i zi

3.2 sigmoid函數(shù)公式

σ ( z ) = 1 1 + e ? z \sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+e?z1?
或者,嵌套線性回歸函數(shù)
y ^ i = 1 1 + e ? ( w T ? x ( i ) + b ) \hat{y}^i = \frac{1}{1 + e^{-( w^T \cdot x^{(i)} + b)}} y^?i=1+e?(wT?x(i)+b)1?
關(guān)于sigmoid函數(shù),我們需要知道:

  1. 它是一種激活函數(shù),激活函數(shù)是神經(jīng)網(wǎng)絡(luò)中的一個(gè)重要組成部分,它決定一個(gè)神經(jīng)元是否應(yīng)該被“激活”或“觸發(fā)”。具體地說,激活函數(shù)定義了每個(gè)神經(jīng)元的輸出與其輸入之間的關(guān)系。它為神經(jīng)網(wǎng)絡(luò)引入了非線性因素,使得網(wǎng)絡(luò)能夠?qū)W習(xí)并執(zhí)行更復(fù)雜的任務(wù)。
  2. 它的輸出范圍:[0,1]
  3. 它的圖像是這樣:

在這里插入圖片描述

當(dāng)我們將一個(gè) x i x^i xi輸入到sigmoid函數(shù)中,會(huì)得到一個(gè) y ^ \hat{y} y^?或者 y ^ i \hat{y}^i y^?i ,它是由 x i x^i xi生成的和當(dāng)前標(biāo)簽 y i y^i yi同類型的值(這也是為什么用hat/y表示而不是用別的字母)

它是0和1之間的概率值,表示正類(也就是1)的預(yù)測(cè)概率。

在這里, y ^ i 是模型對(duì)輸入? x i 的預(yù)測(cè)輸出,而? y i 是實(shí)際的標(biāo)簽或真實(shí)值。 \text{在這里,} \hat{y}^i \text{ 是模型對(duì)輸入 } x^i \text{ 的預(yù)測(cè)輸出,而 } y^i \text{ 是實(shí)際的標(biāo)簽或真實(shí)值。} 在這里,y^?i?是模型對(duì)輸入?xi?的預(yù)測(cè)輸出,而?yi?是實(shí)際的標(biāo)簽或真實(shí)值。

我們希望? x i 生成的預(yù)測(cè) y ^ i 盡可能接近? x i 的標(biāo)簽? y i 。 \text{我們希望 } {x}^i \text{ 生成的預(yù)測(cè)} \hat{y}^i \text{盡可能接近 }{x}^i \text{的標(biāo)簽 }y^i \text{。} 我們希望?xi?生成的預(yù)測(cè)y^?i盡可能接近?xi的標(biāo)簽?yi。

為了得到一個(gè)明確的分類預(yù)測(cè)(0或1),可以設(shè)定一個(gè)閾值,通常為0.5。如果 y ^ \hat{y} y^?大于0.5,則預(yù)測(cè)為1,否則為0。

所以,在這個(gè)公式中,為了讓 y ^ \hat{y} y^? 趨近于1,我們便需要讓 w T ? x ( i ) + b w^T \cdot x^{(i)} + b wT?x(i)+b的值盡可能的大。

所以,邏輯回歸的目標(biāo),就是找到合適的 w w w b b b

好了,概念理清了,我們開始寫代碼

對(duì)于代碼,關(guān)于線性函數(shù)我們一會(huì)可以使用np里面的函數(shù)直接計(jì)算,所以只需要寫sigmoid的函數(shù)即可:

def sigmoid(z): #z:傳入的線性函數(shù)的結(jié)果值s=1/(1+np.exp(-z))return s  #$\hat{y}$

下一步,既然要找 w w w b b b,我們就應(yīng)該寫一個(gè)初始化函數(shù)先給 w w w b b b 賦默認(rèn)值。

四、初始化函數(shù)

很簡(jiǎn)單,直接上代碼:

def initialize_zeros(dim):#為了創(chuàng)建可以和訓(xùn)練集X計(jì)算的權(quán)重矩陣w:#dim:傳入的數(shù)據(jù)集的第一個(gè)向量坐標(biāo),X.shape[0]#一些博客里面會(huì)這樣寫#w=np.zeros(shape=(dim,1))#這樣做的目的是將所有的值用0填充,但是這樣也許會(huì)導(dǎo)致一個(gè)“對(duì)稱性”問題#當(dāng)你這樣初始化權(quán)重并使用它們?cè)谏窠?jīng)網(wǎng)絡(luò)中時(shí),每一層的所有神經(jīng)元都會(huì)有相同的輸出。#因此,當(dāng)你進(jìn)行反向傳播時(shí),所有神經(jīng)元都會(huì)收到相同的梯度。這將導(dǎo)致所有的權(quán)重都更新為相同的值。無論網(wǎng)絡(luò)有多少神經(jīng)元,它們都會(huì)表現(xiàn)得像一個(gè)神經(jīng)元,這極大地限制了網(wǎng)絡(luò)的容量和表達(dá)能力。#所以我們使用隨機(jī)w=0.01*np.random.rand(dim,1)#乘以0.01是為了確保初始化的權(quán)重值很小。b=0#使用斷言來檢測(cè)是正確assert(w.shape==(dim,1))assert(isinstance(b,float) or isinstance(b,int))return (w,b)

初始化參數(shù)的函數(shù)已經(jīng)構(gòu)建好了,現(xiàn)在就可以執(zhí)行“前向”和“后向”傳播步驟來學(xué)習(xí)參數(shù)。

五、構(gòu)建邏輯回歸的前向傳播和后向傳播

神經(jīng)網(wǎng)絡(luò)或者深度學(xué)習(xí)模型單次的訓(xùn)練過程有四個(gè)階段:

  1. 前向傳播:給當(dāng)前數(shù)據(jù) x i x^i xi,根據(jù)算法(當(dāng)前我們用的是sigmoid函數(shù))輸出一個(gè)結(jié)果 y ^ i \hat y^i y^?i
  2. 計(jì)算機(jī)損失:得到前向傳播的預(yù)測(cè) y ^ i \hat y^i y^?i以后,我們會(huì)評(píng)估“預(yù)測(cè)與我們給定的標(biāo)簽 y i y^i yi之間的差異。這個(gè)差異(通常稱為“損失”或“誤差”)
  3. 后向傳播:基于前面計(jì)算的損失,模型會(huì)計(jì)算每個(gè)參數(shù)的梯度,以知道如何更好地更新參數(shù)來提高預(yù)測(cè)。這個(gè)步驟就是告訴模型:“為了減少預(yù)測(cè)誤差,你應(yīng)該這樣調(diào)整你的參數(shù)w和b?!?/li>
  4. 更新參數(shù): 在知道了如何更新參數(shù)之后,實(shí)際更新參數(shù)。

到目前為之,我們已經(jīng)完成了前兩步的基本實(shí)現(xiàn)和理論概括。我將會(huì)在這個(gè)章節(jié)將它們進(jìn)行組合,實(shí)現(xiàn)完整的前向傳播和后向傳播。
不過在此之前,我們還需要引入一個(gè)東西:損失函數(shù)

5.1 損失函數(shù)

很久很久以前,在一座威嚴(yán)聳立的山上。一群數(shù)學(xué)家在給一群哲學(xué)家分完筷子以后,閑的無聊。這個(gè)時(shí)候,突然有人想到了一個(gè)問題:

有沒有什么辦法可以讓標(biāo)簽 ( y i {y^i} yi) 為 1 x i {x^i} xi 的預(yù)測(cè)值 ( y ^ i \hat{y}^i y^?i) 趨近于 1

有沒有什么辦法可以讓標(biāo)簽 ( y i {y^i} yi) 為 0 x i {x^i} xi 的預(yù)測(cè)值 ( y ^ i \hat{y}^i y^?i) 趨近于 0

這個(gè)時(shí)候,有一個(gè)拿到 兩!根!筷!子! 的哲學(xué)家說,簡(jiǎn)單啊,你讓

可以讓標(biāo)簽 ( y i {y^i} yi) 為 1 x i {x^i} xi 的預(yù)測(cè)值 ( y ^ i \hat{y}^i y^?i) 不趨近于 0
可以讓標(biāo)簽 ( y i {y^i} yi) 為 0 x i {x^i} xi 的預(yù)測(cè)值 ( y ^ i \hat{y}^i y^?i) 不趨近于 1

在把這個(gè)哲學(xué)家祭天以后,一個(gè)數(shù)學(xué)家仔細(xì)琢磨這句話,說:“不如這樣吧,我們可以想一個(gè)公式,在公式里面同時(shí)輸入 y i {y^i} yi y ^ i \hat{y}^i y^?i。如果這兩個(gè)的值很相近呢,就讓這個(gè)公式的輸出的值小一點(diǎn)。如果不相近呢,就讓它的輸出大一點(diǎn)?!?/font>

“那我們用 對(duì)數(shù)(log) 吧!” 另一個(gè)數(shù)學(xué)家說道。

“既然不相近,我們假設(shè)這個(gè)公式的輸出為 L o s s Loss Loss吧!代表 “損失”

如果輸入的 y i {y^i} yi1 ,我就讓 L o s s = ? log ? ( y ^ ( i ) ) Loss= -\log(\hat{y}^{(i)}) Loss=?log(y^?(i)), 這樣如果 y ^ i \hat{y}^i y^?i接近 0 時(shí),S會(huì)特別大,反之會(huì)特別小。
如果輸入的 y i {y^i} yi0, 我就讓 L o s s = ? log ? ( 1 ? y ^ ( i ) ) Loss = -\log(1 - \hat{y}^{(i)}) Loss=?log(1?y^?(i)), 這樣如果 y ^ i \hat{y}^i y^?i接近 1 時(shí),S會(huì)特別大,反之會(huì)特別小。”

“那我們把它們結(jié)合一下吧,成為一個(gè)公式。同時(shí)讓這兩個(gè)公式添加兩個(gè)非0即1相反的乘數(shù)。雖然是一個(gè)公式,但是同時(shí)只有一半可以用?!?/p>

“我看就用 y i {y^i} yi 1 ? y i 1-{y^i} 1?yi 吧,這兩個(gè)不是標(biāo)簽么?非0即1”

“太棒了!讓我再來添加一個(gè)帥氣的符號(hào)吧!把它變成:
L o s s = L ( y , y ^ ) = ? [ y log ? ( y ^ ) + ( 1 ? y ) log ? ( 1 ? y ^ ) ] Loss=L(y, \hat{y}) = -[y \log(\hat{y}) + (1 - y) \log(1 - \hat{y})] Loss=L(y,y^?)=?[ylog(y^?)+(1?y)log(1?y^?)]
“太帥了!!!,我們給它取一個(gè)名字吧!同時(shí)找一個(gè)帥氣的翻譯者,把它翻譯詞讓人 望!而!生!畏! 的中文吧!”

“那就叫:

二元交叉熵?fù)p失函數(shù)(Binary Cross-Entropy Loss,也稱為log loss)

吧!”

“既然有處理單個(gè)數(shù)據(jù)的函數(shù)了,那么我們?cè)俑纳埔幌掳?#xff0c;讓它可以處理多個(gè)數(shù)據(jù)吧!

“這好辦呀!假設(shè)有 M M M個(gè)數(shù)據(jù),我們把每一個(gè)單一的數(shù)據(jù)結(jié)果加起來,然后再除以 M M M不就好了嗎?”

“既然結(jié)果依賴于 y ^ ( i ) \hat{y}^{(i)} y^?(i) y ( i ) {y}^{(i)} y(i),同時(shí) y ( i ) {y}^{(i)} y(i) x ( i ) {x}^{(i)} x(i)是給定的不能修改,那么可以說結(jié)果決度定于 y ^ ( i ) \hat{y}^{(i)} y^?(i)

y ^ ( i ) \hat{y}^{(i)} y^?(i)不是來源于 y ^ ( i ) = 1 1 + e ? ( w T ? x ( i ) + b ) \hat{y}^(i) = \frac{1}{1 + e^{-( w^T \cdot x^{(i)} + b)}} y^?(i)=1+e?(wT?x(i)+b)1?嗎?而且剛剛不是有個(gè)高大威猛帥氣的男生說 邏輯回歸的目標(biāo),就是找到合適的 w w w b b b 嗎?那我們干脆直接用 w w w b b b作表示吧,那不就是…”

J ( w , b ) = 1 m ∑ i = 1 m L ( y ( i ) , y ^ ( i ) ) J(w, b) = \frac{1}{m} \sum_{i=1}^{m} \text{L}(y^{(i)}, \hat{y}^{(i)}) J(w,b)=m1?i=1m?L(y(i),y^?(i))

這,就是損失函數(shù)(Cost Function / Loss Function)

在深度學(xué)習(xí)中,我們需要找合適的 w w w b b b,盡可能的縮小 J ( w , b ) J(w,b) J(w,b)

5.2 前向傳播

通過我們現(xiàn)在的知識(shí),可以構(gòu)建前向傳播了。

前向傳播(Forward Propagation): 是神經(jīng)網(wǎng)絡(luò)中的一個(gè)過程,其中輸入數(shù)據(jù)從輸入層流經(jīng)網(wǎng)絡(luò)的每一層,直到最后生成輸出。在這個(gè)過程中,每一層的神經(jīng)元接收上一層的輸出(對(duì)于第一層,接收輸入數(shù)據(jù)),并通過加權(quán)和以及激活函數(shù)產(chǎn)生該層的輸出。這些輸出隨后被傳遞到下一層,直至達(dá)到輸出層。

前向傳播的目的是基于當(dāng)前的參數(shù)(權(quán)重和偏置)和輸入數(shù)據(jù)來計(jì)算網(wǎng)絡(luò)的輸出。當(dāng)?shù)玫骄W(wǎng)絡(luò)的輸出之后,我們可以將它與真實(shí)的目標(biāo)或標(biāo)簽值進(jìn)行比較,從而計(jì)算損失。

代碼:

#前向傳播:計(jì)算損失
def propagate(w,b,X,Y):
#傳入的參數(shù):# w:權(quán)重向量,維度為[X.shape[0],1]#每一個(gè)元素的值隨機(jī)  參見初始化函數(shù)#w的第一個(gè)維度應(yīng)該等于X.shape[0],為什么?因?yàn)閣.T也就是[1,X.shape[0]]要X進(jìn)行點(diǎn)乘 參見線性回歸函數(shù)# b:偏差,一個(gè)常數(shù)# X:輸入的矩陣,當(dāng)前為 (12288, 209)# Y:標(biāo)簽矩陣 ,當(dāng)前為(1,209)
#返回的參數(shù)#cost:當(dāng)前一輪訓(xùn)練完成后,計(jì)算得到的損失值的平均,單個(gè)的點(diǎn)相較于決策邊界的成本的總和的平均m=X.shape[1] #X的第二個(gè)參數(shù),也就是樣本的總個(gè)數(shù)  #Z=w.T*X+b  #線性函數(shù)
A=sigmoid(np.dot(w.T,X)+b) #sigmoid函數(shù)(將線性函數(shù)集成了)
#此時(shí)這里A是一個(gè)矩陣,里面的內(nèi)容是模型的預(yù)測(cè)值#使用向量化以后的組合           
cost=(-1/m)*np.sum(Y*np.log(A) + (1-Y)*(np.log(1-A)))
#注意,因?yàn)橛?jì)算機(jī)的時(shí)候參與了Y矩陣,所以這個(gè)時(shí)候cost里面有一個(gè)下標(biāo)為1,對(duì)于Y(1,209)來說這個(gè)1是確保Y是一個(gè)矩陣,但是對(duì)于cost,這個(gè)1是無用的,我們需要移除
cost=np.squeeze(cost)    return cost

5.3 后向傳播

現(xiàn)在我們已經(jīng)知道了“損失”,我們便可以通過“損失”的大小來反向的調(diào)整 w w w b b b,使得 z = w T ? x + b z = w^T \cdot x + b z=wT?x+b 畫出來的決策邊界可以盡可能的擬合所有的點(diǎn)。

怎么做呢?

使用梯度下降

5.3.1 梯度下降算法

梯度下降算法它的公式為:

對(duì)于 w w w的更新:
1:求損失函數(shù) J J J關(guān)于權(quán)重 w w w的偏導(dǎo)數(shù)
? J ? w = 1 m X ( Y ^ ? Y ) T \frac{\partial J}{\partial w} = \frac{1}{m} X (\hat{Y} - Y)^T ?w?J?=m1?X(Y^?Y)T
2:新的 w w w等于當(dāng)前 w ? a w-a w?a倍的損失函數(shù) J J J關(guān)于權(quán)重 w w w的偏導(dǎo)數(shù)
w = w ? α ? J ? w w = w - \alpha \frac{\partial J}{\partial w} w=w?α?w?J?

對(duì)于 b b b的更新:
1:求損失函數(shù) J J J關(guān)于權(quán)重 b b b的偏導(dǎo)數(shù)
? J ? b = 1 m ∑ i = 1 m ( y ^ ( i ) ? y ( i ) ) \frac{\partial J}{\partial b} = \frac{1}{m} \sum_{i=1}^{m} (\hat{y}^{(i)} - y^{(i)}) ?b?J?=m1?i=1m?(y^?(i)?y(i))
2:新的 b b b等于當(dāng)前 b ? a b-a b?a倍的損失函數(shù) J J J關(guān)于權(quán)重 b b b的偏導(dǎo)數(shù)

b = b ? α ? J ? b b = b - \alpha \frac{\partial J}{\partial b} b=b?α?b?J?

這些公式,有興趣的小伙伴可以自行推導(dǎo)一下,方法很簡(jiǎn)單,使用鏈?zhǔn)椒▌t。

為什么要求導(dǎo)呢?為什么求導(dǎo)數(shù)可以反推呢?

別問,用就行。管它意大利的還是東北山里的,能響就好炮。

5.4 前向傳播和后向傳播完整代碼

結(jié)合前向傳播的片段,我們現(xiàn)在可以寫出本章完整的代碼

注意:由于我們還需要將學(xué)習(xí)率參與到運(yùn)算中,所以這個(gè)函數(shù)返回的是dw和db的需要更新多少,并不是真的已經(jīng)更新完的值。

def propagate(w,b,X,Y):#傳入的參數(shù):# w:權(quán)重向量,維度為[X.shape[0],1]#每一個(gè)元素的值隨機(jī)  參見初始化函數(shù)#w的第一個(gè)維度應(yīng)該等于X.shape[0],為什么?因?yàn)閣.T也就是[1,X.shape[0]]要X進(jìn)行點(diǎn)乘 參見線性回歸函數(shù)# b:偏差,一個(gè)常數(shù)# X:輸入的矩陣,當(dāng)前為 (12288, 209)# Y:標(biāo)簽矩陣 ,當(dāng)前為(1,209)#返回的參數(shù)#cost:當(dāng)前一輪訓(xùn)練完成后,計(jì)算得到的損失值的平均,單個(gè)的點(diǎn)相較于那條線的成本的總和的平均#dw:后向傳播以后,w需要改變多少#db:后向傳播以后,b需要改變多少m=X.shape[1] #X的第二個(gè)參數(shù),也就是樣本的總個(gè)數(shù)#前向傳播:也就是執(zhí)行一次邏輯回歸和損失計(jì)算,也就是執(zhí)行那三個(gè)函數(shù)#Z=w.T*X+b  #線性函數(shù)A=sigmoid(np.dot(w.T,X)+b) #sigmoid函數(shù)(將線性函數(shù)集成了)#此時(shí)這里A是一個(gè)矩陣,里面的內(nèi)容是模型的預(yù)測(cè)值#使用向量化以后的組合           cost=(-1/m)*np.sum(Y*np.log(A) + (1-Y)*(np.log(1-A)))#注意,因?yàn)橛?jì)算機(jī)的時(shí)候參與了Y矩陣,所以這個(gè)時(shí)候cost里面有一個(gè)下標(biāo)為1,對(duì)于Y(1,209)來說這個(gè)1是確保Y是一個(gè)矩陣,但是對(duì)于cost,這個(gè)1是無用的,我們需要移除cost=np.squeeze(cost)#反向傳播:(計(jì)算w和b需要改變多少)#為了計(jì)算w和b,我們需要使用梯度下降算法,它的公式是:# w= w - 學(xué)習(xí)率 * 損失函數(shù)對(duì)于w的導(dǎo)數(shù)dz=A-Ydw = (1/m) * np.dot(X,dz.T)db = (1/m) * np.sum(dz)#確保數(shù)據(jù)是否正確assert(dw.shape == w.shape)assert(db.dtype == float)#斷言會(huì)失敗,導(dǎo)致程序拋出一個(gè) AssertionError 異常。assert(cost.shape == ())#創(chuàng)建一個(gè)字典,把dw和db保存起來。grads={"dw":dw,"db":db}return (grads,cost)

六、代碼逐步擬合

現(xiàn)在,我們已經(jīng)有了實(shí)現(xiàn)所有功能的代碼,我們使用一些聚合函數(shù)將它們逐步聚合。

這樣做的好處有很多,最主要的是如果代碼出現(xiàn)問題,我們不用盯著一大塊代碼段查找bug…同時(shí),作為學(xué)習(xí)者,分塊寫代碼可以方便我們以后查閱和復(fù)習(xí)

6.1 運(yùn)行梯度下降更新w和b

#通過最最小化成本函數(shù)J來學(xué)習(xí)w和b
def optimize (w,b,X,Y,num_itertions,learning_rate,print_cost = False):# 此函數(shù)通過運(yùn)行梯度下降算法來優(yōu)化w和b# 參數(shù):#     w  - 權(quán)重,大小不等的數(shù)組(num_px * num_px * 3,1)#     b  - 偏差,一個(gè)標(biāo)量#     X  - 維度為(num_px * num_px * 3,訓(xùn)練數(shù)據(jù)的數(shù)量)的數(shù)組。#     Y  - 真正的“標(biāo)簽”矢量(如果非貓則為0,如果是貓則為1),矩陣維度為(1,訓(xùn)練數(shù)據(jù)的數(shù)量)#     num_iterations  - 優(yōu)化循環(huán)的迭代次數(shù)#     learning_rate  - 梯度下降更新規(guī)則的學(xué)習(xí)率,就是那個(gè)阿爾法#     print_cost  - 每100步打印一次損失值# 返回:#     params  - 包含權(quán)重w和偏差b的字典#     grads  - 包含權(quán)重和偏差相對(duì)于成本函數(shù)的梯度的字典#     成本 - 優(yōu)化期間計(jì)算的所有成本列表,將用于繪制學(xué)習(xí)曲線。# 提示:# 我們需要寫下兩個(gè)步驟并遍歷它們:#     1)計(jì)算當(dāng)前參數(shù)的成本和梯度,使用propagate()。#     2)使用w和b的梯度下降法則更新參數(shù)。costs=[]for i in range (num_itertions):grads, cost =propagate(w,b,X,Y)dw = grads["dw"]db = grads["db"]#公式w = w-learning_rate *dwb = b-learning_rate *db#記錄成本if i %100 ==0:costs.append(cost)#打印成本數(shù)據(jù)if (print_cost) and (i % 100 ==0):print("迭代的次數(shù): %i , 誤差值: %f" % (i,cost))#創(chuàng)建字典保存w和bparams={"w":w,"b":b}grads={"dw":dw,"db":db}return (params,grads,costs)# print("====================測(cè)試optimize====================")
# #([[1],[2]])一維的數(shù)組,有兩個(gè)元素[1]和[2]
# w,b,X,Y=np.array([[1],[2]]), 2 , np.array([[1,2],[3,4]]), np.array([[1,0]])
# params,grads,costs=optimize(w,b,X,Y,num_itertions=100,learning_rate = 0.009,print_cost = False)
# print ("w = " + str(params["w"]))
# print ("b = " + str(params["b"]))
# print ("dw = " + str(grads["dw"]))
# print ("db = " + str(grads["db"]))

6.2 實(shí)現(xiàn)預(yù)測(cè)函數(shù)(計(jì)算數(shù)據(jù)轉(zhuǎn)化的值)

現(xiàn)在,optimize函數(shù)會(huì)輸出已學(xué)習(xí)的w和b的值,我們可以使用w和b來預(yù)測(cè)數(shù)據(jù)集X的所生成的標(biāo)簽,預(yù)測(cè)標(biāo)簽是0還是1。

我們要實(shí)現(xiàn)預(yù)測(cè)函數(shù)。計(jì)算預(yù)測(cè)有兩個(gè)步驟:

1.計(jì)算 Y = A = σ ( w T X + b ) Y ^ = A = σ ( w^TX + b ) Y=A=σ(wTX+b)
2.選定sigmoid函數(shù)的閾值,將 a a a變?yōu)?(如果激活值<=0.5)或者1(如果激活值>0.5), a a a 表示神經(jīng)元的激活值, A A A 是sigmoid激活函數(shù) σ σ σ 的輸出矩陣。

def predict(w,b,X):#使用學(xué)習(xí)邏輯回歸參數(shù)logistic(w,b)預(yù)測(cè)標(biāo)簽是0還是1,# 參數(shù):#     w  - 權(quán)重,大小不等的數(shù)組(num_px * num_px * 3,1)#     b  - 偏差,一個(gè)標(biāo)量#     X  - 維度為(num_px * num_px * 3,訓(xùn)練數(shù)據(jù)的數(shù)量)的數(shù)組。# 返回:#   Y_prediction  - 包含X中所有圖片的所有預(yù)測(cè)【0 | 1】的一個(gè)numpy數(shù)組(向量)m=X.shape[1] #圖片的數(shù)量Y_prediction =np.zeros((1,m)) #創(chuàng)建都是0的矩陣(1行m列)w=w.reshape(X.shape[0],1) #將w轉(zhuǎn)為一個(gè)圖片參數(shù)的累乘,維度為1#預(yù)測(cè)貓?jiān)趫D片中出現(xiàn)的概率A=sigmoid(np.dot(w.T,X)+b)for i in range(A.shape[1]):#將概率a[0,1]轉(zhuǎn)化為實(shí)際預(yù)測(cè)的p[0.i]Y_prediction[0,i] = 1 if A[0,i] >0.5 else 0#使用斷言assert(Y_prediction.shape==(1,m))return Y_prediction    # print("====================測(cè)試predict====================")
# w, b, X, Y = np.array([[1], [2]]), 2, np.array([[1,2], [3,4]]), np.array([[1, 0]])
# print("predictions = " + str(predict(w, b, X)))

6.3 模型調(diào)用函數(shù)

就目前而言,我們基本上把所有的東西都做完了,現(xiàn)在我們要把這些函數(shù)統(tǒng)統(tǒng)整合到一個(gè)model()函數(shù)中,屆時(shí)只需要調(diào)用一個(gè)model()就基本上完成所有的事了。

def model(X_train , Y_train , X_test , Y_test , num_iterations = 2000 , learning_rate = 0.5 , print_cost = False):w , b = initialize_zeros(X_train.shape[0])parameters , grads , costs = optimize(w , b , X_train , Y_train,num_iterations , learning_rate , print_cost)#從字典“參數(shù)”中檢索參數(shù)w和bw , b = parameters["w"] , parameters["b"]#預(yù)測(cè)測(cè)試/訓(xùn)練集的例子Y_prediction_test = predict(w , b, X_test)Y_prediction_train = predict(w , b, X_train)#打印訓(xùn)練后的準(zhǔn)確性print("訓(xùn)練集準(zhǔn)確性:"  , format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100) ,"%")print("測(cè)試集準(zhǔn)確性:"  , format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100) ,"%")d = {"costs" : costs,"Y_prediction_test" : Y_prediction_test,"Y_prediciton_train" : Y_prediction_train,"w" : w,"b" : b,"learning_rate" : learning_rate,"num_iterations" : num_iterations }return d
# print("====================測(cè)試model====================")     
# #這里加載的是真實(shí)的數(shù)據(jù),請(qǐng)參見上面的代碼部分。
# d = model(train_set_x, train_set_y_orig, test_set_x, test_set_y_orig, num_iterations = 2000, learning_rate = 0.005, print_cost = True)
# #繪制圖
# costs = np.squeeze(d['costs'])
# plt.plot(costs)
# plt.ylabel('cost')
# plt.xlabel('iterations (per hundreds)')
# plt.title("Learning rate =" + str(d["learning_rate"]))
# plt.show()

6.4 完整代碼和測(cè)試

以下是完整代碼:

#所謂模型:就是一個(gè)(組)參數(shù)適合的公式
#所謂學(xué)習(xí):就是找那個(gè)合適的參數(shù)!#導(dǎo)入序列化必要函數(shù)
import numpy as np#導(dǎo)入生成圖片要的包
import matplotlib.pyplot as plt
# 是在 Python 中導(dǎo)入 matplotlib 庫(kù)的 pyplot 模塊并為其指定一個(gè)簡(jiǎn)稱 plt 的語(yǔ)句。matplotlib 是一個(gè)非常流行的 Python 數(shù)據(jù)可視化庫(kù),它提供了一套全面的繪圖工具來制作各種靜態(tài)、動(dòng)態(tài)或交互式的圖形。
# pyplot 是 matplotlib 的一個(gè)子模塊,通常被認(rèn)為是該庫(kù)的核心。它提供了一個(gè)類似于 MATLAB 的繪圖界面,使得創(chuàng)建圖形變得非常簡(jiǎn)單。#導(dǎo)入針對(duì)數(shù)據(jù)格式的包
import h5py
# import h5py 是 Python 中引入 h5py 庫(kù)的命令。
# h5py 是一個(gè) Python 庫(kù),它提供了一種高效的方式來讀取和寫入 HDF5 格式的文件。
# HDF5(Hierarchical Data Format version 5)是一個(gè)流行的數(shù)據(jù)存儲(chǔ)格式,常用于大型數(shù)據(jù)集,如科學(xué)計(jì)算或深度學(xué)習(xí)中的訓(xùn)練數(shù)據(jù)。
# HDF5 文件可以包含大量的數(shù)據(jù)集并支持高效的并行IO操作,它提供了一種結(jié)構(gòu)化的方式來存儲(chǔ)數(shù)據(jù),其中數(shù)據(jù)可以被組織為不同的組和數(shù)據(jù)集。#從lr_utils文件(或者稱為模塊,每一個(gè)py文件就是一個(gè)模塊)導(dǎo)入函數(shù)
from lr_utils import load_dataset#load_dataset函數(shù)是對(duì)訓(xùn)練集合和測(cè)試集合的預(yù)處理,并且已經(jīng)封裝好了,提取就可以
train_set_x_orig,train_set_y_orig,test_set_x_roig,test_set_y_orig,classes=load_dataset()#classes是一個(gè)字段,就是將 0 表示非貓("non-cat")圖片,1 表示貓("cat")文字說明#查看一下兩個(gè)數(shù)據(jù)集有多少數(shù)據(jù),幾個(gè)維度
"""
print(train_set_x_orig.shape) #(209, 64, 64, 3) 訓(xùn)練集:209行的后面那三個(gè)維度的矩陣
print(train_set_y_orig.shape) #(1, 209) 訓(xùn)練集標(biāo)簽:1行的209個(gè)數(shù)據(jù) 訓(xùn)練數(shù)據(jù)集是由209個(gè) 64*64的3色域圖片組成print(test_set_x_roig.shape) #(50, 64, 64, 3) 測(cè)試集50行的后面那三個(gè)維度的矩陣
print(test_set_y_orig.shape) #(1, 50) 測(cè)試集標(biāo)簽:1行的50個(gè)數(shù)據(jù)
"""#降低維度,改變數(shù)組的位置(轉(zhuǎn)置)
#匹配標(biāo)簽數(shù)據(jù)集和訓(xùn)練數(shù)據(jù)集的維度,將高維度的轉(zhuǎn)化為低緯度
#轉(zhuǎn)置是為了方便計(jì)算,把209放到后面,和標(biāo)簽一樣
#公式:將A(a,b,c,d)轉(zhuǎn)化為A(b*c*d,a)#X=X.reshape(X.shape[0],-1).T#X=X.reshape()  重塑數(shù)組的維度#(A,B)二維數(shù)組#X.shape[0] 第一個(gè)維度不變#-1在reshape方法中有一個(gè)特殊的意義。它表示該維度的大小應(yīng)當(dāng)被自動(dòng)推斷,以保證總元素?cái)?shù)不變。#為了計(jì)算-1應(yīng)該被替代的值,numpy會(huì)使用以下方法:#總元素?cái)?shù) / 已知的其他維度的大小 = 未知維度的大小#在A(m,n,o)中,原始數(shù)組的總元素?cái)?shù)是m * n * o。已知的其他維度的大小是m。所以,-1會(huì)被計(jì)算為(m * n * o) / m = n * o。#因此,形狀為(m, n, o)的三維數(shù)組會(huì)被重新形狀為(m, n*o)的二維數(shù)組。#.T 二維數(shù)組前后交換
# #測(cè)試
# a=np.random.rand(5,2,3)#創(chuàng)建[5,2,3]維度的數(shù)組,用隨機(jī)數(shù)填滿
# print(a.shape) #(5, 2, 3)
# print((a.reshape(a.shape[0],-1).T).shape) #[6,5]#print(train_set_x_orig.shape) #(209, 64, 64, 3)
train_set_x_flatten=train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T #(12288, 209)
# print(train_set_x_flatten.shape)# print(test_set_x_roig.shape)#(50, 64, 64, 3)
test_set_x_flatten=test_set_x_roig.reshape(test_set_x_roig.shape[0],-1).T #(12288, 50)
# print(test_set_x_flatten.shape)#將數(shù)據(jù)集中化和標(biāo)準(zhǔn)化,因?yàn)槎际菆D片數(shù)據(jù),所以可以除以255,將每個(gè)數(shù)據(jù)控制到[0,1]之間
train_set_x=train_set_x_flatten/255
# print(train_set_x.shape)#數(shù)據(jù)的維度還是沒變(12288, 209)
test_set_x=test_set_x_flatten/255#數(shù)據(jù)處理的部分完成了,接下來就是構(gòu)建神經(jīng)網(wǎng)絡(luò)#我們要處理的是二分類問題,而“邏輯回歸”是處理二分問題的一個(gè)算法#邏輯回歸,實(shí)際上是找到一個(gè)決策邊界,然后根據(jù)樣本點(diǎn)相對(duì)于這個(gè)邊界的位置來分類,對(duì)于線性邏輯回歸,這個(gè)決策邊界是一條直線(在二維空間中)或一個(gè)超平面(在更高的維度中),這取決于特征的數(shù)量。#邏輯回歸函數(shù)=線性回歸函數(shù)+sigmoid函數(shù),所以我們需要兩個(gè)函數(shù)#1.線性回歸函數(shù):Z = z^(i) = w.T ? x^(i)+b# x^(i):第i個(gè)樣本的特征向量# w:權(quán)重向量,表示當(dāng)前x^(i)的權(quán)重比(權(quán)重用于決定決策邊界怎么畫)# w.T是w的轉(zhuǎn)置,我們?yōu)榱擞?jì)算w與x的“點(diǎn)乘”,要求w的行向量 == x的列向量# 如果你的 w 向量本來就是一個(gè)行向量,并且它的長(zhǎng)度(列數(shù))與 x 向量的長(zhǎng)度(行數(shù))相同,不需要再進(jìn)行轉(zhuǎn)置,但是,權(quán)重向量和特征向量通常都被定義為列向量,這是一種約束。#b: 這是偏置項(xiàng),它是一個(gè)常數(shù)#z^(i):第i個(gè)樣本的線性輸出。輸入一個(gè)x^(i),在當(dāng)前函數(shù)中,得到一個(gè)z(i)#2.sigmoid函數(shù):a=1/1+e^(-Z) //其中的Z是線性回歸函數(shù)#是一種激活函數(shù)#輸出范圍:[0,1]#擬合,實(shí)際上是指盡量減少誤分類的數(shù)量,總有一些點(diǎn)無法分類,而我們需要找到可以盡可能的滿足多點(diǎn)的決策邊界,所以我們需要是最小化邏輯回歸的損失函數(shù)(通常是對(duì)數(shù)損失函數(shù)或交叉熵?fù)p失函數(shù))#所以我們還需要一個(gè)損失函數(shù)參數(shù):#L(a^(i),y^(i) = -y^(i)*log(a^(i)) - (1-y^(i))*log(1-a^(i))#最后,我們需要一個(gè)對(duì)于所有數(shù)據(jù)的損失求和的函數(shù):假設(shè)所有數(shù)據(jù)一共有m個(gè)# J=1/m * m∑(i=1)* L(a^(i),y^(i))#構(gòu)建sigmoid函數(shù)
def sigmoid(z):a=1/(1+np.exp(-z))return a#初始化函數(shù)
#主要用于構(gòu)建w和b,之前看到的方法是創(chuàng)建一個(gè)(dim,1)維度的0向量# w=np.zeros(shape=(dim,1))#但是這樣也許會(huì)導(dǎo)致一個(gè)“對(duì)稱性”問題#當(dāng)你這樣初始化權(quán)重并使用它們?cè)谏窠?jīng)網(wǎng)絡(luò)中時(shí),每一層的所有神經(jīng)元都會(huì)有相同的輸出。#因此,當(dāng)你進(jìn)行反向傳播時(shí),所有神經(jīng)元都會(huì)收到相同的梯度。這將導(dǎo)致所有的權(quán)重都更新為相同的值。無論網(wǎng)絡(luò)有多少神經(jīng)元,它們都會(huì)表現(xiàn)得像一個(gè)神經(jīng)元,這極大地限制了網(wǎng)絡(luò)的容量和表達(dá)能力。def initialize_zeros(dim):#dim:傳入的數(shù)據(jù)集的第一個(gè)向量坐標(biāo),X.shape[0]#w=np.zeros(shape=(dim,1))w=0.01*np.random.rand(dim,1)#乘以0.01是為了確保初始化的權(quán)重值很小。b=0#使用斷言來檢測(cè)是正確assert(w.shape==(dim,1))assert(isinstance(b,float) or isinstance(b,int))return (w,b)#構(gòu)建邏輯回歸的前向傳播和后向傳播#神經(jīng)網(wǎng)絡(luò)或者深度學(xué)習(xí)模型單次的訓(xùn)練過程有四個(gè)階段:#1.前向傳播:給當(dāng)前數(shù)據(jù)x^(i),根據(jù)算法(當(dāng)前我們用的是sigmoid函數(shù))輸出一個(gè)結(jié)果[sigmoid的范圍是[0,1]]#2.計(jì)算機(jī)損失:得到前向傳播的數(shù)據(jù)(預(yù)測(cè))以后,我們會(huì)評(píng)估“預(yù)測(cè)與我們給定的標(biāo)簽y^(i)”之間的差異。這個(gè)差異(通常稱為“損失”或“誤差”)#3.后向傳播:基于前面計(jì)算的損失,模型會(huì)計(jì)算每個(gè)參數(shù)的梯度,以知道如何更好地更新參數(shù)來提高預(yù)測(cè)。這個(gè)步驟就是告訴模型:“為了減少預(yù)測(cè)誤差,你應(yīng)該這樣調(diào)整你的參數(shù)w和b?!?/span>#4.更新參數(shù): 在知道了如何更新參數(shù)之后,實(shí)際更新參數(shù)。#構(gòu)建實(shí)現(xiàn)上述功能的函數(shù)(漸變函數(shù))
def propagate(w,b,X,Y):#傳入的參數(shù):# w:權(quán)重向量,維度為[X.shape[0],1]#每一個(gè)元素的值隨機(jī)  參見初始化函數(shù)#w的第一個(gè)維度應(yīng)該等于X.shape[0],為什么?因?yàn)閣.T也就是[1,X.shape[0]]要X進(jìn)行點(diǎn)乘 參見線性回歸函數(shù)# b:偏差,一個(gè)常數(shù)# X:輸入的矩陣,當(dāng)前為 (12288, 209)# Y:標(biāo)簽矩陣 ,當(dāng)前為(1,209)#返回的參數(shù)#cost:當(dāng)前一輪訓(xùn)練完成后,計(jì)算得到的損失值的平均,單個(gè)的點(diǎn)相較于那條線的成本的總和的平均#dw:后向傳播以后,w需要改變多少#db:后向傳播以后,b需要改變多少m=X.shape[1] #X的第二個(gè)參數(shù),也就是樣本的總個(gè)數(shù)#前向傳播:也就是執(zhí)行一次邏輯回歸和損失計(jì)算,也就是執(zhí)行那三個(gè)函數(shù)#Z=w.T*X+b  #線性函數(shù)A=sigmoid(np.dot(w.T,X)+b) #sigmoid函數(shù)(將線性函數(shù)集成了)#此時(shí)這里A是一個(gè)矩陣,里面的內(nèi)容是模型的預(yù)測(cè)值#使用向量化以后的組合           cost=(-1/m)*np.sum(Y*np.log(A) + (1-Y)*(np.log(1-A)))#注意,因?yàn)橛?jì)算機(jī)的時(shí)候參與了Y矩陣,所以這個(gè)時(shí)候cost里面有一個(gè)下標(biāo)為1,對(duì)于Y(1,209)來說這個(gè)1是確保Y是一個(gè)矩陣,但是對(duì)于cost,這個(gè)1是無用的,我們需要移除cost=np.squeeze(cost)#反向傳播:(計(jì)算w和b需要改變多少)#為了計(jì)算w和b,我們需要使用梯度下降算法,它的公式是:# w= w - 學(xué)習(xí)率 * 損失函數(shù)對(duì)于w的導(dǎo)數(shù)dz=A-Ydw = (1/m) * np.dot(X,dz.T)db = (1/m) * np.sum(dz)#確保數(shù)據(jù)是否正確assert(dw.shape == w.shape)assert(db.dtype == float)#斷言會(huì)失敗,導(dǎo)致程序拋出一個(gè) AssertionError 異常。assert(cost.shape == ())#創(chuàng)建一個(gè)字典,把dw和db保存起來。grads={"dw":dw,"db":db}return (grads,cost)#通過最最小化成本函數(shù)J來學(xué)習(xí)w和b
def optimize (w,b,X,Y,num_itertions,learning_rate,print_cost = False):# 此函數(shù)通過運(yùn)行梯度下降算法來優(yōu)化w和b# 參數(shù):#     w  - 權(quán)重,大小不等的數(shù)組(num_px * num_px * 3,1)#     b  - 偏差,一個(gè)標(biāo)量#     X  - 維度為(num_px * num_px * 3,訓(xùn)練數(shù)據(jù)的數(shù)量)的數(shù)組。#     Y  - 真正的“標(biāo)簽”矢量(如果非貓則為0,如果是貓則為1),矩陣維度為(1,訓(xùn)練數(shù)據(jù)的數(shù)量)#     num_iterations  - 優(yōu)化循環(huán)的迭代次數(shù)#     learning_rate  - 梯度下降更新規(guī)則的學(xué)習(xí)率,就是那個(gè)阿爾法#     print_cost  - 每100步打印一次損失值# 返回:#     params  - 包含權(quán)重w和偏差b的字典#     grads  - 包含權(quán)重和偏差相對(duì)于成本函數(shù)的梯度的字典#     成本 - 優(yōu)化期間計(jì)算的所有成本列表,將用于繪制學(xué)習(xí)曲線。# 提示:# 我們需要寫下兩個(gè)步驟并遍歷它們:#     1)計(jì)算當(dāng)前參數(shù)的成本和梯度,使用propagate()。#     2)使用w和b的梯度下降法則更新參數(shù)。costs=[]for i in range (num_itertions):grads, cost =propagate(w,b,X,Y)dw = grads["dw"]db = grads["db"]#公式w = w-learning_rate *dwb = b-learning_rate *db#記錄成本if i %100 ==0:costs.append(cost)#打印成本數(shù)據(jù)if (print_cost) and (i % 100 ==0):print("迭代的次數(shù): %i , 誤差值: %f" % (i,cost))#創(chuàng)建字典保存w和bparams={"w":w,"b":b}grads={"dw":dw,"db":db}return (params,grads,costs)# print("====================測(cè)試optimize====================")
# #([[1],[2]])一維的數(shù)組,有兩個(gè)元素[1]和[2]
# w,b,X,Y=np.array([[1],[2]]), 2 , np.array([[1,2],[3,4]]), np.array([[1,0]])
# params,grads,costs=optimize(w,b,X,Y,num_itertions=100,learning_rate = 0.009,print_cost = False)
# print ("w = " + str(params["w"]))
# print ("b = " + str(params["b"]))
# print ("dw = " + str(grads["dw"]))
# print ("db = " + str(grads["db"]))def predict(w,b,X):#使用學(xué)習(xí)邏輯回歸參數(shù)logistic(w,b)預(yù)測(cè)標(biāo)簽是0還是1,# 參數(shù):#     w  - 權(quán)重,大小不等的數(shù)組(num_px * num_px * 3,1)#     b  - 偏差,一個(gè)標(biāo)量#     X  - 維度為(num_px * num_px * 3,訓(xùn)練數(shù)據(jù)的數(shù)量)的數(shù)組。# 返回:#   Y_prediction  - 包含X中所有圖片的所有預(yù)測(cè)【0 | 1】的一個(gè)numpy數(shù)組(向量)m=X.shape[1] #圖片的數(shù)量Y_prediction =np.zeros((1,m)) #創(chuàng)建都是0的矩陣(1行m列)w=w.reshape(X.shape[0],1) #將w轉(zhuǎn)為一個(gè)圖片參數(shù)的累乘,維度為1#預(yù)測(cè)貓?jiān)趫D片中出現(xiàn)的概率A=sigmoid(np.dot(w.T,X)+b)for i in range(A.shape[1]):#將概率a[0,1]轉(zhuǎn)化為實(shí)際預(yù)測(cè)的p[0.i]Y_prediction[0,i] = 1 if A[0,i] >0.5 else 0#使用斷言assert(Y_prediction.shape==(1,m))return Y_prediction    # def model(X_train,Y_train,X_test,Y_test, num_iterations=2000,learning_rate =0.005, print_cost=False):#     #參數(shù):
#        # X_train   -numpy的數(shù)組,維度為(num_px*num_px*3,m_train)的訓(xùn)練集 
#        # Y_train   -numpy的數(shù)組,維度為(1,m_train)(標(biāo)簽)(矢量)的訓(xùn)練集合#        # X_test   -numpy的數(shù)組,維度為(num_px*num_px*3,m_test)的測(cè)試集 
#        # Y_test   -numpy的數(shù)組,維度為(1,m_test)(標(biāo)簽)(矢量)的測(cè)試集合#        # num_iterations - 用于優(yōu)化參數(shù)的迭代次數(shù)
#        # learning_rate --學(xué)習(xí)率
#        # print_cost  - 設(shè)置為true以每100次迭代打印成本#     #返回
#        #d -包含模型信息的字典#     w,b=initialize_zeros(X_train.shape[0])   #初始化w和b,根據(jù)訓(xùn)練集合的第一個(gè)參數(shù)(那一堆東西)#     parameters,grads,costs=optimize(w,b,X_train,Y_train,num_iterations,learning_rate,print_cost)#     #從字典“參數(shù)”中檢索參數(shù)w和b
#     w,b = parameters["w"],parameters["b"]#     #預(yù)測(cè)測(cè)試/訓(xùn)練集的例子#     Y_prediction_test =predict(w,b,X_test)
#     Y_prediction_train=predict(w,b,X_train)#     #打印
#     #用于計(jì)算數(shù)據(jù)的平均值:np.mean()
#     print("訓(xùn)練集的準(zhǔn)確度:",format(100-np.mean(np.abs(Y_prediction_train-Y_train))*100),"%")
#     print("測(cè)試集的準(zhǔn)確度:",format(100-np.mean(np.abs(Y_prediction_test-Y_test))*100),"%")#     d = {
#             "costs" : costs,
#             "Y_prediction_test" : Y_prediction_test,
#             "Y_prediciton_train" : Y_prediction_train,
#             "w" : w,
#             "b" : b,
#             "learning_rate" : learning_rate,
#             "num_iterations" : num_iterations }
#     return d# print("====================測(cè)試model====================")    # d1=model(train_set_x,train_set_y_orig,test_set_x,test_set_y_orig,num_iterations =2000,learning_rate =0.01,print_cost=True)
# d2=model(train_set_x,train_set_y_orig,test_set_x,test_set_y_orig,num_iterations =2000,learning_rate =0.001,print_cost=True)
# d3=model(train_set_x,train_set_y_orig,test_set_x,test_set_y_orig,num_iterations =2000,learning_rate =0.0001,print_cost=True)# #繪圖
# costs1=np.squeeze(d1['costs'])
# plt.plot(costs1)
# costs2=np.squeeze(d2['costs'])
# plt.plot(costs2)
# costs3=np.squeeze(d3['costs'])
# plt.plot(costs3)# plt.ylabel('cost')
# plt.xlabel(('iterations (per hundreds)'))
# plt.title("Learning rate =" + str(d1["learning_rate"])+str(d2["learning_rate"])+str(d3["learning_rate"]))
# plt.show()def model(X_train , Y_train , X_test , Y_test , num_iterations = 2000 , learning_rate = 0.5 , print_cost = False):w , b = initialize_zeros(X_train.shape[0])parameters , grads , costs = optimize(w , b , X_train , Y_train,num_iterations , learning_rate , print_cost)#從字典“參數(shù)”中檢索參數(shù)w和bw , b = parameters["w"] , parameters["b"]#預(yù)測(cè)測(cè)試/訓(xùn)練集的例子Y_prediction_test = predict(w , b, X_test)Y_prediction_train = predict(w , b, X_train)#打印訓(xùn)練后的準(zhǔn)確性print("訓(xùn)練集準(zhǔn)確性:"  , format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100) ,"%")print("測(cè)試集準(zhǔn)確性:"  , format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100) ,"%")d = {"costs" : costs,"Y_prediction_test" : Y_prediction_test,"Y_prediciton_train" : Y_prediction_train,"w" : w,"b" : b,"learning_rate" : learning_rate,"num_iterations" : num_iterations }return dprint("====================測(cè)試model====================")     
#這里加載的是真實(shí)的數(shù)據(jù),請(qǐng)參見上面的代碼部分。
d = model(train_set_x, train_set_y_orig, test_set_x, test_set_y_orig, num_iterations = 2000, learning_rate = 0.005, print_cost = True)
#繪制圖
costs = np.squeeze(d['costs'])
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations (per hundreds)')
plt.title("Learning rate =" + str(d["learning_rate"]))
plt.show()

最后,我們得到了這樣的結(jié)果和圖片
在這里插入圖片描述

6.5 再玩一下?好的!

讓我們最后修改一下學(xué)習(xí)率,看看會(huì)有什么樣的變化

如果你也想玩,替換最后的打印語(yǔ)句即可:

print("====================測(cè)試model====================")    d1=model(train_set_x,train_set_y_orig,test_set_x,test_set_y_orig,num_iterations =2000,learning_rate =0.01,print_cost=True)
d2=model(train_set_x,train_set_y_orig,test_set_x,test_set_y_orig,num_iterations =2000,learning_rate =0.001,print_cost=True)
d3=model(train_set_x,train_set_y_orig,test_set_x,test_set_y_orig,num_iterations =2000,learning_rate =0.0001,print_cost=True)#繪圖
costs1=np.squeeze(d1['costs'])
plt.plot(costs1)
costs2=np.squeeze(d2['costs'])
plt.plot(costs2)
costs3=np.squeeze(d3['costs'])
plt.plot(costs3)plt.ylabel('cost')
plt.xlabel(('iterations (per hundreds)'))
plt.title("Learning rate1 =" + str(d1["learning_rate"])+'\n'+"Learning rate2 =" + str(d2["learning_rate"])+'\n'+"Learning rate2 =" + str(d2["learning_rate"]))
plt.show()

得到的結(jié)果是這樣滴!

在這里插入圖片描述

為什么呢?
學(xué)習(xí)率會(huì)有影響
我知道,為什么會(huì)這樣呢?
你猜?

寫在后面的話

這應(yīng)該是我注冊(cè)CSDN以來寫的最暢快的一片博客。

對(duì)于標(biāo)題:《打開深度學(xué)習(xí)的鎖》,其實(shí)有很多自負(fù),我甚至連那扇門都沒有看到…但我依然感覺的到,我解開了一些東西,這種感覺很舒服,也很自豪。

好似小學(xué)課堂上,我第一次解開方程組,老師獎(jiǎng)勵(lì)的那塊糖。那顆糖打開了我喜歡數(shù)學(xué)的門,而這道題,打開我對(duì)于深度學(xué)習(xí)的那把鎖,以此,暢快!。

很久沒有寫博客了。為什么不寫呢?原因很多:沒時(shí)間、沒心氣、沒東西.

寫博客曾經(jīng)是我學(xué)習(xí)的一種的方式,本人比較笨,也比較懶,對(duì)于一個(gè)知識(shí)點(diǎn),往往需要很長(zhǎng)的周期才可以掌握。但我依然希望沉淀一點(diǎn)東西,然后寫下來。保留這份難得沉下心,這個(gè)為了一個(gè)目標(biāo)的渴望與完成時(shí)的激動(dòng)。

在未來的某個(gè)時(shí)段,作為引子,以供以后的自己檢索回憶。

也可看自己是增是減。

我曾經(jīng)寫過很多沒用的東西,但就是這些東西記錄了當(dāng)年那個(gè)小小的自己,自顧自的向前走,時(shí)不時(shí)跌到、頹廢、崩潰、抑郁、焦慮、然后起身、振作、自我調(diào)節(jié)、繼續(xù)行走。如今回到看,那個(gè)少年也走出了一條窄窄的路。

那個(gè)孩子,仍然在以自己的方式——迎接自己渴望的歡呼,承受自己唾棄的鄙夷,走下去。

郝佳順
2023年9月9日
于韓國(guó)慶北大學(xué)

http://www.risenshineclean.com/news/54727.html

相關(guān)文章:

  • 找人做網(wǎng)站做的很爛seo診斷服務(wù)
  • 網(wǎng)站運(yùn)營(yíng)托管協(xié)議杭州網(wǎng)絡(luò)優(yōu)化公司排名
  • 武漢做網(wǎng)站的公司有哪些比較好友情鏈接也稱為
  • 糧食局網(wǎng)站建設(shè)報(bào)告網(wǎng)紅推廣
  • 清遠(yuǎn)黨風(fēng)廉政建設(shè)網(wǎng)站不受限制的搜索瀏覽器
  • 做網(wǎng)站每年要交不費(fèi)用嗎石家莊seo公司
  • 設(shè)計(jì)網(wǎng)站賣錢seo百度點(diǎn)擊軟件
  • 網(wǎng)站關(guān)鍵字標(biāo)簽最新seo操作
  • 海南城鄉(xiāng)建設(shè)庁網(wǎng)站色盲測(cè)試圖第六版
  • 圖片制作網(wǎng)頁(yè)關(guān)于進(jìn)一步優(yōu)化落實(shí)疫情防控措施
  • 網(wǎng)站被墻了怎么辦百度推廣合作
  • 長(zhǎng)沙專業(yè)網(wǎng)站設(shè)計(jì)2023年小學(xué)生簡(jiǎn)短小新聞
  • ssp媒體服怎樣做網(wǎng)站搭建一個(gè)網(wǎng)站
  • 鄭州網(wǎng)站建設(shè)gusai123護(hù)膚品軟文推廣
  • 北京模板網(wǎng)站開發(fā)品牌軟文范文
  • 招商網(wǎng)站大全seo技術(shù)推廣
  • 樣板網(wǎng)站看b站視頻下載軟件
  • 創(chuàng)建網(wǎng)站的向?qū)Ш湍0搴馑畇eo營(yíng)銷
  • b2c 電子商務(wù)網(wǎng)站的經(jīng)營(yíng)特點(diǎn)百度提升優(yōu)化
  • 棋類游戲網(wǎng)站開發(fā)游戲優(yōu)化是什么意思?
  • 團(tuán)購(gòu)網(wǎng)站前景新聞熱搜榜 今日熱點(diǎn)
  • 保定網(wǎng)站開發(fā)公司學(xué)做網(wǎng)站培訓(xùn)班要多少錢
  • 北流網(wǎng)站建設(shè)培訓(xùn)班招生方案
  • 公眾號(hào)免費(fèi)素材網(wǎng)站2023年6月份疫情嚴(yán)重嗎
  • 營(yíng)銷型網(wǎng)站建設(shè)公司易網(wǎng)拓線上推廣渠道有哪些方式
  • 織夢(mèng)動(dòng)漫網(wǎng)站模版深圳網(wǎng)頁(yè)搜索排名提升
  • 網(wǎng)站推廣工具大全網(wǎng)站改版seo建議
  • 兼職做任務(wù)賺錢的網(wǎng)站有哪些aso優(yōu)化平臺(tái)有哪些
  • 阿里云虛擬主機(jī)網(wǎng)站嗎東莞百度seo在哪里
  • 蘇州做網(wǎng)站最好公司寧波靠譜營(yíng)銷型網(wǎng)站建設(shè)