丝袜人妻一区二区三区_少妇福利无码视频_亚洲理论片在线观看_一级毛片国产A级片

當(dāng)前位置:首頁 > 房產(chǎn)信息

mxnet 深度學(xué)習(xí)高能干貨:手把手教你搭建MXNet框架

簡(jiǎn)介:我相信在學(xué)習(xí)一門新的編程語言或框架時(shí),很多程序員首先會(huì)理解語言或框架所涉及的數(shù)據(jù)結(jié)構(gòu)。畢竟,當(dāng)你清楚地理解了數(shù)據(jù)結(jié)構(gòu),你就可以更優(yōu)雅地編寫代碼,MXNet也是如此。

在MXNet框架中,你至少需要知道三駕馬車:NDArray、Symbol、Module。這三個(gè)將是您在將來使用MXNet框架時(shí)經(jīng)常使用的接口。那么這三者在構(gòu)建或訓(xùn)練一個(gè)深度學(xué)習(xí)算法的時(shí)候起到什么樣的作用呢?

這里可以做一個(gè)簡(jiǎn)單的類比。如果把從建筑到訓(xùn)練算法的過程比作從建筑到裝修房子的過程,那么NDArray相當(dāng)于鋼筋混凝土之類的零件,Symbol相當(dāng)于房子每一層的設(shè)計(jì),Module相當(dāng)于房子整體框架的搭建。

在本文中,您將實(shí)際感受到命令式編程和符號(hào)式編程的區(qū)別,因?yàn)镹DArray接口使用命令式編程,而符號(hào)式接口使用符號(hào)式編程。

如需轉(zhuǎn)載,請(qǐng)聯(lián)系大數(shù)據(jù)(ID: hzdashuju)

01 NDArray

NDArray是MXNet框架中數(shù)據(jù)流的基本結(jié)構(gòu),NDArray的公文地址為:

https://mxnet.apache.org/api/python/ndarray/ndarray.html

在本文檔中可以找到與陣列相關(guān)的所有接口。在了解NDArray之前,希望你知道Python中的NumPy庫:

http://www.numpy.org/

因?yàn)橐环矫?,在大多?shù)深度學(xué)習(xí)框架的Python接口中,NumPy庫的使用非常頻繁;另一方面,NumPy在大多數(shù)深度學(xué)習(xí)框架的基本數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)中被借鑒。

在NumPy庫中,最基本的數(shù)據(jù)結(jié)構(gòu)之一是數(shù)組,它代表多維數(shù)組。NDArray的用法與NumPy庫中的數(shù)組數(shù)據(jù)結(jié)構(gòu)非常相似,所以可以簡(jiǎn)單地認(rèn)為它是可以在GPU上運(yùn)行的NumPy數(shù)組。

接下來我會(huì)介紹一下NDArray中的一些常見操作,并提供NDArray和NumPy數(shù)組的一個(gè)比較,方便讀者了解兩者之間的關(guān)系。

首先導(dǎo)入MXNet和NumPy,然后通過NDArray初始化一個(gè)二維矩陣。代碼如下:

importmxnet asmx

importnumpy asnp

a = mx.nd.array([[ 1,2],[ 3,4]])

打印(a)

輸出結(jié)果如下:

[[ 1.2.]

[ 3.4.]]

& ltn數(shù)組2x2 @cpu( 0)>;

然后用NumPy數(shù)組初始化一個(gè)相同的二維矩陣,代碼如下:

b = np.array([[ 1,2],[ 3,4]])

打印(b)

輸出結(jié)果如下:

[[ 12]

[ 34]]

實(shí)際使用中,縮寫mx代替mxnet,mx.nd代替mxnet.ndarray,np代替numpy,本書后續(xù)章節(jié)涉及的所有代碼默認(rèn)采用此類縮寫。

我們來看看NumPy數(shù)組和NDArray常用的幾種方法的比較,比如打印NDArray的維度信息:

打印(a.shape)

輸出結(jié)果如下:

( 2, 2)

要打印數(shù)值數(shù)組的尺寸信息:

打印(b.shape)

輸出結(jié)果如下:

( 2, 2)

要打印數(shù)組的數(shù)字類型:

打印(a.dtype)

輸出結(jié)果如下:

& ltclass'numpy.float32 ' >;

要打印Numpy數(shù)組的數(shù)字類型:

打印(b.dtype)

輸出結(jié)果如下:

int64

當(dāng)大多數(shù)深度學(xué)習(xí)框架用于訓(xùn)練模型時(shí),默認(rèn)情況下采用float32數(shù)值類型,因此初始化NDArray對(duì)象時(shí),默認(rèn)的數(shù)值類型是float32。

如果要初始化指定數(shù)值類型的數(shù)組,可以通過dtype參數(shù)指定,代碼如下:

c=mx.nd.array([[ 1,2],[ 3,4]],dt type = NP . int 8)

打印(c.dtype)

輸出結(jié)果如下:

& ltclass'numpy.int8 ' >

如果要初始化指定數(shù)值類型的NumPy數(shù)組,可以輸入如下代碼:

d = np.array([[ 1,2],[ 3,4]],dtype=np.int8)

打印(d.dtype)

輸出結(jié)果如下:

int8

NumPy的數(shù)組結(jié)構(gòu)中一個(gè)非常常見的操作是slice,它也可以在NDArray中實(shí)現(xiàn)。具體代碼如下:

c = mx.nd.array([[ 1,2,3,4],[ 5,6,7,8]])

打印(c[ 0,1: 3])

輸出結(jié)果如下:

[ 2.3.]

& ltNDArray 2@cpu( 0)>;

在NumPy陣列中,可以按如下方式實(shí)現(xiàn):

d = np.array([[ 1,2,3,4],[ 5,6,7,8]])

打印(d[ 0,1: 3])

輸出結(jié)果如下:

[ 23]

在復(fù)制和修改現(xiàn)有的NumPy數(shù)組或NDArray時(shí),為了避免影響原始數(shù)組,通過copy()復(fù)制數(shù)組而不是直接復(fù)制數(shù)組是非常重要的。讓我們以NDArray為例,看看如何使用copy()方法復(fù)制數(shù)組。首先打印出C的內(nèi)容:

打印(c)

輸出結(jié)果如下:

[[ 1.2.3.4.]

[ 5.6.7.8.]]

& ltn數(shù)組2x4 @cpu( 0)>;

然后調(diào)用c的copy()方法將c的內(nèi)容復(fù)制到f,打印f的內(nèi)容:

f = c.copy()

打印(f)

輸出結(jié)果如下:

[[ 1.2.3.4.]

[ 5.6.7.8.]]

& ltn數(shù)組2x4 @cpu( 0)>;

修改f中的一個(gè)值并打印f的內(nèi)容:

f[ 0,0] = -1

打印(f)

輸出結(jié)果如下,可以看到對(duì)應(yīng)位置的值被修改了:

[[ -1.2.3.4.]

[ 5.6.7.8.]]

& ltn數(shù)組2x4 @cpu( 0)>;

那么C中對(duì)應(yīng)位置的值修改了嗎?此時(shí)可以打印c的內(nèi)容:

打印(c)

輸出結(jié)果如下,可以看出此時(shí)C中對(duì)應(yīng)位置的值沒有修改:

[[ 1.2.3.4.]

[ 5.6.7.8.]]

& ltn數(shù)組2x4 @cpu( 0)>;

接下來,讓我們看看如果直接將C復(fù)制到E會(huì)發(fā)生什么:

e = c

打印(e)

輸出結(jié)果如下:

[[ 1.2.3.4.]

[ 5.6.7.8.]]

& ltn數(shù)組2x4 @cpu( 0)>;

在E中修改一個(gè)值,打印E的內(nèi)容:

e[ 0,0] = -1

打印(e)

輸出如下:

[[ -1.2.3.4.]

[ 5.6.7.8.]]

& ltn數(shù)組2x4 @cpu( 0)>;

這時(shí),打印c:

打印(c)

輸出結(jié)果如下,可以看到對(duì)應(yīng)位置的值也發(fā)生了變化:

[[ -1.2.3.4.]

[ 5.6.7.8.]]

& ltn數(shù)組2x4 @cpu( 0)>;

其實(shí)NumPy數(shù)組和NDArray的轉(zhuǎn)換也很方便,NDArray到NumPy數(shù)組的轉(zhuǎn)換可以通過調(diào)用NDArray對(duì)象的asnumpy()方法來實(shí)現(xiàn):

g=e.asnumpy()

打印(g)

輸出結(jié)果如下:

[[ -1.2.3.4.]

[ 5.6.7.8.]]

通過mxnet . NDArray . array()接口可以實(shí)現(xiàn)將NumPy數(shù)組轉(zhuǎn)移到ndaarray:

print(mx.nd.array(g))

輸出結(jié)果如下:

[[ -1.2.3.4.]

[ 5.6.7.8.]]

& ltn數(shù)組2x4 @cpu( 0)>;?

前面說過,NDArray和NumPy數(shù)組最大的區(qū)別就是NDArray可以在GPU上運(yùn)行。從打印出來的NDArray對(duì)象的內(nèi)容可以看出,最后有一個(gè)@cpu,說明NDArray對(duì)象是在cpu上初始化的。那么如何在GPU上初始化NDArray對(duì)象呢?首先,調(diào)用NDArray對(duì)象的上下文屬性來獲取變量所在的環(huán)境:

打印(e.context)

輸出結(jié)果如下:

cpu( 0)

然后,調(diào)用NDArray對(duì)象的as_in_context()方法指定變量的環(huán)境,例如,這里環(huán)境指定為第0個(gè)GPU:

e = e.as_in_context(mx.gpu( 0))

打印(e.context)

輸出結(jié)果如下:

gpu( 0)

上下文是深度學(xué)習(xí)算法的重要內(nèi)容。目前常用的環(huán)境是CPU或者GPU。在深度學(xué)習(xí)算法中,數(shù)據(jù)和模型必須在同一個(gè)環(huán)境中才能正常訓(xùn)練和測(cè)試。

在MXNet框架中,NDArray對(duì)象的默認(rèn)初始化環(huán)境是CPU。在不同的環(huán)境中,變量初始化意味著變量的存儲(chǔ)位置不同,存儲(chǔ)在不同環(huán)境中的變量無法計(jì)算。例如,在中央處理器中初始化的陣列對(duì)象和在圖形處理器中初始化的陣列對(duì)象在執(zhí)行計(jì)算時(shí)會(huì)報(bào)告錯(cuò)誤:

f = mx.nd.array([[ 2,3,4,5],[ 6,7,8,9]])

打印(e+f)

顯示結(jié)果如下。從錯(cuò)誤信息可以看出,兩個(gè)對(duì)象的初始化環(huán)境不一致:

mxnet . base . mxnet error:[11:14:13]src/implemental/。/implemental _ utils . h:56:檢查失敗:輸入[i]->;ctx()。dev_mask() == ctx.dev_mask() ( 1vs .2)操作員廣播_添加要求所有輸入在相同的上下文中實(shí)時(shí)進(jìn)行。但是第一個(gè)參數(shù)在gpu( 0)上,而第二個(gè)參數(shù)在cpu( 0)上

接下來F的環(huán)境也修改為GPU,然后進(jìn)行加法計(jì)算:

f = f.as_in_context(mx.gpu( 0))

打印(e+f)

輸出結(jié)果如下:

[[ 1.5.7.9.]

[ 11.13.15.17.]]

& ltNDArray 2x4 @gpu( 0)>

NDArray是MXNet框架中最常用、最基本的數(shù)據(jù)結(jié)構(gòu),是一個(gè)可以在CPU或GPU上執(zhí)行命令式操作的多維矩陣。這種命令式操作直觀靈活,是MXNet框架的特點(diǎn)之一。因?yàn)樵谑褂肕XNet框架訓(xùn)練模型時(shí),幾乎所有的數(shù)據(jù)流都是通過NDArray數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的,所以熟悉這種數(shù)據(jù)結(jié)構(gòu)非常重要。

02符號(hào)

Symbol是MXNet框架中用來搭建網(wǎng)絡(luò)層的模塊。文號(hào)的正式文件地址為:

https://mxnet.apache.org/api/python/symbol/symbol.html

在本文檔中可以查詢與符號(hào)相關(guān)的所有界面。與NDArray不同,Symbol使用符號(hào)編程,符號(hào)編程是MXNet框架實(shí)現(xiàn)快速訓(xùn)練和節(jié)省視頻內(nèi)存的關(guān)鍵模塊。

符號(hào)編程的含義,簡(jiǎn)單來說就是符號(hào)編程需要定義一個(gè)帶有符號(hào)接口的計(jì)算圖,既包含定義好的輸入輸出格式,又將準(zhǔn)備好的數(shù)據(jù)輸入到計(jì)算圖中完成計(jì)算。

但是NDArray采用命令式編程,計(jì)算過程可以一步一步實(shí)現(xiàn)。其實(shí)知道了NDArray之后,才可以通過NDArray定義和使用網(wǎng)絡(luò),那為什么還要提供Symbol呢?主要是提高效率。定義計(jì)算圖后,可以優(yōu)化整個(gè)計(jì)算圖的內(nèi)存占用,這樣可以大大減少訓(xùn)練模型時(shí)的內(nèi)存占用。

在MXNet中,Symbol接口主要用來構(gòu)建網(wǎng)絡(luò)結(jié)構(gòu)層,然后用來定義輸入數(shù)據(jù)。接下來我們?cè)倥e一個(gè)例子。首先定義一個(gè)網(wǎng)絡(luò)結(jié)構(gòu),如下。

用mxnet.symbol.Variable()接口定義輸入數(shù)據(jù),用該接口定義的輸入數(shù)據(jù)類似于一個(gè)占位符。用mxnet.symbol.Convolution()接口定義一個(gè)卷積核尺寸為3*3,卷積核數(shù)量為128的卷積層,卷積層是深度學(xué)習(xí)算法提取特征的主要網(wǎng)絡(luò)層,該層將是你在深度學(xué)習(xí)算法(尤其是圖像領(lǐng)域)中使用最為頻繁的網(wǎng)絡(luò)層。用 mxnet.symbol.BatchNorm()接口定義一個(gè)批標(biāo)準(zhǔn)化(batch normalization,常用縮寫B(tài)N表示)層,該層有助于訓(xùn)練算法收斂。用mxnet.symbol.Activation()接口定義一個(gè)ReLU激活層,激活層主要用來增加網(wǎng)絡(luò)層之間的非線性,激活層包含多種類型,其中以ReLU激活層最為常用。用mxnet.symbol.Pooling()接口定義一個(gè)最大池化層(pooling),池化層的主要作用在于通過縮減維度去除特征圖噪聲和減少后續(xù)計(jì)算量,池化層包含多種形式,常用形式有均值池化和最大池化。用mxnet.symbol.FullyConnected()接口定義一個(gè)全連接層,全連接層是深度學(xué)習(xí)算法中經(jīng)常用到的層,一般是位于網(wǎng)絡(luò)的最后幾層。需要注意的是,該接口的num_hidden參數(shù)表示分類的類別數(shù)。用mxnet.symbol.SoftmaxOutput()接口定義一個(gè)損失函數(shù)層,該接口定義的損失函數(shù)是圖像分類算法中常用的交叉熵?fù)p失函數(shù)(cross entropy loss),該損失函數(shù)的輸入是通過softmax函數(shù)得到的,softmax函數(shù)是一個(gè)變換函數(shù),表示將一個(gè)向量變換成另一個(gè)維度相同,但是每個(gè)元素范圍在[0,1]之間的向量,因此該層用mxnet.symbol.SoftmaxOutput()來命名。這樣就得到了一個(gè)完整的網(wǎng)絡(luò)結(jié)構(gòu)了。

網(wǎng)絡(luò)結(jié)構(gòu)定義代碼如下:

importmxnet asmx

data = mx.sym.Variable( 'data ')

conv = mx.sym .卷積(data=data,num_filter= 128,kernel=( 3,3),pad=( 1,1),name= 'conv1 ')

bn = MX . sym . batchorm(數(shù)據(jù)=conv,名稱= 'bn1 ')

relu = mx.sym.Activation(data=bn,act_type= 'relu ',name= 'relu1 ')

pool = mx.sym.Pooling(data=relu,kernel=( 2,2),stride=( 2,2),pool_type= 'max ',name= 'pool1 ')

fc = MX . sym . fully connected(data = pool,num_hidden= 2,name= 'fc1 ')

sym = MX . sym . SoftMaxOutPut(data = fc,name = ' SoftMaxOutPut ')

Mx.sym是mxnet.symbol常用的縮寫,后面的章節(jié)默認(rèn)采用。另外,最好在定義每個(gè)網(wǎng)絡(luò)層的時(shí)候指定name參數(shù),這樣代碼看起來更清晰。

定義好網(wǎng)絡(luò)結(jié)構(gòu)之后,肯定想看看網(wǎng)絡(luò)結(jié)構(gòu)包含哪些參數(shù)。畢竟訓(xùn)練模型的過程就是更新模型參數(shù)的過程。在MXNet中,list_arguments()方法可用于查看符號(hào)對(duì)象的參數(shù)。命令如下:

print(sym.list_arguments())

從下面的輸出結(jié)果可以看出,第一個(gè)和最后一個(gè)分別是‘data’和‘soft max _ label’,分別代表輸入數(shù)據(jù)和標(biāo)簽;‘conv 1 _ weight’和‘conv 1 _ bias’是卷積層的參數(shù),具體來說,前者是卷積核的權(quán)重參數(shù),后者是bias參數(shù)。bn1 _γ’和‘bn1 _β’是Bn層的參數(shù);‘fc1 _ weight’和‘fc1 _ bias’是全連接層的參數(shù)。

['數(shù)據(jù)',' conv1_weight ',' conv1_bias ',' bn1_gamma ',' bn1_beta ',' fc1_weight ',' fc1_bias ',' softmax_label']

除了檢查網(wǎng)絡(luò)的參數(shù)層名稱,有時(shí)還需要檢查網(wǎng)絡(luò)層參數(shù)的維度、網(wǎng)絡(luò)輸出維度等信息,這對(duì)于代碼調(diào)試尤其有幫助。

在MXNet中,可以使用以下方法查看符號(hào)對(duì)象的圖層參數(shù)尺寸、輸出尺寸和輔助圖層參數(shù)尺寸信息。調(diào)用此方法時(shí),需要指定輸入數(shù)據(jù)的維度,以便網(wǎng)絡(luò)結(jié)構(gòu)根據(jù)指定的輸入維度計(jì)算維度信息,如圖層參數(shù)和網(wǎng)絡(luò)輸出:

arg_shape,out_shape,aux _ shape = sym . expert _ shape(data =(1,3,10,10))

打印(arg_shape)

打印(out_shape)

打印(輔助形狀)

從以下輸出結(jié)果可以看出,第一行代表網(wǎng)絡(luò)層參數(shù)的維度,對(duì)應(yīng)于前面list_arguments()方法中列出的層參數(shù)名稱,例如:

輸入數(shù)據(jù)'data'的維度是(1, 3, 10, 10);卷積層的權(quán)重參數(shù)'conv1_weight'的維度是(128, 3, 3, 3);卷積層的偏置參數(shù)'conv1_bias'的維度是(128,),因?yàn)槊總€(gè)卷積核對(duì)應(yīng)于一個(gè)偏置參數(shù);全連接層的權(quán)重參數(shù)'fc1_weight'的維度是(2, 3200),這里的3000是通過計(jì)算5*5*128得到的,其中5*5表示全連接層的輸入特征圖的寬和高。

第二行代表網(wǎng)絡(luò)輸出的維度,因?yàn)榫W(wǎng)絡(luò)的最后一層是輸出節(jié)點(diǎn)為2的全連接層,輸入數(shù)據(jù)的批量維度為1,所以輸出維度為[(1,2)]。

第三行是輔助參數(shù)的維度,是BN層的參數(shù)維度。

[( 1, 3, 10, 10), ( 128, 3, 3, 3), ( 128,), ( 128,), ( 128,), ( 2, 3200), ( 2,), ( 1,)]

[( 1, 2)]

[( 128,), ( 128,)]

如果截取Symbol模塊定義的網(wǎng)絡(luò)結(jié)構(gòu)的一部分非常方便的話,可以通過MXNet中的get _ internals()方法獲取Symbol對(duì)象的所有圖層信息,然后選擇要截取的圖層,比如截取sym從輸入到匯集圖層:

sym _ mini = sym . get _ internal()[' pool 1 _ output ']

print(sym_mini.list_arguments())

輸出結(jié)果如下,可以看出圖層參數(shù)中沒有sym的原始全連接圖層和標(biāo)簽圖層信息:

['數(shù)據(jù)',' conv1_weight ',' conv1_bias ',' bn1_gamma ',' bn1_beta']

截取后,可以繼續(xù)在截取的Symbol對(duì)象后添加網(wǎng)絡(luò)層,例如添加一個(gè)輸出節(jié)點(diǎn)為5的全連接層和一個(gè)softmax層:

fc _ new = MX . sym . fully connected(data = sym _ mini,num_hidden= 5,name= 'fc_new ')

sym _ new = MX . sym . SoftMaxOutput(data = fc _ new,name = ' SoftMaxOutput ')

print(sym_new.list_arguments())

輸出如下,您可以看到整個(gè)連接層已被替換:

['數(shù)據(jù)',' conv1_weight ',' conv1_bias ',' bn1_gamma ',' bn1_beta ',' fc_new_weight ',' fc_new_bias ',' softmax_label']

除了定義神經(jīng)網(wǎng)絡(luò)層,Symbol模塊還可以實(shí)現(xiàn)NDArray的大部分操作。接下來,以數(shù)組的加法和乘法為例,介紹了利用符號(hào)模塊實(shí)現(xiàn)上述運(yùn)算的方法。兩個(gè)輸入data_a和data _ b通過mxnet.symbol.Variable()接口定義。然后定義data_a和data_b相加再乘以data_c得到結(jié)果s的運(yùn)算,通過打印s的類型可以看到s的類型是Symbol,代碼如下:

importmxnet asmx

data_a = mx.sym.Variable ( 'data_a ')

data_b = mx.sym.Variable ( 'data_b ')

data_c = mx.sym.Variable ( 'data_c ')

s = data_c*(data_a+data_b)

打印(類型)

輸出結(jié)果如下:

& ltclass ' mxnet . symbol . symbol . symbol ' >;

接下來,調(diào)用S的bind()方法,將具體的輸入和定義的操作綁定到執(zhí)行器。同時(shí),您需要為bind()方法指定是在CPU上還是GPU上執(zhí)行計(jì)算。執(zhí)行完綁定操作后,你得到執(zhí)行器E,最后打印E的類型供查看。代碼如下:

e = s.bind(mx.cpu(),{ 'data_a':mx.nd.array([ 1,2,3]),' data_b':mx.nd.array([ 4,5,6]),

data_c':mx.nd.array([ 2,3,4])})

打印(e型)

輸出結(jié)果如下:

& ltclass'mxnet.executor.Executor ' >;

這個(gè)執(zhí)行器是一個(gè)完整的計(jì)算圖,所以可以調(diào)用執(zhí)行器的forward()方法進(jìn)行計(jì)算,得到結(jié)果:

output=e.forward()

打印(輸出[ 0])

輸出結(jié)果如下:

[ 10.21.36.]

& ltNDArray 3@cpu( 0)>;

相比之下,通過NDArray模塊實(shí)現(xiàn)這些操作要簡(jiǎn)單直觀得多。代碼如下:

importmxnet asmx

data_a = mx.nd.array([ 1,2,3])

data_b = mx.nd.array([ 4,5,6])

data_c = mx.nd.array([ 2,3,4])

結(jié)果= data_c*(data_a+data_b)

打印(結(jié)果)

輸出結(jié)果如下:

[ 10.21.36.]

& ltNDArray 3@cpu( 0)>;

雖然使用符號(hào)接口的實(shí)現(xiàn)看起來很復(fù)雜,但在定義計(jì)算圖表后,許多視頻內(nèi)存可以重用或共享。比如在Symbol模塊的實(shí)現(xiàn)版本中,底層計(jì)算的data_a+data_b的結(jié)果會(huì)存儲(chǔ)在data_a或data_b所在的空中,因?yàn)樵谶@個(gè)計(jì)算圖中,data_a和data_b是在進(jìn)行加法計(jì)算。

前面描述了由符號(hào)模塊中的變量接口定義的操作和數(shù)組模塊中的相應(yīng)實(shí)現(xiàn)之間的相似性。另外,Symbol模塊中網(wǎng)絡(luò)層的操作基本上和NDArray模塊中有對(duì)應(yīng)的操作,對(duì)靜態(tài)圖的調(diào)試很有幫助。

如前所述,Symbol模塊采用符號(hào)編程(或靜態(tài)圖),即需要先定義一個(gè)計(jì)算圖,然后執(zhí)行計(jì)算。這種方法雖然效率高,但實(shí)際上對(duì)代碼調(diào)試并不友好,因?yàn)槟愫茈y獲得中間變量的值。

現(xiàn)在,因?yàn)閹в忻钍骄幊痰腘DArray模塊基本上包含了Symbol模塊中同名的操作,所以可以在一定程度上幫助調(diào)試代碼。然后以卷積層為例,看看如何用NDArray模塊實(shí)現(xiàn)卷積層運(yùn)算。首先用mxnet . ndaarray . arange()接口初始化輸入數(shù)據(jù)。這里定義了一個(gè)四維數(shù)據(jù),之所以定義為四維,是因?yàn)槟P椭械臄?shù)據(jù)流基本上都是四維的。具體代碼如下:

data = mx.nd.arange( 0,28)。重塑((1,1,4,7))

打印(數(shù)據(jù))

輸出結(jié)果如下:

[[[[ 0.1.2.3.4.5.6.]

[ 7.8.9.10.11.12.13.]

[ 14.15.16.17.18.19.20.]

[ 21.22.23.24.25.26.27.]]]]

& ltNDArray 1x1x4x7 @cpu( 0)>

然后通過mxnet . ndaarray .卷積()接口定義卷積層操作。除了與mxnet.symbol .卷積()接口相同的數(shù)據(jù)、num_filter、內(nèi)核和名稱外,該接口的輸入需要直接指定權(quán)重和偏差。

權(quán)重和偏差是卷積層的參數(shù)值。為了簡(jiǎn)單起見,這里將權(quán)重初始化為所有值都為1的4維變量,將偏差初始化為所有值都為0的1維變量,這樣就可以得到最終的卷積結(jié)果。具體代碼如下:

conv1 = mx.nd .卷積(data=data,weight = MX . nd . one((10,1,3,3)),

bias=mx.nd.zeros(( 10)),num_filter= 10,kernel=( 3,3),

名稱= 'conv1 ')

打印(conv1)

輸出結(jié)果如下:

[[[[ 72.81.90.99.108.]

[ 135.144.153.162.171.]]

[[ 72.81.90.99.108.]

[ 135.144.153.162.171.]

[[ 72.81.90.99.108.]

[ 135.144.153.162.171.]]

[[ 72.81.90.99.108.]

[ 135.144.153.162.171.]]

[[ 72.81.90.99.108.]

[ 135.144.153.162.171.]]

[[ 72.81.90.99.108.]

[ 135.144.153.162.171.]]

[[ 72.81.90.99.108.]

[ 135.144.153.162.171.]]

[[ 72.81.90.99.108.]

[ 135.144.153.162.171.]]

[[ 72.81.90.99.108.]

[ 135.144.153.162.171.]]

[[ 72.81.90.99.108.]

[ 135.144.153.162.171.]]]]

& ltNDArray 1x10x2x5 @cpu( 0)>

總的來說,Symbol和NDArray有很多相似之處,兩者在MXNet中都發(fā)揮著重要的作用。NDArray,采用命令式編程,特點(diǎn)是直觀,常用來實(shí)現(xiàn)底層計(jì)算;符號(hào),使用符號(hào)編程,特點(diǎn)是效率高,主要用于定義計(jì)算圖。

03模塊

在MXNet框架中,Module是一個(gè)高級(jí)封裝模塊,可以用來進(jìn)行Symbol Module定義的網(wǎng)絡(luò)模型的訓(xùn)練,與Module相關(guān)的接口介紹可以參考Module的公文地址:

https://mxnet.apache.org/api/python/module/module.html

Module接口為模型訓(xùn)練提供了很多非常方便的方法,只需要將準(zhǔn)備好的數(shù)據(jù)和超級(jí)參數(shù)傳遞給相應(yīng)的方法就可以開始訓(xùn)練。

早上,我們用符號(hào)接口定義了一個(gè)網(wǎng)絡(luò)結(jié)構(gòu)符號(hào)。接下來,我們將介紹基于這種網(wǎng)絡(luò)結(jié)構(gòu)的模塊模塊。首先,我們將看看如何通過模塊模塊來執(zhí)行模型的預(yù)測(cè)操作。

通過mxnet.module.Module()接口初始化一個(gè)Module對(duì)象。初始化時(shí)需要傳入定義的網(wǎng)絡(luò)結(jié)構(gòu)sym,指定運(yùn)行環(huán)境,這里設(shè)置為GPU環(huán)境。

然后執(zhí)行Module對(duì)象的綁定操作,類似于Symbol模塊中的綁定操作。這種綁定操作的目的是將網(wǎng)絡(luò)結(jié)構(gòu)添加到執(zhí)行器中,使定義的靜態(tài)圖能夠真正運(yùn)行。因?yàn)檫@個(gè)過程涉及到視頻內(nèi)存的分配,所以在執(zhí)行綁定操作之前,需要提供輸入數(shù)據(jù)和標(biāo)簽的維度信息。讀者可以通過命令行“$ watch nvidia-smi”檢查執(zhí)行綁定前后視頻內(nèi)存的變化。

綁定操作中還有一個(gè)重要的參數(shù),就是for_training。該參數(shù)默認(rèn)為真,表示接下來進(jìn)行訓(xùn)練過程。因?yàn)槲覀冎恍枰M(jìn)行網(wǎng)絡(luò)的正向計(jì)算,所以我們將這個(gè)參數(shù)設(shè)置為False。

最后,調(diào)用Module對(duì)象的init_params()方法來初始化網(wǎng)絡(luò)結(jié)構(gòu)的參數(shù)。初始化方法是可選的,這里采用默認(rèn)方法。此時(shí),一個(gè)可用的網(wǎng)絡(luò)結(jié)構(gòu)執(zhí)行器被初始化。初始化網(wǎng)絡(luò)結(jié)構(gòu)執(zhí)行器的代碼如下:

mod = MX . mod . module(sym = sym,context=mx.gpu( 0))

mod.bind(data_shapes=[( 'data ',(8,3,28,28))],

label_shapes=[( 'softmax_label ',(8),)],

for_training= False)

mod.init_params()

然后隨機(jī)初始化一個(gè)4維輸入數(shù)據(jù),其維度需要與初始化Module對(duì)象時(shí)設(shè)置的數(shù)據(jù)維度相同,然后通過mxnet.io.DataBatch()接口打包成一個(gè)批處理數(shù)據(jù),可以作為Module對(duì)象的forward()方法的輸入。執(zhí)行正向計(jì)算后,調(diào)用Module對(duì)象的get_outputs()方法,得到模型的輸出結(jié)果。具體代碼如下:

data = mx.nd.random.uniform( 0,1,shape=( 8,3,28,28))

mod . forward(MX . io . Databatch([data])

print(mod.get_outputs()[ 0])

輸出結(jié)果如下,由于輸入數(shù)據(jù)批量為8,網(wǎng)絡(luò)全連接層輸出節(jié)點(diǎn)數(shù)為2,所以輸出的維數(shù)為8*2:

[[ 0.500800670.4991993]

[ 0.501486120.49851385]

[ 0.501038370.4989616]

[ 0.501711310.49828872]

[ 0.502543870.4974561]

[ 0.501042540.49895743]

[ 0.502231480.49776852]

[ 0.497809590.50219035]]

& ltNDArray 8x2 @gpu( 0)>

接下來,我們介紹如何通過模塊模塊進(jìn)行模型的訓(xùn)練操作。代碼部分和預(yù)測(cè)操作有很多相似之處。具體代碼如下面的代碼清單3-1所示。接下來,我們?cè)敿?xì)介紹代碼內(nèi)容。

本文中的代碼列表可以在本書的項(xiàng)目代碼地址中找到:

https://github.com/miraclewkf/MXNet-Deep-Learning-in-Action

使用mxnet.io.NDArrayIter()接口初始化得到訓(xùn)練和驗(yàn)證數(shù)據(jù)迭代器,這里為了演示采用隨機(jī)初始化的數(shù)據(jù),實(shí)際應(yīng)用中要讀取有效的數(shù)據(jù),不論讀取的是什么樣的數(shù)據(jù),最后都需要封裝成數(shù)據(jù)迭代器才能提供給模型訓(xùn)練。用mxnet.module.Module()接口初始化得到一個(gè)Module對(duì)象,這一步至少要輸入一個(gè)Symbol對(duì)象,另外這一步還可以指定訓(xùn)練環(huán)境是CPU還是GPU,這里采用GPU。調(diào)用Module對(duì)象的bind()方法將準(zhǔn)備好的數(shù)據(jù)和網(wǎng)絡(luò)結(jié)構(gòu)連接到執(zhí)行器構(gòu)成一個(gè)完整的計(jì)算圖。調(diào)用Module對(duì)象的init_params()方法初始化網(wǎng)絡(luò)的參數(shù),因?yàn)榍懊娑x的網(wǎng)絡(luò)結(jié)構(gòu)只是一個(gè)架子,里面沒有參數(shù),因此需要執(zhí)行參數(shù)初始化。調(diào)用Module對(duì)象的init_optimizer()方法初始化優(yōu)化器,默認(rèn)采用隨機(jī)梯度下降法(stochastic gradient descent,SGD)進(jìn)行優(yōu)化。調(diào)用mxnet.metric.create()接口創(chuàng)建評(píng)價(jià)函數(shù),這里采用的是準(zhǔn)確率(accuracy)。執(zhí)行5次循環(huán)訓(xùn)練,每次循環(huán)都會(huì)將所有數(shù)據(jù)過一遍模型,因此在循環(huán)開始處需要執(zhí)行評(píng)價(jià)函數(shù)的重置操作、數(shù)據(jù)的初始讀取等操作。此處的while循環(huán)只有在讀取完訓(xùn)練數(shù)據(jù)之后才會(huì)退出,該循環(huán)首先會(huì)調(diào)用Module對(duì)象的forward()方法執(zhí)行模型的前向計(jì)算,這一步就是輸入數(shù)據(jù)通過每一個(gè)網(wǎng)絡(luò)層的參數(shù)進(jìn)行計(jì)算并得到最后結(jié)果。調(diào)用Module對(duì)象的backward()方法執(zhí)行模型的反向傳播計(jì)算,這一步將涉及損失函數(shù)的計(jì)算和梯度的回傳。調(diào)用Module對(duì)象的update()方法執(zhí)行參數(shù)更新操作,參數(shù)更新的依據(jù)就是第9步計(jì)算得到的梯度,這樣就完成了一個(gè)批次(batch)數(shù)據(jù)對(duì)網(wǎng)絡(luò)參數(shù)的更新。調(diào)用Module對(duì)象的update_metric()方法更新評(píng)價(jià)函數(shù)的計(jì)算結(jié)果。讀取下一個(gè)批次的數(shù)據(jù),這里采用了Python中的try和except語句,表示如果try包含的語句執(zhí)行出錯(cuò),則執(zhí)行except包含的語句,這里用來標(biāo)識(shí)是否讀取到了數(shù)據(jù)集的最后一個(gè)批次。調(diào)用評(píng)價(jià)對(duì)象的get_name_value()方法并打印此次計(jì)算的結(jié)果。調(diào)用Module對(duì)象的get_params()方法讀取網(wǎng)絡(luò)參數(shù),并利用這些參數(shù)初始化Module對(duì)象了。調(diào)用數(shù)據(jù)對(duì)象的reset()方法進(jìn)行重置,這樣在下一次循環(huán)中就可以從數(shù)據(jù)的最初始位置開始讀取了。代碼清單3-1 通過Module模塊訓(xùn)練模型

importmxnet asmx

導(dǎo)入日志

data = mx.sym.Variable( 'data ')

conv = mx.sym .卷積(data=data,num_filter= 128,kernel=( 3,3),pad=( 1,1),

名稱= 'conv1 ')

bn = MX . sym . batchorm(數(shù)據(jù)=conv,名稱= 'bn1 ')

relu = mx.sym.Activation(data=bn,act_type= 'relu ',name= 'relu1 ')

pool = mx.sym.Pooling(data=relu,kernel=( 2,2),stride=( 2,2),pool_type= 'max ',

名稱= 'pool1 ')

fc = MX . sym . fully connected(data = pool,num_hidden= 2,name= 'fc1 ')

sym = MX . sym . SoftMaxOutPut(data = fc,name = ' SoftMaxOutPut ')

data = mx.nd.random.uniform( 0,1,shape=( 1000,3,224,224))

label = MX . nd . round(MX . nd . random . uniform(0,1,shape=( 1000)))

train_data = mx.io.NDArrayIter(數(shù)據(jù)={ 'data':data},

label={ 'softmax_label':label},

批處理大小= 8,

洗牌=真)

打印(train_data.provide_data)

打印(train_data.provide_label)

mod = MX . mod . module(sym = sym,context=mx.gpu( 0))

mod . bind(data _ shapes = train _ data . provide _ data,

label _ shapes = train _ data . provide _ label)

mod.init_params()

mod.init_optimizer()

eval _ metric = MX . metric . create(' ACC ')

前戲范圍(5):

批次結(jié)束=假

eval_metric.reset()

data_iter = iter(train_data)

next_data_batch = next(data_iter)

whilenotend_of_batch:

data_batch = next_data_batch

mod.forward(data_batch)

mod.backward()

mod.update()

mod.update_metric(eval_metric,labels=data_batch.label)

嘗試:

next_data_batch = next(data_iter)

mod.prepare(next_data_batch)

例外停止迭代:

批處理結(jié)束=真

eval _ name _ vals = eval _ metric . get _ name _ value()

print(" Epoch:{ } Train _ Acc:{:. 4f } "。格式(epoch,eval_name_vals[ 0][ 1])

arg_params,aux_params = mod.get_params()

mod.set_params(arg_params,aux_params)

train_data.reset()

事實(shí)上,清單3-1中的代碼可以通過mod.bind()方法中的fit()方法從頭到尾實(shí)現(xiàn)。fit()方法不僅封裝了上述的綁定操作、參數(shù)初始化、優(yōu)化器初始化、模型正向計(jì)算、反向傳播、參數(shù)更新、評(píng)價(jià)指標(biāo)計(jì)算等操作,還提供了保存訓(xùn)練結(jié)果等其他操作,因此未來使用MXNet訓(xùn)練模型時(shí)會(huì)頻繁調(diào)用fit()方法。

下面的代碼演示了fit()方法的調(diào)用。前兩行設(shè)置命令行打印訓(xùn)練信息。這三行代碼可以直接替換代碼清單3-1中從mod.bind()行到末尾的所有代碼。

在fit()方法的輸入?yún)?shù)中,train_data參數(shù)是訓(xùn)練數(shù)據(jù),num_epoch參數(shù)是整個(gè)訓(xùn)練集在訓(xùn)練過程中的迭代次數(shù)(也稱為epoch數(shù))。需要注意的是,只有當(dāng)所有的train_data都通過模型時(shí),才能完成一個(gè)歷元,所以這里設(shè)置訓(xùn)練集數(shù)據(jù)在訓(xùn)練完成之前通過模型五次。

logger = logging.getLogger()

logger.setLevel(日志記錄。INFO)

mod.fit(train_data=train_data,num_epoch= 5)

清單3-2顯示了簡(jiǎn)化的代碼。

代碼清單3-2 通過Module模塊訓(xùn)練模型(簡(jiǎn)化版)

importmxnet asmx

導(dǎo)入日志

data = mx.sym.Variable( 'data ')

conv = mx.sym .卷積(data=data,num_filter= 128,kernel=( 3,3),pad=( 1,1),

名稱= 'conv1 ')

bn = MX . sym . batchorm(數(shù)據(jù)=conv,名稱= 'bn1 ')

relu = mx.sym.Activation(data=bn,act_type= 'relu ',name= 'relu1 ')

pool = mx.sym.Pooling(data=relu,kernel=( 2,2),stride=( 2,2),pool_type= 'max ',

名稱= 'pool1 ')

fc = MX . sym . fully connected(data = pool,num_hidden= 2,name= 'fc1 ')

sym = MX . sym . SoftMaxOutPut(data = fc,name = ' SoftMaxOutPut ')

data = mx.nd.random.uniform( 0,1,shape=( 1000,3,224,224))

label = MX . nd . round(MX . nd . random . uniform(0,1,shape=( 1000)))

train_data = mx.io.NDArrayIter(數(shù)據(jù)={ 'data':data},

label={ 'softmax_label':label},

批處理大小= 8,

洗牌=真)

打印(train_data.provide_data)

打印(train_data.provide_label)

mod = MX . mod . module(sym = sym,context=mx.gpu( 0))

logger = logging.getLogger()

logger.setLevel(日志記錄。INFO)

mod.fit(train_data=train_data,num_epoch= 5)

從下面打印的訓(xùn)練結(jié)果可以看出,輸出結(jié)果與代碼清單3-1的輸出結(jié)果基本一致:

信息:根:歷元[ 0]訓(xùn)練精度= 0.515000

信息:根:紀(jì)元[ 0]時(shí)間成本= 4.618

信息:根:紀(jì)元[ 1]訓(xùn)練精度= 0.700000

信息:根:紀(jì)元[ 1]時(shí)間成本= 4.425

信息:根:紀(jì)元[ 2]訓(xùn)練精度= 0.969000

信息:根:紀(jì)元[ 2]時(shí)間成本= 4.428

信息:根:紀(jì)元[ 3]訓(xùn)練精度= 0.988000

信息:根:紀(jì)元[ 3]時(shí)間成本= 4.410

信息:根:紀(jì)元[ 4]訓(xùn)練精度= 0.999000

信息:根:紀(jì)元[ 4]時(shí)間成本= 4.425

在上面的演示代碼中,只設(shè)置了fit()方法的幾個(gè)輸入。其實(shí)fit()方法的輸入有很多。在實(shí)際使用中,可以根據(jù)具體要求設(shè)置不同的輸入?yún)?shù),這將在本書后面的章節(jié)中詳細(xì)介紹。

得益于MXNet的靜態(tài)圖形設(shè)計(jì)和計(jì)算過程的優(yōu)化,你會(huì)發(fā)現(xiàn)MXNet的訓(xùn)練速度比大多數(shù)深度學(xué)習(xí)框架都要快,視頻內(nèi)存非常?。∵@樣可以讓你用更大的批量在一張卡片或者多張卡片上訓(xùn)練同一個(gè)模型,對(duì)于復(fù)雜模型的訓(xùn)練非常有利,有時(shí)甚至?xí)绊懹?xùn)練結(jié)果。

04摘要

本文主要介紹了MXNet框架中最常用的三個(gè)模塊:NDArray、Symbol和module,并比較了它們之間的關(guān)系,通過簡(jiǎn)單的代碼就可以大致了解這三個(gè)模塊的使用。

NDArray是MXNet框架中最基本的數(shù)據(jù)結(jié)構(gòu),借鑒了NumPy中數(shù)組的思想,可以在GPU上運(yùn)行。同時(shí),采用命令式編程的NDArray在代碼調(diào)試方面非常靈活。NDArray提供了類似于NumPy數(shù)組的方法和屬性,所以熟悉NumPy數(shù)組的用戶應(yīng)該能夠快速操作NDArray,并且它們之間的轉(zhuǎn)換非常方便。

符號(hào)是MXNet框架中定義網(wǎng)絡(luò)結(jié)構(gòu)層的接口。符號(hào)編程通過構(gòu)造靜態(tài)計(jì)算圖,可以大大提高模型訓(xùn)練的效率。符號(hào)提供了多種查看符號(hào)對(duì)象信息的方法,包括參數(shù)圖層、參數(shù)標(biāo)注等。同時(shí)也方便用戶在設(shè)計(jì)網(wǎng)絡(luò)結(jié)構(gòu)的過程中查漏補(bǔ)缺。

此外,Symbol中的大多數(shù)網(wǎng)絡(luò)層接口在NDArray中都有相應(yīng)的實(shí)現(xiàn),因此可以通過NDArray中具有相應(yīng)名稱的網(wǎng)絡(luò)層查看具體的計(jì)算過程。

該模塊是一個(gè)高級(jí)接口,它封裝了在MXNet框架中訓(xùn)練模型所需的大多數(shù)操作。用戶可以執(zhí)行綁定操作、參數(shù)初始化、優(yōu)化器初始化、模型的正向計(jì)算、損失函數(shù)的反向傳播、網(wǎng)絡(luò)參數(shù)的更新、評(píng)估指標(biāo)的計(jì)算等。同時(shí),該模塊還將常見的訓(xùn)練操作封裝在fit()方法中,通過該方法用戶可以更方便地訓(xùn)練模型,可以說是靈活簡(jiǎn)單。

關(guān)于作者:魏開豐,高級(jí)AI算法工程師、計(jì)算機(jī)視覺工程師,在MXNet、Pytorch、深度學(xué)習(xí)算法等方面有深入的研究和豐富的實(shí)踐經(jīng)驗(yàn)。,從事計(jì)算機(jī)視覺算法。他的主要研究興趣包括目標(biāo)檢測(cè)、圖像分類、圖像對(duì)抗算法、模型加速和壓縮。

本文摘自經(jīng)出版社授權(quán)的《MXNet深度學(xué)習(xí):計(jì)算機(jī)視覺算法的實(shí)現(xiàn)》。

“MXNet深度學(xué)習(xí)實(shí)踐”拓展閱讀

轉(zhuǎn)載請(qǐng)聯(lián)系微信:DoctorData

推薦語言:網(wǎng)易高級(jí)計(jì)算機(jī)視覺算法工程師編寫,他從算法實(shí)現(xiàn)和框架原理兩個(gè)維度詳細(xì)講解了計(jì)算機(jī)視覺算法的實(shí)現(xiàn)以及MXNet框架的使用和原理。

問:你在用什么深度學(xué)習(xí)框架?

轉(zhuǎn)載/提交請(qǐng)聯(lián)系:baiyu@hzbook.com

1.《mxnet 深度學(xué)習(xí)高能干貨:手把手教你搭建MXNet框架》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識(shí),僅代表作者本人觀點(diǎn),與本網(wǎng)站無關(guān),侵刪請(qǐng)聯(lián)系頁腳下方聯(lián)系方式。

2.《mxnet 深度學(xué)習(xí)高能干貨:手把手教你搭建MXNet框架》僅供讀者參考,本網(wǎng)站未對(duì)該內(nèi)容進(jìn)行證實(shí),對(duì)其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。

3.文章轉(zhuǎn)載時(shí)請(qǐng)保留本站內(nèi)容來源地址,http://f99ss.com/fangchan/1237713.html

上一篇

沿途有你 【魅力冶金】沿途有你——冶金學(xué)院

下一篇

篆刻印章在線生成器 秒變PS達(dá)人|自制篆刻印章

吸血新世紀(jì) ACC 2020丨替格瑞洛單藥方案漸成首選——TWLIGHT研究亞組結(jié)果線上直播解讀(下)

  • 吸血新世紀(jì) ACC 2020丨替格瑞洛單藥方案漸成首選——TWLIGHT研究亞組結(jié)果線上直播解讀(下)
  • 吸血新世紀(jì) ACC 2020丨替格瑞洛單藥方案漸成首選——TWLIGHT研究亞組結(jié)果線上直播解讀(下)
  • 吸血新世紀(jì) ACC 2020丨替格瑞洛單藥方案漸成首選——TWLIGHT研究亞組結(jié)果線上直播解讀(下)

2016年馬會(huì)開開獎(jiǎng)結(jié)果 江湖召集令 | 邀你一起和小伙伴們來接管馬會(huì)

  • 2016年馬會(huì)開開獎(jiǎng)結(jié)果 江湖召集令 | 邀你一起和小伙伴們來接管馬會(huì)
  • 2016年馬會(huì)開開獎(jiǎng)結(jié)果 江湖召集令 | 邀你一起和小伙伴們來接管馬會(huì)
  • 2016年馬會(huì)開開獎(jiǎng)結(jié)果 江湖召集令 | 邀你一起和小伙伴們來接管馬會(huì)

佳能5d4參數(shù) 【福聯(lián)·影像】相機(jī)設(shè)置教程:EOS 5D Mark Ⅳ常用拍攝設(shè)置技巧,含基本參考參數(shù)

  • 佳能5d4參數(shù) 【福聯(lián)·影像】相機(jī)設(shè)置教程:EOS 5D Mark Ⅳ常用拍攝設(shè)置技巧,含基本參考參數(shù)
  • 佳能5d4參數(shù) 【福聯(lián)·影像】相機(jī)設(shè)置教程:EOS 5D Mark Ⅳ常用拍攝設(shè)置技巧,含基本參考參數(shù)
  • 佳能5d4參數(shù) 【福聯(lián)·影像】相機(jī)設(shè)置教程:EOS 5D Mark Ⅳ常用拍攝設(shè)置技巧,含基本參考參數(shù)

卓婭麗植發(fā) 90后小伙貸款植發(fā),結(jié)果越植越少!最后…連女朋友也跑了

近日,來自上海的張先生告訴記者,他在醫(yī)院植發(fā)。據(jù)說成功率高達(dá)95%,但最終結(jié)果是越來越少發(fā)。連他女朋友都跑了...為此,他要求醫(yī)院賠償! 張先生告訴記者,他本來在兩個(gè)額前小突起的發(fā)際線后面,現(xiàn)在整個(gè)頭發(fā)都斷了,后腦勺的毛囊長不出來,坑坑洼洼的很...

舌頭上有白點(diǎn)顆粒狀圖 舌頭有白點(diǎn)是口腔癌? 網(wǎng)上診斷結(jié)果需甄別準(zhǔn)確性

舌頭有白點(diǎn)是口腔癌? 在線診斷結(jié)果不可靠?!罢局粍?dòng)也是絕癥!你咳一咳,再上網(wǎng)查查,絕對(duì)是肺結(jié)核!發(fā)個(gè)燒上網(wǎng)查查??隙ㄊ前2├?。半天就涼了!如果你在網(wǎng)上有鼻涕,那就是腦膜炎。你的大腦在爆漿!網(wǎng)上沒什么好查的,沒病給嚇成病走人……”這兩天,一位瑞...

三維數(shù)組 三維數(shù)組何去何從?

  • 三維數(shù)組 三維數(shù)組何去何從?
  • 三維數(shù)組 三維數(shù)組何去何從?
  • 三維數(shù)組 三維數(shù)組何去何從?

說好不分開 當(dāng)初說好不分開,結(jié)果你卻停下來!停下來?

  • 說好不分開 當(dāng)初說好不分開,結(jié)果你卻停下來!停下來?
  • 說好不分開 當(dāng)初說好不分開,結(jié)果你卻停下來!停下來?
  • 說好不分開 當(dāng)初說好不分開,結(jié)果你卻停下來!停下來?
胃出血后的菜譜大全 男子吃了這道菜,結(jié)果胃出血!這道美味正在大量上市,很多寧波人都愛吃!

胃出血后的菜譜大全 男子吃了這道菜,結(jié)果胃出血!這道美味正在大量上市,很多寧波人都愛吃!

春回大地,萬物生長,現(xiàn)在市場(chǎng)上有大量新鮮的春筍。在寧波人眼里,春筍堪稱“春菜之王”。只要遇到竹筍,所有的野菜和蔬菜就完全黯然失色。  但最近,很多人都“倒”在了這種美食面前。 自3月中旬以來,醫(yī)院消化內(nèi)科門診人數(shù)不斷增加,其中因食用竹筍引起的胃...