前言
閱讀文獻(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)植康。正如它的名字所暗示的那樣旷太,它們的功能分別是:
- G是一個(gè)生成數(shù)據(jù)的網(wǎng)絡(luò),它接收一個(gè)隨機(jī)的噪聲z销睁,通過這個(gè)噪聲生成數(shù)據(jù)供璧,記做G(z)。
- 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)
步驟:
- 訓(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
- 訓(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
allhost_dna_seq.fasta:三個(gè)不同 host contigs 的 fa 文件合并到一起
allhost_dna_seq.fasta:三個(gè)不同 phage contigs 的 fa 文件合并到一起
- Kmers 計(jì)算出來的結(jié)果為:
每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量
- NAC 計(jì)算出來的結(jié)果為:
每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量
- RCKmer 計(jì)算出來的結(jié)果為:
每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量
- DNC 計(jì)算出來的結(jié)果為:
每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量
- TNC 計(jì)算出來的結(jié)果為:
每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量
- CKSNAP 計(jì)算出來的結(jié)果為:
每一個(gè) host(phage)的contigs 將會(huì)計(jì)算出一列向量
- PseEIIP 計(jì)算出來的結(jié)果為:
每一個(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ù)noisev
和real_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)行初始化
所有的層:
- Discriminator:Linear光涂,LeakyReLU,Linear豪诲,Linear顶捷,Linear
- 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為例宵蕉,嵌套):