利用深度學(xué)習(xí)模型解決數(shù)據(jù)稀疏問題

前言

閱讀文獻(xiàn)《PHIAF: prediction of phage-host interactions with GAN-based data augmentation and sequence-based feature fusion》
GitHub 地址:https://github.com/BioMedicalBigDataMiningLab/PHIAF/blob/master/code/generate_data.py

這個(gè)項(xiàng)目由于正樣本數(shù)據(jù)稀疏怠缸,數(shù)據(jù)量不夠支撐進(jìn)行深度學(xué)習(xí)的量勉抓,因此現(xiàn)在有限的正樣本中學(xué)習(xí)一個(gè)分別盆色,然后在對(duì)這個(gè)分布進(jìn)行采樣低滩,得到一個(gè)大的負(fù)樣本數(shù)據(jù)集劝术,然后再進(jìn)行深度學(xué)習(xí)

GAN 原理

作者本文采用了GAN模型(生成對(duì)抗神經(jīng)網(wǎng)絡(luò))

GAN的基本原理其實(shí)非常簡(jiǎn)單丈冬,這里以生成數(shù)據(jù)為例進(jìn)行說明噪窘。假設(shè)我們有兩個(gè)網(wǎng)絡(luò)妆艘,G(Generator)和D(Discriminator)植康。正如它的名字所暗示的那樣旷太,它們的功能分別是:

  1. G是一個(gè)生成數(shù)據(jù)的網(wǎng)絡(luò),它接收一個(gè)隨機(jī)的噪聲z销睁,通過這個(gè)噪聲生成數(shù)據(jù)供璧,記做G(z)。
  2. D是一個(gè)判別網(wǎng)絡(luò)冻记,判別數(shù)據(jù)是不是“真實(shí)的”睡毒。它的輸入?yún)?shù)是x,x代表一張數(shù)據(jù)冗栗,輸出D(x)代表x為真實(shí)數(shù)據(jù)的概率演顾,如果為1供搀,就代表100%是真實(shí)的數(shù)據(jù),而輸出為0钠至,就代表不可能是真實(shí)的數(shù)據(jù)葛虐。
    在訓(xùn)練過程中,生成網(wǎng)絡(luò)G的目標(biāo)就是盡量生成真實(shí)的數(shù)據(jù)去欺騙判別網(wǎng)絡(luò)D棉钧。而D的目標(biāo)就是盡量把G生成的數(shù)據(jù)和真實(shí)的數(shù)據(jù)分別開來屿脐。這樣,G和D構(gòu)成了一個(gè)動(dòng)態(tài)的“博弈過程”宪卿。在最理想的狀態(tài)下的诵,G可以生成足以“以假亂真”的數(shù)據(jù)G(z)
    傳送門

GAN 代碼實(shí)例

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim

torch.manual_seed(1)
np.random.seed(1)


class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(16, 128),
            nn.LeakyReLU(),
            nn.Dropout(p=0.3),
            nn.Linear(128, 256),
            nn.LeakyReLU(),
            nn.Dropout(p=0.3),
            nn.Linear(256, 512)
        )

    def forward(self, inputs):
        return self.model(inputs)


class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.model = nn.Sequential(
            nn.Linear(512, 256),
            nn.Tanh(),
            nn.Linear(256, 128),
            nn.Tanh(),
            nn.Linear(128, 1),
            nn.Sigmoid()
        )

    def forward(self, inputs):
        return self.model(inputs)


def train():
    G_mean = []
    G_std = []  # 用于記錄生成器生成的數(shù)據(jù)的均值和方差
    data_mean = 3
    data_std = 1  # 目標(biāo)分布的均值和方差
    batch_size = 64
    g_input_size = 16
    g_output_size = 512

    epochs = 1001
    d_epoch = 10  # 每個(gè)epoch判別器的訓(xùn)練輪數(shù)

    # 初始化網(wǎng)絡(luò)
    D = Discriminator()
    G = Generator()

    # 初始化優(yōu)化器和損失函數(shù)
    d_learning_rate = 0.01
    g_learning_rate = 0.001
    ## 定義損失函數(shù) BCELoss()
    loss_func = nn.BCELoss()  # - [p * log(q) + (1-p) * log(1-q)]
    optimiser_D = optim.Adam(D.parameters(), lr=d_learning_rate)
    optimiser_G = optim.Adam(G.parameters(), lr=g_learning_rate)

    for epoch in range(epochs):
        G.train()
        # 訓(xùn)練判別器d_steps次
        for _ in range(d_epoch):
            # 真實(shí)數(shù)據(jù) real_data 輸入D(),得到 d_real
            real_data = torch.tensor(np.random.normal(data_mean, data_std, (batch_size, g_output_size)),
                                     dtype=torch.float)

            # 利用判別器學(xué)習(xí)真實(shí)數(shù)據(jù),D() 函數(shù)將計(jì)算出一列向量 d_real,優(yōu)化的目標(biāo)是使得這列向量 d_real->1
            d_real = D(real_data)
            # 隨機(jī)生成一列偽數(shù)據(jù)
            g_input = torch.rand(batch_size, g_input_size)
            # 利用生成器 G() 生成偽數(shù)據(jù)
            fake_data = G(g_input).detach()  # detach:只生成結(jié)果向量,不參與反向傳播
            # 利用判別器學(xué)習(xí)偽數(shù)據(jù)佑钾,D() 函數(shù)將計(jì)算出一列向量 d_fake,優(yōu)化的目標(biāo)是使得這列向量 d_fake->0
            d_fake = D(fake_data)

            # 計(jì)算損失值,判別器學(xué)習(xí)使得d_real->1,d_fake->0,這里判別器的激活函數(shù)是 Sigmoid()
            # 因此真實(shí)數(shù)據(jù) real_data 的標(biāo)簽為 1; 偽數(shù)據(jù) fake_data 的標(biāo)簽為 0

            # 計(jì)算判別器 D() 所得出真實(shí)數(shù)據(jù)的結(jié)果向量 d_real 與標(biāo)簽 1 的損失
            loss_d_real = loss_func(d_real, torch.ones([batch_size, 1]))
            # 計(jì)算判別器 D() 所得出偽數(shù)據(jù)的結(jié)果向量 d_fake 與標(biāo)簽 0 的損失
            loss_d_fake = loss_func(d_fake, torch.zeros([batch_size, 1]))
            # 總損失為 loss_d_real 和 loss_d_fake 之和
            d_loss = loss_d_real + loss_d_fake

            # 反向傳播,優(yōu)化
            optimiser_D.zero_grad()
            d_loss.backward()
            ## 判別器的優(yōu)化參數(shù)迭代
            optimiser_D.step()

        # 訓(xùn)練生成器
        # 隨機(jī)生成同維度的向量 g_input,利用生成器 G() 生成偽數(shù)據(jù) fake_data
        # 將偽數(shù)據(jù) fake_data 放入判別器 D() 中判斷,生成結(jié)果向量 d_g_fake
        g_input = torch.rand(batch_size, g_input_size)
        fake_data = G(g_input)
        d_g_fake = D(fake_data)

        # GAN 的目的是使得生成器 G() 生成的數(shù)據(jù)接近真實(shí)數(shù)據(jù)
        # 計(jì)算損失值,使得 d_g_fake->1,使得生成器 G() 生成的數(shù)據(jù)能讓判別器 D() 判斷成 “1”
        loss_G = loss_func(d_g_fake, torch.ones([batch_size, 1]))

        # 反向傳播,優(yōu)化
        optimiser_G.zero_grad()
        loss_G.backward()
        optimiser_G.step()
        # 記錄生成器輸出的均值和方差
        G_mean.append(fake_data.mean().item())
        G_std.append(fake_data.std().item())

        if epoch % 10 == 0:
            print("Epoch: {}, 生成數(shù)據(jù)的均值: {}, 生成數(shù)據(jù)的標(biāo)準(zhǔn)差: {}".format(epoch, G_mean[-1], G_std[-1]))
            print('-' * 10)
            G.eval()

if __name__ == '__main__':
    train()

原理:GAN 的基本概念是產(chǎn)生生成器 Generator 和判別器 Discriminator西疤,Generator 負(fù)責(zé)生成偽數(shù)據(jù),而 Discriminator 負(fù)責(zé)判斷 Generator 產(chǎn)生的偽數(shù)據(jù)是否能夠以假亂真休溶。兩者不斷地更新參數(shù)代赁,相互競(jìng)爭(zhēng)
步驟:

  1. 訓(xùn)練Discriminator:首先 Discriminator 需要基于真實(shí)數(shù)據(jù)計(jì)算出真實(shí)數(shù)據(jù)的結(jié)果向量 d_real ,然后基于隨機(jī)生成的數(shù)據(jù)(偽數(shù)據(jù))計(jì)算出偽數(shù)據(jù)的結(jié)果向量 d_fake邮偎,然后基于損失函數(shù)管跺,使得 d_fake 更接近于負(fù)類 0 义黎,d_real 更接近于正類 1
  2. 訓(xùn)練Generator :隨機(jī)生成同維度的向量后禾进,經(jīng)過 Generator 產(chǎn)生結(jié)果向量 fake_data ,然后利用訓(xùn)練好的 Discriminator 判斷 fake_data 是否為 "真實(shí)數(shù)據(jù)":即基于 fake_data 利用 Discriminator 計(jì)算出結(jié)果向量 d_g_fake 廉涕,然后基于損失函數(shù)泻云,使得 d_g_fake 更接近于正類 1,這樣判別器 Discriminator 認(rèn)為 Generator 產(chǎn)生的數(shù)據(jù)都是"真實(shí)數(shù)據(jù)"了狐蜕,此時(shí) Generator 產(chǎn)生的偽數(shù)據(jù)可以達(dá)到以假亂真的效果宠纯,從而可以 Generator 產(chǎn)生的偽數(shù)據(jù)當(dāng)作真實(shí)數(shù)據(jù)

phiaf 代碼

1. 預(yù)處理DNA序列

對(duì)于預(yù)處理DNA序列的腳本,compute_dna_features.py

import numpy as np
import os
import warnings
warnings.filterwarnings("ignore")
import pandas as pd
from sklearn import preprocessing


for mm in ['phage','host']:
    for method in ['Kmer','RCKmer','NAC','DNC','TNC','CKSNAP','PseEIIP']:
        print(mm,method)
        os.system('python /home/software/PHIAF/iLearn/iLearn-nucleotide-basic.py --file /home/rzli/phiaf/all%s_dna_seq.fasta --method %s --format csv --out /home/rzli/phiaf/all%s_seq_%s.csv'%(mm,method,method,mm))


phage1=np.loadtxt('/home/phiaf/allKmer_seq_phage.csv',delimiter=',')[:,1:]
host1=np.loadtxt('/home/phiaf/allKmer_seq_host.csv',delimiter=',')[:,1:]

for method in ['RCKmer','NAC','DNC','TNC','CKSNAP','PseEIIP']:
    phage2=np.loadtxt('/home/phiaf/all'+method+'_seq_phage.csv',delimiter=',')[:,1:]
    host2=np.loadtxt('/home/phiaf/all'+method+'_seq_host.csv',delimiter=',')[:,1:]
    
    # 合并 Kmer层释,RCKmer婆瓜,NAC,DNC贡羔,TNC廉白,CKSNAP,PseEIIP
    phage1=np.hstack((phage1,phage2))
    host1=np.hstack((host1,host2))


## 獲得 phage 和 host 的分類信息
inters=pd.read_csv('/home/phiaf/data_pos_neg.txt',header=None,sep='\t')
phages=[]
hosts=[]
for i in inters.index:
    phages.append(inters.loc[i,0].split(',')[0])
    hosts.append(inters.loc[i,0].split(',')[1])
# 得到 phages 和 host 的 sample 號(hào)
phages=list(set(phages))
hosts=list(set(hosts))


min_max_scaler1 = preprocessing.MinMaxScaler()
# 對(duì) phage1 向量進(jìn)行歸一化
phage_features_norm = min_max_scaler1.fit_transform(phage1)
min_max_scaler2 = preprocessing.MinMaxScaler()
# 對(duì) host1 向量進(jìn)行歸一化
host_features_norm = min_max_scaler2.fit_transform(host1)

# 
for pp in range(len(phages))::
    np.savetxt('/home/phiaf/'+phages[pp]+'.txt',phage_features_norm[pp,:])
for hh in range(len(hosts))::
    np.savetxt('/home/phiaf/'+hosts[hh]+'.txt',host_features_norm[hh,:])

首先 data_pos_neg.txt 長(zhǎng)這樣乖寒,第一列是 phage猴蹂,第二列是 host,第三列的 0 和 1代表 phage與host是否能互作 1 代表能楣嘁;0 代表不能


我們可以了解到磅轻,作者將所有的 host contigs 和 phage contigs 分別合并為 allhost_dna_seq.fasta 和 allphage_dna_seq.fasta

  1. allhost_dna_seq.fasta:三個(gè)不同 host contigs 的 fa 文件合并到一起


  2. allhost_dna_seq.fasta:三個(gè)不同 phage contigs 的 fa 文件合并到一起


  3. Kmers 計(jì)算出來的結(jié)果為:
    host

    每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量

  4. NAC 計(jì)算出來的結(jié)果為:
    host

    每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量

  5. RCKmer 計(jì)算出來的結(jié)果為:
    host

    每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量

  6. DNC 計(jì)算出來的結(jié)果為:
    host

    每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量

  7. TNC 計(jì)算出來的結(jié)果為:
    host

    每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量

  8. CKSNAP 計(jì)算出來的結(jié)果為:
    host

    每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量

  9. PseEIIP 計(jì)算出來的結(jié)果為:
    host

    每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量
    注:phage和host結(jié)果的格式相似

2. 預(yù)處理蛋白質(zhì)序列

import os
import pandas as pd
import numpy as np
import warnings

warnings.filterwarnings("ignore")
from collections import Counter
from Bio.SeqUtils.ProtParam import ProteinAnalysis
from Bio import SeqIO
from sklearn import preprocessing


def file_name(file_dir, gb_fas):
    for root, dirs, files in os.walk(file_dir):
        LL1 = []
        for ff in files:
            if os.path.splitext(ff)[1] == gb_fas:
                LL1.append(os.path.join(ff))
        return LL1


# Encode the AAC feature with the protein sequence
def AAC_feature(fastas):
    AA = 'ACDEFGHIKLMNPQRSTVWY*'
    encodings = []
    header = ['#']
    for i in AA:
        header.append(i)
    encodings.append(header)
    sequence = fastas
    count = Counter(sequence)
    for key in count:
        count[key] = float(count[key]) / len(sequence)
    code = []
    for aa in AA:
        code.append(count[aa])
    encodings.append(code)
    return code

## 計(jì)算蛋白質(zhì)序列理化性質(zhì)的函數(shù)
# Extract the physical-chemical properties from the protein sequence
def physical_chemical_feature(sequence):
    seq_new = sequence.replace('X', '').replace('U', '').replace('B', '').replace('Z', '').replace('J', '')
    CE = 'CHONS'
    ## 理化性質(zhì)參數(shù)
    Chemi_stats = {'A': {'C': 3, 'H': 7, 'O': 2, 'N': 1, 'S': 0},
                   'C': {'C': 3, 'H': 7, 'O': 2, 'N': 1, 'S': 1},
                   'D': {'C': 4, 'H': 7, 'O': 4, 'N': 1, 'S': 0},
                   'E': {'C': 5, 'H': 9, 'O': 4, 'N': 1, 'S': 0},
                   'F': {'C': 9, 'H': 11, 'O': 2, 'N': 1, 'S': 0},
                   'G': {'C': 2, 'H': 5, 'O': 2, 'N': 1, 'S': 0},
                   'H': {'C': 6, 'H': 9, 'O': 2, 'N': 3, 'S': 0},
                   'I': {'C': 6, 'H': 13, 'O': 2, 'N': 1, 'S': 0},
                   'K': {'C': 6, 'H': 14, 'O': 2, 'N': 2, 'S': 0},
                   'L': {'C': 6, 'H': 13, 'O': 2, 'N': 1, 'S': 0},
                   'M': {'C': 5, 'H': 11, 'O': 2, 'N': 1, 'S': 1},
                   'N': {'C': 4, 'H': 8, 'O': 3, 'N': 2, 'S': 0},
                   'P': {'C': 5, 'H': 9, 'O': 2, 'N': 1, 'S': 0},
                   'Q': {'C': 5, 'H': 10, 'O': 3, 'N': 2, 'S': 0},
                   'R': {'C': 6, 'H': 14, 'O': 2, 'N': 4, 'S': 0},
                   'S': {'C': 3, 'H': 7, 'O': 3, 'N': 1, 'S': 0},
                   'T': {'C': 4, 'H': 9, 'O': 3, 'N': 1, 'S': 0},
                   'V': {'C': 5, 'H': 11, 'O': 2, 'N': 1, 'S': 0},
                   'W': {'C': 11, 'H': 12, 'O': 2, 'N': 2, 'S': 0},
                   'Y': {'C': 9, 'H': 11, 'O': 3, 'N': 1, 'S': 0}
                   }

    count = Counter(seq_new)
    code = []

    for c in CE:
        abundance_c = 0
        for key in count:
            num_c = Chemi_stats[key][c]
            abundance_c += num_c * count[key]

        code.append(abundance_c)
    return (code)


## 計(jì)算蛋白質(zhì)分子量的函數(shù)
# calculate the protein molecular for the protein sequnce.
def molecular_weight(seq):
    # 刪除蛋白質(zhì)序列中的 'X' , 'U' , 'B' , 'Z' , 'J'
    seq_new = seq.replace('X', '').replace('U', '').replace('B', '').replace('Z', '').replace('J', '')
    analysed_seq = ProteinAnalysis(seq_new)
    analysed_seq.monoisotopic = True
    mw = analysed_seq.molecular_weight()
    return ([mw])


if __name__ == '__main__':
    inters = pd.read_csv('/home/phiaf/data_pos_neg.txt', header=None, sep='\t')
    phages = []
    hosts = []
    for i in inters.index:
        phages.append(inters.loc[i,0].split(',')[0])
        hosts.append(inters.loc[i,0].split(',')[1])
    phages = list(set(phages))
    hosts = list(set(hosts))

    ####gb file is download from NCBI
    phage_features = []
    for pp in phages:
        print(pp)
        a = []
        filepath = '/home/phiaf/phagegb/' + pp + '.gb'
        for record1 in SeqIO.parse(filepath, "genbank"):
            if (record1.features):
                myseq1 = record1.seq
                for feature1 in record1.features:
                    ## 提取 phage gbk 文件的 CDS translation 后的序列(蛋白質(zhì)序列)
                    if feature1.type == "CDS" and 'translation' in feature1.qualifiers:
                        seq1 = feature1.qualifiers['translation'][0]
                        ## 計(jì)算蛋白質(zhì)序列的理化性質(zhì), 分子量和 AAC 特征, 每條蛋白質(zhì)序列都計(jì)算一次
                        a.append(physical_chemical_feature(seq1) + molecular_weight(seq1) + AAC_feature(seq1))
        xx = np.array(a)
        phage_features.append(xx.mean(axis=0).tolist() + xx.max(axis=0).tolist() + xx.min(axis=0).tolist() +
                              xx.std(axis=0).tolist() + xx.var(axis=0).tolist() + np.median(xx, axis=0).tolist())

        print(phage_features)
    host_features = []
    for hh in hosts:
        print(hh)
        a = []
        filepath = '/home/phiaf/hostgb/' + hh + '.gb'
        for record1 in SeqIO.parse(filepath, "genbank"):
            if (record1.features):
                myseq1 = record1.seq
                for feature1 in record1.features:
                    ## 提取 phage gbk 文件的 CDS translation 后的序列(蛋白質(zhì)序列)
                    if feature1.type == "CDS" and 'translation' in feature1.qualifiers:
                        seq1 = feature1.qualifiers['translation'][0]
                        ## 計(jì)算蛋白質(zhì)序列的理化性質(zhì), 分子量和 AAC 特征, 每條蛋白質(zhì)序列都計(jì)算一次
                        a.append(physical_chemical_feature(seq1) + molecular_weight(seq1) + AAC_feature(seq1))
        xx = np.array(a)
        host_features.append(xx.mean(axis=0).tolist() + xx.max(axis=0).tolist() + xx.min(axis=0).tolist() +
                             xx.std(axis=0).tolist() + xx.var(axis=0).tolist() + np.median(xx, axis=0).tolist())
        print(host_features)


    ###save and normalize features
    min_max_scaler1 = preprocessing.MinMaxScaler()
    ## 向量歸一化
    phage_features_norm = min_max_scaler1.fit_transform(phage_features)
    min_max_scaler2 = preprocessing.MinMaxScaler()
    ## 向量歸一化
    host_features_norm = min_max_scaler2.fit_transform(host_features)
    for pp in range(3):
        np.savetxt('/home/phiaf/phage_protein_' + phages[pp] + '.txt', phage_features_norm[pp, :])
    for hh in range(3):
        np.savetxt('/home/phiaf/host_protein_' + hosts[hh] + '.txt', host_features_norm[hh, :])

每一個(gè) gbk 文件生成:

形如這樣的一列向量

3. 預(yù)處理的結(jié)果

對(duì)于 DNA 預(yù)處理后的結(jié)果(這里用3個(gè)contig為例子)



每一個(gè) contig 將會(huì)生成一列向量:


對(duì)于 protein 預(yù)處理后的結(jié)果(這里用3個(gè)contig為例子)



每一個(gè) contig 中所有 CDS 的蛋白質(zhì)序列合起來將會(huì)生成一列向量:


4. 產(chǎn)生pseudo數(shù)據(jù)

代碼:
step 1:定義初始函數(shù)以及讀取文件

import os, sys
sys.path.append(os.getcwd())
import random
random.seed(1)
import numpy as np
import pandas as pd
import torch
import torch.autograd as autograd
import torch.nn as nn
import torch.optim as optim
torch.manual_seed(1)
from sklearn.model_selection import LeaveOneOut
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
import warnings
warnings.filterwarnings("ignore")


def obtainfeatures(data, file_path1, strs):
    host_features = []
    for i in data:
        host_features.append(np.loadtxt(file_path1 + i + strs).tolist())
    return np.array(host_features)


class Generator(nn.Module):
    def __init__(self, shape1):
        super(Generator, self).__init__()

        main = nn.Sequential(
            nn.Linear(shape1, 128),
            nn.ReLU(True),
            nn.Linear(128, 256),
            nn.ReLU(True),
            nn.Linear(256, 512),
            nn.ReLU(True),
            nn.Linear(512, 1024),
            nn.Tanh(),
            nn.Linear(1024, shape1),
        )
        # 執(zhí)行 main 函數(shù)
        self.main = main

    def forward(self, noise):
        output = self.main(noise)
        return output



class Discriminator(nn.Module):
    def __init__(self, shape1):
        super(Discriminator, self).__init__()

        self.fc1 = nn.Linear(shape1, 512)
        self.relu = nn.LeakyReLU(0.2)
        self.fc2 = nn.Linear(512, 256)
        self.relu = nn.LeakyReLU(0.2)
        self.fc3 = nn.Linear(256, 128)
        self.relu = nn.LeakyReLU(0.2)
        self.fc4 = nn.Linear(128, 1)

    def forward(self, inputs):
        out = self.fc1(inputs)
        out = self.relu(out)
        out = self.fc2(out)
        out = self.relu(out)
        out = self.fc3(out)
        out = self.relu(out)
        out = self.fc4(out)
        ## .view(-1)平鋪成一維向量
        return out.view(-1)

# 定義生成模型 netG 和判別模型 netD 每一層的初始化權(quán)重參數(shù)
def weights_init(m):
    classname = m.__class__.__name__
    if classname.find('Linear') != -1:
        m.weight.data.normal_(0.0, 0.02)
        m.bias.data.fill_(0)
    elif classname.find('BatchNorm') != -1:
        m.weight.data.normal_(1.0, 0.02)
        m.bias.data.fill_(0)


# 讀取訓(xùn)練數(shù)據(jù)的函數(shù)
def inf_train_gen(datas):
    with open('/home/rzli/phiaf/result/' + datas + '.txt') as f:
        MatrixFeaturesPositive = [list(x.split(" ")) for x in f]
    FeaturesPositive = [line[:] for line in MatrixFeaturesPositive[:]]
    dataset2 = np.array(FeaturesPositive, dtype='float32')
    return dataset2

## 定義懲罰項(xiàng)函數(shù)
def calc_gradient_penalty(netD, real_data, fake_data):
    alpha = torch.rand(BATCH_SIZE, 1)
    alpha = alpha.expand(real_data.size())
    alpha = alpha.cuda() if use_cuda else alpha
    interpolates = alpha * real_data + ((1 - alpha) * fake_data)
    if use_cuda:
        interpolates = interpolates.cuda()
    interpolates = autograd.Variable(interpolates, requires_grad=True)
    disc_interpolates = netD(interpolates)
    gradients = autograd.grad(outputs=disc_interpolates, inputs=interpolates,
                              grad_outputs=torch.ones(disc_interpolates.size()).cuda() if use_cuda else torch.ones(
                                  disc_interpolates.size()), create_graph=True, retain_graph=True, only_inputs=True)[0]
    gradient_penalty = ((gradients.norm(2, dim=1) - 1) ** 2).mean() * LAMBDA
    return gradient_penalty


# 讀取第3步的數(shù)據(jù)列表 data_pos_neg.txt
data = pd.read_csv('/home/phiaf/data_pos_neg.txt', header=None, sep=',')
# 將 phage 能與 host 互作的互作對(duì)取出珍逸,即 data_pos_neg.txt 第三列數(shù)值為 1 
data = data[data[2] == 1].values.tolist()

# 分別獲得 phage 能與 host 互作的互作對(duì)中,phage 的 contig 編號(hào)和 host 的 contig 編號(hào)
## 獲得 phage 的 contig 編號(hào)
phage = [i[0] for i in data]
## 獲得 host 的 contig 編號(hào)
host = [i[1] for i in data]

# 讀取第3步所計(jì)算出來的 dna 和 protein 特征(每個(gè) phage 和 host 對(duì)應(yīng)的 contig 均含有 dna 和 protein 的一列特征向量)
phage_feature_pro = obtainfeatures(phage, '/home/phiaf/phage_protein_norm_features/protein_', '.txt')
phage_feature_dna = obtainfeatures(phage, '/home/phiaf/phage_dna_norm_features/dna_', '.txt')
host_feature_pro = obtainfeatures(host, '/home/phiaf/host_protein_norm_features/protein_', '.txt')
host_feature_dna = obtainfeatures(host, '/home/phiaf/host_dna_norm_features/dna_', '.txt')

# 將 phage 的 dna 和 protein 的特征向量進(jìn)行合并
phage_all = np.concatenate((phage_feature_dna, phage_feature_pro), axis=1)
# 將 host 的 dna 和 protein 的特征向量進(jìn)行合并
host_all = np.concatenate((host_feature_dna, host_feature_pro), axis=1)

###save features of real positive samples
# 將合并后的 phage 和 host 的特征合并到一起(全部合并為一列向量)聋溜,并儲(chǔ)存谆膳,此時(shí) data_GAN.txt 代表了可以互作的 phage 和 host 全部的 dna 和 protein 特征(一列向量)
np.savetxt('/home/phiaf/result/data_GAN.txt', np.concatenate((phage_all, host_all), axis=1))

此時(shí) data_GAN.txt 代表了可以互作的 phage 和 host 全部的 dna 和 protein 特征(一列向量)

step 2:生成pseudo數(shù)據(jù):

data = inf_train_gen('data_GAN')
FIXED_GENERATOR = False
LAMBDA = .1
CRITIC_ITERS = 5
BATCH_SIZE = len(data)
ITERS = 10000
use_cuda = False

## 實(shí)例化一個(gè)對(duì)象,生成 G 網(wǎng)絡(luò)
netG = Generator(data.shape[1])
netD = Discriminator(data.shape[1])
netD.apply(weights_init)
netG.apply(weights_init)

optimizerD = optim.Adam(netD.parameters(), lr=1e-4, betas=(0.5, 0.9))
optimizerG = optim.Adam(netG.parameters(), lr=1e-4, betas=(0.5, 0.9))
one = torch.tensor(1, dtype=torch.float)  ###torch.FloatTensor([1])
mone = one * -1


for iteration in range(ITERS):
    print(iteration)
    for p in netD.parameters():
        # 要求每一輪運(yùn)算完成需要更新權(quán)重參數(shù)撮躁,使得預(yù)測(cè)值與真實(shí)值的誤差盡可能小
        ## requires_grad=True 的作用是讓 backward 可以追蹤這個(gè)參數(shù)并且計(jì)算它的梯度, 與計(jì)算損失函數(shù)的鏈?zhǔn)角髮?dǎo)有關(guān)(參與誤差反向傳播, 要不要計(jì)算梯度)
        p.requires_grad = True
    ## 讀取可以互作的 phage 和 host 全部的 dna 和 protein 特征(一列向量), data_GAN.txt
    data = inf_train_gen('data_GAN')
    ## 將 data_GAN.txt 轉(zhuǎn)換成 torch 語法的 tensor
    real_data = torch.FloatTensor(data)

    # 定義一個(gè) Variable 存放 data_GAN.txt 變量摹量,real_data_v 為真實(shí)的正樣本
    real_data_v = autograd.Variable(real_data)
    # 隨機(jī)生成一個(gè)張量 (1 行 864 列的張量),正態(tài)分布均值為0馒胆,方差為1缨称,即高斯白噪聲
    noise = torch.randn(BATCH_SIZE, data.shape[1])
    # 定義一個(gè) Variable 存放 noise 變量
    noisev = autograd.Variable(noise, volatile=True)
    # 定義一個(gè) Variable 存放生成的 pseudo 數(shù)據(jù)
    fake = autograd.Variable(netG(noisev).data)
    # 將 pseudo 數(shù)據(jù)轉(zhuǎn)換為矩陣
    fake_output=fake.data.cpu().numpy()

    ## 訓(xùn)練判別器 netD()
    for iter_d in range(CRITIC_ITERS):
        #  netD 梯度清零
        netD.zero_grad()
        # 判別器 netD() 讀取真實(shí)的正樣本數(shù)據(jù),并生成一列結(jié)果向量
        D_real = netD(real_data_v)
        # 轉(zhuǎn)換為均值
        D_real = D_real.mean()


        # 隨機(jī)生成一個(gè)噪聲張量 (1 行 864 列的張量)祝迂,正態(tài)分布均值為0睦尽,方差為1,即高斯白噪聲
        noise = torch.randn(BATCH_SIZE, data.shape[1])
        # 定義一個(gè) Variable 存放隨機(jī)生成的數(shù)據(jù)(向量)型雳,1 行 864 列的張量可以理解為有 a1 ...... a864 個(gè)變量( 見 tip 5)
        noisev = autograd.Variable(noise, volatile=True)
        # 定義一個(gè) Variable 存放生成的 pseudo 數(shù)據(jù)当凡,pseudo 數(shù)據(jù)是由生成器 netG 基于隨機(jī)向量 noisev 生成
        fake = autograd.Variable(netG(noisev).data)
        inputv = fake
        ##  判別器 netD() 讀取生成器 netG 生成的 pseudo 數(shù)據(jù),并生成一列結(jié)果向量
        D_fake = netD(inputv)
        ## 轉(zhuǎn)換為均值
        D_fake = D_fake.mean()

        ## 計(jì)算懲罰項(xiàng)
        gradient_penalty = calc_gradient_penalty(netD, real_data_v.data, fake.data)
       ## 計(jì)算損失函數(shù)纠俭,目的是使得 pseudo 數(shù)據(jù) D_fake 與真實(shí)數(shù)據(jù) D_real 的誤差縮小
        D_cost = D_fake - D_real + gradient_penalty
        Wasserstein_D = D_real - D_fake
        D_cost.backward()
        # 對(duì)優(yōu)化器參數(shù)進(jìn)行更新
        optimizerD.step()

    ## 訓(xùn)練生成器 netG
    if not FIXED_GENERATOR:
        for p in netD.parameters():
            p.requires_grad = False
        netG.zero_grad()
        
        # 讀取真實(shí)的正樣本數(shù)據(jù)
        real_data = torch.Tensor(data)        
        real_data_v = autograd.Variable(real_data)
        ## 轉(zhuǎn)換為均值
        real_data_v_G = real_data_v.mean()
          
        # 隨機(jī)生成一列向量
        noise = torch.randn(BATCH_SIZE, data.shape[1])
        # 基于隨機(jī)生成一列向量構(gòu)造 pseudo 數(shù)據(jù) fake
        noisev = autograd.Variable(noise)
        fake = netG(noisev)
        # 由判別器 netD 判斷 pseudo 數(shù)據(jù) fake沿量,判別器 netD 將會(huì)計(jì)算出一列結(jié)果向量 G
        G = netD(fake)
        G = G.mean()

        ## 構(gòu)造損失函數(shù)
        G_cost = G -  real_data_v_G
        ## 反向傳播
        G_cost.backward()
        optimizerG.step()

    ###save generated sample features every 200 iteration
    if iteration%200 == 0:
        fake_writer = open("/home/phiaf/result/Iteration_"+str(iteration)+".txt","w")
        for rowIndex in range(len(fake_output)):
            for columnIndex in range(len(fake_output[0])):
                fake_writer.write(str(fake_output[rowIndex][columnIndex]) + ",")
            fake_writer.write("\n")
        fake_writer.flush()
        fake_writer.close()

requires_grad=True 的解釋 的作用是讓 backward 可以追蹤這個(gè)參數(shù)并且計(jì)算它的梯度, 與計(jì)算損失函數(shù)的鏈?zhǔn)角髮?dǎo)有關(guān)(參與誤差反向傳播, 要不要計(jì)算梯度)

這個(gè)例子中作者將判別器 netD 的損失函數(shù)定義為 D_fake - D_real + gradient_penalty,其中 D_fake 和 D_real 為將一列向量的元素均值化后的值(標(biāo)量)冤荆,gradient_penalty 為懲罰項(xiàng)(標(biāo)量)朴则,D_fake 為判別器 netD 基于偽數(shù)據(jù)生成的結(jié)果,D_real 為為真實(shí)的正樣本結(jié)果钓简,而判別器 netD 的目的是能夠更加精細(xì)的區(qū)分偽數(shù)據(jù)和真實(shí)正樣本
生成器 netG 的損失函數(shù)定義為 G_cost = G - real_data_v_G乌妒,其中 G 和 real_data_v_G 為將一列向量的元素均值化后的值(標(biāo)量),G 為判別器 netD 基于偽數(shù)據(jù)生成的結(jié)果外邓,real_data_v_G 為真實(shí)的正樣本結(jié)果撤蚊,生成器 netG 的目的是能夠盡可能使產(chǎn)生的偽數(shù)據(jù)接近真實(shí)正樣本,以騙過判別器 netD 的判斷

step 3 檢驗(yàn)生成的偽數(shù)據(jù)的真實(shí)性:

####test model result, LOOCV to select optimal pseudo samples
with open("../result/result_GAN/data_GAN.txt") as f:
    MatrixFeatures = [list(x.split(" ")) for x in f]
realFeatures = [line[:] for line in MatrixFeatures[:]]
realDataset = np.array(realFeatures, dtype='float32')
# Adding equal numbers of binary labels
label=[]
for rowIndex in range(len(realDataset)):
    label.append(1)
for rowIndex in range(len(realDataset)):
    label.append(0)
labelArray=np.asarray(label)
opt_diff_accuracy_05=0.5
opt_Epoch=0
opt_accuracy=0
allresult=[]
for indexEpoch in range(500):
    epoch = indexEpoch * 200
    with open("../result/result_GAN/Iteration_"+str(epoch)+".txt") as f:
          MatrixFeatures = [list(x.split(",")) for x in f]
    fakeFeatures = [line[:-1] for line in MatrixFeatures[:]]
    fakedataset = np.array(fakeFeatures, dtype='float32')
    realFakeFeatures=np.vstack((realDataset, fakedataset))

    prediction_list=[]
    real_list=[]
    ####LOOCV
    loo = LeaveOneOut()
    loo.get_n_splits(realFakeFeatures)
    for train_index, test_index in loo.split(realFakeFeatures):
        X_train, X_test = realFakeFeatures[train_index], realFakeFeatures[test_index]
        y_train, y_test = labelArray[train_index], labelArray[test_index]
        knn = KNeighborsClassifier(n_neighbors=1).fit(X_train, y_train)
        predicted_y = knn.predict(X_test)
        prediction_list.append(predicted_y)
        real_list.append(y_test)
    accuracy=accuracy_score(real_list, prediction_list)
    allresult.append(str(indexEpoch)+"%"+str(accuracy))
    diff_accuracy_05=abs(accuracy-0.5)
    if diff_accuracy_05 < opt_diff_accuracy_05:
        opt_diff_accuracy_05=diff_accuracy_05
        opt_Epoch=epoch
        opt_accuracy=accuracy
print(str(opt_Epoch)+"%"+str(opt_accuracy))

由于每訓(xùn)練200輪损话,將會(huì)輸出偽數(shù)據(jù)侦啸,這一步的目的是檢測(cè)輸出的所有偽數(shù)據(jù)哪一些更接近真實(shí)的正樣本

小tips

[1]. 實(shí)例化生成模型(基于pytorch語法)
class Generator(nn.Module):
    def __init__(self, shape1):
        super(Generator, self).__init__()
        main = nn.Sequential(
            nn.Linear(shape1, 128),
            nn.ReLU(True),
            nn.Linear(128, 256),
            nn.ReLU(True),
            nn.Linear(256, 512),
            nn.ReLU(True),
            nn.Linear(512, 1024),
            nn.Tanh(),
            nn.Linear(1024, shape1),
        )
        self.main = main

    def forward(self, noise, real_data):
         output = self.main(noise)
         return output

## 實(shí)例化 G 網(wǎng)絡(luò)
netG = Generator(data.shape[1])
netD.apply(weights_init)

# 計(jì)算
netG(noisev, real_data_v)
# 等價(jià)于
netG.forward(noisev, real_data_v)

事實(shí)上netG(noisev)netG.forward(noisev),當(dāng)傳入數(shù)據(jù)noisevreal_data_v時(shí)執(zhí)行的是:

 main = nn.Sequential(
            nn.Linear(shape1, 128),
            nn.ReLU(True),
            nn.Linear(128, 256),
            nn.ReLU(True),
            nn.Linear(256, 512),
            nn.ReLU(True),
            nn.Linear(512, 1024),
            nn.Tanh(),
            nn.Linear(1024, shape1),
        )

其中:

class Generator(nn.Module):
    def __init__(self, shape1):
        super(Generator, self).__init__()
        main = nn.Sequential(
            nn.Linear(shape1, 128),
            nn.ReLU(True),
            nn.Linear(128, 256),
            nn.ReLU(True),
            nn.Linear(256, 512),
            nn.ReLU(True),
            nn.Linear(512, 1024),
            nn.Tanh(),
            nn.Linear(1024, shape1),
        )
        # 執(zhí)行 main 函數(shù)
        self.main = main

    def forward(self, noise):
        output = self.main(noise)
        return output

# self.main = main 代表執(zhí)行 main 函數(shù)
[2]. 生成模型 netG 結(jié)構(gòu)
netG = Generator(data.shape[1])
netG.apply(weights_init)

print(netG)
print(list(netG.parameters()))

netG 的結(jié)構(gòu)以及每一層結(jié)構(gòu)對(duì)應(yīng)的初始化權(quán)重參數(shù):

# netG 結(jié)構(gòu)
Generator(
  (main): Sequential(
    (0): Linear(in_features=864, out_features=128, bias=True)
    (1): ReLU(inplace=True)
    (2): Linear(in_features=128, out_features=256, bias=True)
    (3): ReLU(inplace=True)
    (4): Linear(in_features=256, out_features=512, bias=True)
    (5): ReLU(inplace=True)
    (6): Linear(in_features=512, out_features=1024, bias=True)
    (7): Tanh()
    (8): Linear(in_features=1024, out_features=864, bias=True)
  )
)

# 每一層結(jié)構(gòu)對(duì)應(yīng)的初始化權(quán)重參數(shù)
Parameter containing:
## Linear(in_features=864, out_features=128, bias=True)
tensor([[ 1.2168e-02,  2.7353e-02, -2.8277e-02,  ...,  3.2443e-02,
          1.5985e-02,  1.2108e-02],
        [-7.0914e-03,  9.4568e-03,  1.0394e-02,  ..., -1.8338e-02,
          3.2946e-03,  2.6501e-02],
        [ 1.4687e-02, -1.5824e-02,  7.3161e-03,  ..., -1.7613e-02,
          1.1925e-02, -1.0545e-02],
        ...,
        [-8.8383e-03,  1.6274e-02, -2.6005e-02,  ...,  4.1564e-03,
         -9.5081e-03,  2.6123e-02],
        [ 1.1470e-02,  1.8002e-02,  1.0864e-02,  ...,  4.7736e-03,
          2.2449e-02,  1.4833e-02],
        [-1.7769e-02,  3.5312e-03, -4.9738e-03,  ..., -3.7618e-05,
         -1.9576e-03, -1.5175e-02]], requires_grad=True), 

Parameter containing:
## ReLU(inplace=True)
tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0.], requires_grad=True), 

Parameter containing:
## Linear(in_features=128, out_features=256, bias=True)
tensor([[-0.0110, -0.0047, -0.0027,  ...,  0.0064, -0.0110, -0.0324],
        [-0.0061, -0.0023,  0.0250,  ...,  0.0150,  0.0245,  0.0244],
        [ 0.0337,  0.0291,  0.0137,  ..., -0.0081,  0.0202,  0.0076],
        ...,
        [-0.0120, -0.0140, -0.0303,  ...,  0.0014, -0.0031, -0.0026],
        [ 0.0397,  0.0014,  0.0304,  ...,  0.0357,  0.0148,  0.0075],
        [ 0.0048, -0.0095,  0.0259,  ..., -0.0096, -0.0033, -0.0228]],
       requires_grad=True), 

Parameter containing:
##  ReLU(inplace=True)
tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       requires_grad=True), 

Parameter containing:
## Linear(in_features=256, out_features=512, bias=True)
tensor([[-0.0268, -0.0256, -0.0018,  ..., -0.0122,  0.0229, -0.0120],
        [-0.0108, -0.0052, -0.0068,  ..., -0.0083, -0.0047, -0.0065],
        [-0.0063,  0.0129,  0.0254,  ..., -0.0007, -0.0366,  0.0254],
        ...,
        [ 0.0277, -0.0060, -0.0177,  ..., -0.0341, -0.0216, -0.0029],
        [-0.0086,  0.0132,  0.0023,  ...,  0.0351, -0.0320, -0.0139],
        [ 0.0134,  0.0028,  0.0324,  ..., -0.0345, -0.0102, -0.0134]],
       requires_grad=True), 

Parameter containing:
## ReLU(inplace=True)
tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0.], requires_grad=True), 

Parameter containing:
## Linear(in_features=512, out_features=1024, bias=True)
tensor([[-5.3577e-03,  2.1187e-02, -2.2485e-04,  ..., -7.8326e-03,
         -1.8492e-02, -3.6416e-02],
        [-2.6918e-02, -1.3238e-02,  2.0151e-02,  ..., -1.5236e-02,
         -3.0986e-02,  2.2858e-02],
        [ 1.4550e-02, -2.4193e-02,  3.8080e-03,  ..., -1.0529e-02,
          3.5056e-02, -2.2059e-02],
        ...,
        [ 1.4448e-03,  8.5981e-03, -1.6759e-02,  ..., -2.5140e-02,
         -1.8255e-03,  2.2529e-02],
        [ 5.2836e-02,  1.0386e-02,  3.1571e-03,  ...,  1.7078e-02,
         -7.2594e-03, -9.8481e-05],
        [ 3.8155e-02,  2.8551e-02,  3.2344e-02,  ...,  1.6333e-02,
          9.4571e-03, -1.7940e-02]], requires_grad=True), 

Parameter containing:
## Tanh()
tensor([0., 0., 0.,  ..., 0., 0., 0.], requires_grad=True), Parameter containing:
tensor([[ 0.0008, -0.0073, -0.0042,  ...,  0.0212, -0.0095, -0.0055],
        [-0.0201,  0.0373, -0.0154,  ...,  0.0138, -0.0221, -0.0035],
        [ 0.0181, -0.0185,  0.0333,  ..., -0.0085, -0.0107, -0.0146],
        ...,
        [ 0.0038,  0.0019,  0.0083,  ..., -0.0050, -0.0071,  0.0334],
        [-0.0236,  0.0136,  0.0231,  ..., -0.0035,  0.0250, -0.0042],
        [-0.0132, -0.0127,  0.0002,  ..., -0.0085,  0.0274, -0.0171]],
       requires_grad=True), 

Parameter containing:
## Linear(in_features=1024, out_features=864, bias=True)
tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       requires_grad=True)

顯而易見丧枪,本例子中的生成模型 netG 一共有 8 層

[3]. 初始化模型每一層的權(quán)重參數(shù)

注意到:

# 定義生成模型 netG 和判別模型 netD 每一層的初始化權(quán)重參數(shù)
def weights_init(m):
    classname = m.__class__.__name__
    ## 對(duì)每一層全連接層 Linear 的權(quán)重進(jìn)行初始化
    if classname.find('Linear') != -1:
        m.weight.data.normal_(0.0, 0.02)
        m.bias.data.fill_(0)
    elif classname.find('BatchNorm') != -1:
        m.weight.data.normal_(1.0, 0.02)
        m.bias.data.fill_(0)

作者在這里定義了對(duì)每一層全連接層 Linear 的權(quán)重進(jìn)行初始化

所有的層:

  1. Discriminator:Linear光涂,LeakyReLU,Linear豪诲,Linear顶捷,Linear
  2. Generator:Linear,ReLU屎篱,Linear服赎,ReLU葵蒂,Linear,ReLU重虑,Linear践付,Tanh,Linear
[4]. 定義容器存放變量
real_data_v = autograd.Variable(real_data)
noisev = autograd.Variable(noise, volatile=True)
fake = autograd.Variable(netG(noisev).data)

Variable 的作用是定義一個(gè)容器存放變量缺厉,用作 pytorch 每一輪運(yùn)算更新存入變量用


[5]. backward 用法
a = torch.randn(1, 10)
a = autograd.Variable(a,requires_grad = True)

one = torch.tensor(1, dtype=torch.float)
b = a.mean()
b.backward(one)

print(a)
print(a[0,2])
print(b)
print(one)
print(b.data)
print(a.grad)

# result
tensor([[ 0.6614,  0.2669,  0.0617,  0.6213, -0.4519, -0.1661, -1.5228,  0.3817,
         -1.0276, -0.5631]], requires_grad=True)
tensor(0.0617, grad_fn=<SelectBackward0>)
tensor(-0.1739, grad_fn=<MeanBackward0>)
tensor(1.)
tensor(-0.1739)
tensor([[0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000,
         0.1000]])

上述例子求導(dǎo)過程:
將變量 a 的元素想象成變量永高,該例子一共 a1,a2提针,a3.........a10個(gè)變量命爬,b = a.mean() 代表構(gòu)造函數(shù) f = (a1+a2+a3+.........+a10) / 10,然后利用函數(shù) f 依次對(duì)a1辐脖,a2饲宛,a3.........a10求偏導(dǎo),所得的偏導(dǎo)結(jié)果任然為一列向量 tensor([[0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000, 0.1000,0.1000]])

作為backward的參數(shù)one嗜价,one = tensor(1.) 意思是利用函數(shù) f 依次對(duì)a1艇抠,a2,a3.........a10求偏導(dǎo)的結(jié)果保存為一列向量(向量維度為變量 an 數(shù))

若:

a = torch.randn(1, 10)
a = autograd.Variable(a,requires_grad = True)

one = torch.tensor(1, dtype=torch.float)
mone = one * -1
b = a.mean()
b.backward(mone)

print(a.grad)

# result
tensor([[-0.1000, -0.1000, -0.1000, -0.1000, -0.1000, -0.1000, -0.1000, -0.1000,
         -0.1000, -0.1000]])

如果backward的參數(shù)one久锥,one = tensor(-1.)家淤,意味著利用函數(shù) f 依次對(duì)a1,a2瑟由,a3.........a10求偏導(dǎo)的結(jié)果保存為一列向量(向量維度為變量 an 數(shù))絮重,它的結(jié)果取相反數(shù)

其他例子參考:https://www.cnblogs.com/JeasonIsCoding/p/10164948.html

[6]. 關(guān)于生成器 G 生成數(shù)據(jù)的取值范圍

關(guān)于生成器 G 生成 fake 數(shù)據(jù)的值域問題,這個(gè) fake 值域問題取決于 real 的值域错妖,GAN 的目的是使得 fake 向量與 real 向量盡量相似绿鸣,因此如果 real 的值域介于 0-1 ,那么生成器 G 的最后一層可以加一個(gè)sigmoid函數(shù)暂氯;如果 real 的值域?yàn)檎龜?shù) ,那么生成器 G 的最后一層可以加一個(gè)relu函數(shù)亮蛔;如果 real 的值域?yàn)檎龜?shù) 痴施,那么生成器 G 的最后一層可以加一個(gè)relu函數(shù);如果 real 的值域?yàn)?-1 到 1 究流,那么生成器 G 的最后一層可以加一個(gè)tanh函數(shù)

一般來說辣吃,初始化的生成器 G 和判別器 D 需要對(duì) linear 層進(jìn)行參數(shù)的初始化( Y = X·W + b,初始化參數(shù) W)否則參數(shù)可能為 NA芬探。

def weights_init(m):
    classname = m.__class__.__name__
    if classname.find('Linear') != -1:
        m.weight.data.normal_(0.0, 0.02)
        m.bias.data.fill_(0)
    elif classname.find('BatchNorm') != -1:
        m.weight.data.normal_(1.0, 0.02)
        m.bias.data.fill_(0)

# 對(duì) W 進(jìn)行初始化
m.weight.data.normal_(0.0, 0.02)
# 對(duì)截距 b 進(jìn)行初始化
m.bias.data.fill_(0)

神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)通常是一層線性函數(shù)(linear)加一層非線性函數(shù)(relu神得,sigmoid,tanh)偷仿,否則相當(dāng)于只有一層哩簿,神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)(以Relu與linear為例宵蕉,嵌套):


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市节榜,隨后出現(xiàn)的幾起案子羡玛,更是在濱河造成了極大的恐慌,老刑警劉巖宗苍,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稼稿,死亡現(xiàn)場(chǎng)離奇詭異褒链,居然都是意外死亡乏屯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門复凳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丽啡,“玉大人是越,你說我怎么就攤上這事÷瞪希” “怎么了倚评?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)馏予。 經(jīng)常有香客問我天梧,道長(zhǎng),這世上最難降的妖魔是什么霞丧? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任呢岗,我火速辦了婚禮,結(jié)果婚禮上蛹尝,老公的妹妹穿的比我還像新娘后豫。我一直安慰自己,他們只是感情好突那,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布挫酿。 她就那樣靜靜地躺著,像睡著了一般愕难。 火紅的嫁衣襯著肌膚如雪早龟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天猫缭,我揣著相機(jī)與錄音葱弟,去河邊找鬼。 笑死猜丹,一個(gè)胖子當(dāng)著我的面吹牛芝加,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播射窒,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼藏杖,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼将塑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起制市,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤抬旺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后祥楣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體开财,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年误褪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了责鳍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兽间,死狀恐怖历葛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嘀略,我是刑警寧澤恤溶,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站帜羊,受9級(jí)特大地震影響咒程,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜讼育,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一帐姻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧奶段,春花似錦饥瓷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至词裤,卻和暖如春刺洒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吼砂。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鼎文,地道東北人渔肩。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拇惋,于是被迫代替她去往敵國(guó)和親周偎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抹剩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容