first commit
							
								
								
									
										2
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,2 @@ | |||||||
|  | # Auto detect text files and perform LF normalization | ||||||
|  | * text=auto | ||||||
							
								
								
									
										20
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,20 @@ | |||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ##  代码运行 | ||||||
|  | 
 | ||||||
|  | 在本目录下,在命令行中执行下面的命令: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | python main.py -c ./utils/conf.json | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | - 联邦训练配置:一共10台客户端设备(no\_models=10),每一轮任意挑选其中的5台参与训练(k=5), 每一次本地训练迭代次数为3次(local\_epochs=3),全局迭代次数为20次(global\_epochs=20)。 | ||||||
|  | 
 | ||||||
|  | - 集中式训练配置:我们不需要单独编写集中式训练代码,只需要修改联邦学习配置既可使其等价于集中式训练。具体来说,我们将客户端设备no\_models和每一轮挑选的参与训练设备数k都设为1即可。这样只有1台设备参与的联邦训练等价于集中式训练。其余参数配置信息与联邦学习训练一致。图中我们将局部迭代次数分别设置了1,2,3来进行比较。 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										108
									
								
								cbam.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,108 @@ | |||||||
|  | '''Convolutional Block Attention Module (CBAM) | ||||||
|  | ''' | ||||||
|  | 
 | ||||||
|  | import torch | ||||||
|  | import torch.nn as nn | ||||||
|  | from torch.nn.modules import pooling | ||||||
|  | from torch.nn.modules.flatten import Flatten | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Channel_Attention(nn.Module): | ||||||
|  |     '''Channel Attention in CBAM. | ||||||
|  |     ''' | ||||||
|  | 
 | ||||||
|  |     def __init__(self, channel_in, reduction_ratio=16, pool_types=['avg', 'max']): | ||||||
|  |         '''Param init and architecture building. | ||||||
|  |         ''' | ||||||
|  | 
 | ||||||
|  |         super(Channel_Attention, self).__init__() | ||||||
|  |         self.pool_types = pool_types | ||||||
|  | 
 | ||||||
|  |         self.shared_mlp = nn.Sequential( | ||||||
|  |             nn.Flatten(), | ||||||
|  |             nn.Linear(in_features=channel_in, out_features=channel_in//reduction_ratio), | ||||||
|  |             nn.ReLU(inplace=True), | ||||||
|  |             nn.Linear(in_features=channel_in//reduction_ratio, out_features=channel_in) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         '''Forward Propagation. | ||||||
|  |         ''' | ||||||
|  | 
 | ||||||
|  |         channel_attentions = [] | ||||||
|  | 
 | ||||||
|  |         for pool_types in self.pool_types: | ||||||
|  |             if pool_types == 'avg': | ||||||
|  |                 pool_init = nn.AvgPool2d(kernel_size=(x.size(2), x.size(3)), stride=(x.size(2), x.size(3))) | ||||||
|  |                 avg_pool = pool_init(x) | ||||||
|  |                 channel_attentions.append(self.shared_mlp(avg_pool)) | ||||||
|  |             elif pool_types == 'max': | ||||||
|  |                 pool_init = nn.MaxPool2d(kernel_size=(x.size(2), x.size(3)), stride=(x.size(2), x.size(3))) | ||||||
|  |                 max_pool = pool_init(x) | ||||||
|  |                 channel_attentions.append(self.shared_mlp(max_pool)) | ||||||
|  | 
 | ||||||
|  |         pooling_sums = torch.stack(channel_attentions, dim=0).sum(dim=0) | ||||||
|  |         scaled = nn.Sigmoid()(pooling_sums).unsqueeze(2).unsqueeze(3).expand_as(x) | ||||||
|  | 
 | ||||||
|  |         return x * scaled #return the element-wise multiplication between the input and the result. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ChannelPool(nn.Module): | ||||||
|  |     '''Merge all the channels in a feature map into two separate channels where the first channel is produced by taking the max values from all channels, while the | ||||||
|  |        second one is produced by taking the mean from every channel. | ||||||
|  |     ''' | ||||||
|  |     def forward(self, x): | ||||||
|  |         return torch.cat((torch.max(x, 1)[0].unsqueeze(1), torch.mean(x, 1).unsqueeze(1)), dim=1) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Spatial_Attention(nn.Module): | ||||||
|  |     '''Spatial Attention in CBAM. | ||||||
|  |     ''' | ||||||
|  | 
 | ||||||
|  |     def __init__(self, kernel_size=7): | ||||||
|  |         '''Spatial Attention Architecture. | ||||||
|  |         ''' | ||||||
|  | 
 | ||||||
|  |         super(Spatial_Attention, self).__init__() | ||||||
|  | 
 | ||||||
|  |         self.compress = ChannelPool() | ||||||
|  |         self.spatial_attention = nn.Sequential( | ||||||
|  |             nn.Conv2d(in_channels=2, out_channels=1, kernel_size=kernel_size, stride=1, dilation=1, padding=(kernel_size-1)//2, bias=False), | ||||||
|  |             nn.BatchNorm2d(num_features=1, eps=1e-5, momentum=0.01, affine=True) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         '''Forward Propagation. | ||||||
|  |         ''' | ||||||
|  |         x_compress = self.compress(x) | ||||||
|  |         x_output = self.spatial_attention(x_compress) | ||||||
|  |         scaled = nn.Sigmoid()(x_output) | ||||||
|  |         return x * scaled | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class CBAM(nn.Module): | ||||||
|  |     '''CBAM architecture. | ||||||
|  |     ''' | ||||||
|  |     def __init__(self, channel_in, reduction_ratio=16, pool_types=['avg', 'max'], spatial=True): | ||||||
|  |         '''Param init and arch build. | ||||||
|  |         ''' | ||||||
|  |         super(CBAM, self).__init__() | ||||||
|  |         self.spatial = spatial | ||||||
|  | 
 | ||||||
|  |         self.channel_attention = Channel_Attention(channel_in=channel_in, reduction_ratio=reduction_ratio, pool_types=pool_types) | ||||||
|  | 
 | ||||||
|  |         if self.spatial: | ||||||
|  |             self.spatial_attention = Spatial_Attention(kernel_size=7) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         '''Forward Propagation. | ||||||
|  |         ''' | ||||||
|  |         x_out = self.channel_attention(x) | ||||||
|  |         if self.spatial: | ||||||
|  |             x_out = self.spatial_attention(x_out) | ||||||
|  | 
 | ||||||
|  |         return x_out | ||||||
							
								
								
									
										72
									
								
								client.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,72 @@ | |||||||
|  | import numpy as np | ||||||
|  | import models, torch, copy | ||||||
|  | class Client(object): | ||||||
|  | 
 | ||||||
|  | 	def __init__(self, conf, model, train_dataset, id = -1): | ||||||
|  | 		 | ||||||
|  | 		self.conf = conf | ||||||
|  | 		#训练模型 | ||||||
|  | 		self.local_model = models.get_model(self.conf["model_name"])  | ||||||
|  | 		 | ||||||
|  | 		self.client_id = id | ||||||
|  | 		 | ||||||
|  | 		self.train_dataset = train_dataset | ||||||
|  | 		 | ||||||
|  | 		all_range = list(range(len(self.train_dataset))) | ||||||
|  | 		 | ||||||
|  | 		data_len = int(len(self.train_dataset) / self.conf['no_models']) | ||||||
|  | 		#print(data_len) | ||||||
|  | 		train_indices = all_range[id * data_len: (id + 1) * data_len] | ||||||
|  | 
 | ||||||
|  | 		self.train_loader = torch.utils.data.DataLoader(self.train_dataset, batch_size=conf["batch_size"],  | ||||||
|  | 									sampler=torch.utils.data.sampler.SubsetRandomSampler(train_indices)) | ||||||
|  | 									 | ||||||
|  | 		 | ||||||
|  | 	def local_train(self, model): | ||||||
|  | 
 | ||||||
|  | 		for name, param in model.state_dict().items(): | ||||||
|  | 			self.local_model.state_dict()[name].copy_(param.clone()) | ||||||
|  | 	 | ||||||
|  | 		#print(id(model)) | ||||||
|  | 		optimizer = torch.optim.SGD(self.local_model.parameters(), lr=self.conf['lr'], | ||||||
|  | 									momentum=self.conf['momentum']) | ||||||
|  | 		#print(id(self.local_model)) | ||||||
|  | 		self.local_model.train() | ||||||
|  | 		for e in range(self.conf["local_epochs"]): | ||||||
|  | 			 | ||||||
|  | 			for batch_id, batch in enumerate(self.train_loader): | ||||||
|  | 				data, target = batch | ||||||
|  | 				 | ||||||
|  | 				if torch.cuda.is_available(): | ||||||
|  | 					data = data.cuda() | ||||||
|  | 					target = target.cuda() | ||||||
|  | 				 | ||||||
|  | 				optimizer.zero_grad() | ||||||
|  | 				output = self.local_model(data) | ||||||
|  | 				# print(type(output)) | ||||||
|  | 
 | ||||||
|  | 				# target=np.array(target).astype(int) | ||||||
|  | 				# target=torch.from_numpy(target) | ||||||
|  | 				 | ||||||
|  | 				loss = torch.nn.functional.cross_entropy(output, target) | ||||||
|  | 				loss.backward() | ||||||
|  | 			 | ||||||
|  | 				optimizer.step() | ||||||
|  | 
 | ||||||
|  | 				if self.conf["dp"]: | ||||||
|  | 					model_norm = models.model_norm(model, self.local_model) | ||||||
|  | 					 | ||||||
|  | 					norm_scale = min(1, self.conf['C'] / (model_norm)) | ||||||
|  | 					#print(model_norm, norm_scale) | ||||||
|  | 					for name, layer in self.local_model.named_parameters(): | ||||||
|  | 						clipped_difference = norm_scale * (layer.data - model.state_dict()[name]) | ||||||
|  | 						layer.data.copy_(model.state_dict()[name] + clipped_difference) | ||||||
|  | 
 | ||||||
|  | 			print("Epoch %d done." % e)	 | ||||||
|  | 		diff = dict() | ||||||
|  | 		for name, data in self.local_model.state_dict().items(): | ||||||
|  | 			diff[name] = (data - model.state_dict()[name]) | ||||||
|  | 			#print(diff[name]) | ||||||
|  | 			 | ||||||
|  | 		return diff | ||||||
|  | 		 | ||||||
							
								
								
									
										77
									
								
								client1.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,77 @@ | |||||||
|  | 
 | ||||||
|  | import models, torch, copy | ||||||
|  | class Client(object): | ||||||
|  | 
 | ||||||
|  | 	def __init__(self, conf, model, train_dataset, id = -1): | ||||||
|  | 		 | ||||||
|  | 		self.conf = conf | ||||||
|  | 
 | ||||||
|  | 		self.local_model = models.get_model(self.conf["model_name"])  | ||||||
|  | 		 | ||||||
|  | 		self.client_id = id | ||||||
|  | 		 | ||||||
|  | 		self.train_dataset = train_dataset | ||||||
|  | 		 | ||||||
|  | 		all_range = list(range(len(self.train_dataset))) | ||||||
|  | 		data_len = int(len(self.train_dataset) / self.conf['no_models']) | ||||||
|  | 		train_indices = all_range[id * data_len: (id + 1) * data_len] | ||||||
|  | 
 | ||||||
|  | 		self.train_loader = torch.utils.data.DataLoader(self.train_dataset, batch_size=conf["batch_size"],  | ||||||
|  | 									sampler=torch.utils.data.sampler.SubsetRandomSampler(train_indices)) | ||||||
|  | 									 | ||||||
|  | 		 | ||||||
|  | 	def local_train(self, model): | ||||||
|  | 
 | ||||||
|  | 		for name, param in model.state_dict().items(): | ||||||
|  | 			self.local_model.state_dict()[name].copy_(param.clone()) | ||||||
|  | 			 | ||||||
|  | 		#print("\n\nlocal model train ... ... ") | ||||||
|  | 		#for name, layer in self.local_model.named_parameters(): | ||||||
|  | 		#	print(name, "->", torch.mean(layer.data)) | ||||||
|  | 			 | ||||||
|  | 		#print("\n\n") | ||||||
|  | 		optimizer = torch.optim.SGD(self.local_model.parameters(), lr=self.conf['lr'], | ||||||
|  | 									momentum=self.conf['momentum']) | ||||||
|  | 		 | ||||||
|  | 		 | ||||||
|  | 		self.local_model.train() | ||||||
|  | 		for e in range(self.conf["local_epochs"]): | ||||||
|  | 			 | ||||||
|  | 			for batch_id, batch in enumerate(self.train_loader): | ||||||
|  | 				data, target = batch | ||||||
|  | 				#for name, layer in self.local_model.named_parameters(): | ||||||
|  | 				#	print(torch.mean(self.local_model.state_dict()[name].data)) | ||||||
|  | 				#print("\n\n") | ||||||
|  | 				if torch.cuda.is_available(): | ||||||
|  | 					data = data.cuda() | ||||||
|  | 					target = target.cuda() | ||||||
|  | 			 | ||||||
|  | 				optimizer.zero_grad() | ||||||
|  | 				output = self.local_model(data) | ||||||
|  | 				loss = torch.nn.functional.cross_entropy(output, target) | ||||||
|  | 				loss.backward() | ||||||
|  | 			 | ||||||
|  | 				optimizer.step() | ||||||
|  | 				 | ||||||
|  | 				#for name, layer in self.local_model.named_parameters(): | ||||||
|  | 				#	print(torch.mean(self.local_model.state_dict()[name].data)) | ||||||
|  | 				#print("\n\n") | ||||||
|  | 				if self.conf["dp"]: | ||||||
|  | 					model_norm = models.model_norm(model, self.local_model) | ||||||
|  | 					 | ||||||
|  | 					norm_scale = min(1, self.conf['C'] / (model_norm)) | ||||||
|  | 					#print(model_norm, norm_scale) | ||||||
|  | 					for name, layer in self.local_model.named_parameters(): | ||||||
|  | 						clipped_difference = norm_scale * (layer.data - model.state_dict()[name]) | ||||||
|  | 						layer.data.copy_(model.state_dict()[name] + clipped_difference) | ||||||
|  | 						 | ||||||
|  | 			print("Epoch %d done." % e)	 | ||||||
|  | 		diff = dict() | ||||||
|  | 		for name, data in self.local_model.state_dict().items(): | ||||||
|  | 			diff[name] = (data - model.state_dict()[name]) | ||||||
|  | 			 | ||||||
|  | 		#print("\n\nfinishing local model training ... ... ") | ||||||
|  | 		#for name, layer in self.local_model.named_parameters(): | ||||||
|  | 		#	print(name, "->", torch.mean(layer.data)) | ||||||
|  | 		return diff | ||||||
|  | 		 | ||||||
							
								
								
									
										298
									
								
								coatnet.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,298 @@ | |||||||
|  | import torch | ||||||
|  | import torch.nn as nn | ||||||
|  | 
 | ||||||
|  | from einops import rearrange | ||||||
|  | from einops.layers.torch import Rearrange | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def conv_3x3_bn(inp, oup, image_size, downsample=False): | ||||||
|  |     stride = 1 if downsample == False else 2 | ||||||
|  |     return nn.Sequential( | ||||||
|  |         nn.Conv2d(inp, oup, 3, stride, 1, bias=False), | ||||||
|  |         nn.BatchNorm2d(oup), | ||||||
|  |         nn.GELU() | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PreNorm(nn.Module): | ||||||
|  |     def __init__(self, dim, fn, norm): | ||||||
|  |         super().__init__() | ||||||
|  |         self.norm = norm(dim) | ||||||
|  |         self.fn = fn | ||||||
|  | 
 | ||||||
|  |     def forward(self, x, **kwargs): | ||||||
|  |         return self.fn(self.norm(x), **kwargs) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class SE(nn.Module): | ||||||
|  |     def __init__(self, inp, oup, expansion=0.25): | ||||||
|  |         super().__init__() | ||||||
|  |         self.avg_pool = nn.AdaptiveAvgPool2d(1) | ||||||
|  |         self.fc = nn.Sequential( | ||||||
|  |             nn.Linear(oup, int(inp * expansion), bias=False), | ||||||
|  |             nn.GELU(), | ||||||
|  |             nn.Linear(int(inp * expansion), oup, bias=False), | ||||||
|  |             nn.Sigmoid() | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         b, c, _, _ = x.size() | ||||||
|  |         y = self.avg_pool(x).view(b, c) | ||||||
|  |         y = self.fc(y).view(b, c, 1, 1) | ||||||
|  |         return x * y | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FeedForward(nn.Module): | ||||||
|  |     def __init__(self, dim, hidden_dim, dropout=0.): | ||||||
|  |         super().__init__() | ||||||
|  |         self.net = nn.Sequential( | ||||||
|  |             nn.Linear(dim, hidden_dim), | ||||||
|  |             nn.GELU(), | ||||||
|  |             nn.Dropout(dropout), | ||||||
|  |             nn.Linear(hidden_dim, dim), | ||||||
|  |             nn.Dropout(dropout) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         return self.net(x) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class MBConv(nn.Module): | ||||||
|  |     def __init__(self, inp, oup, image_size, downsample=False, expansion=4): | ||||||
|  |         super().__init__() | ||||||
|  |         self.downsample = downsample | ||||||
|  |         stride = 1 if self.downsample == False else 2 | ||||||
|  |         hidden_dim = int(inp * expansion) | ||||||
|  | 
 | ||||||
|  |         if self.downsample: | ||||||
|  |             self.pool = nn.MaxPool2d(3, 2, 1) | ||||||
|  |             self.proj = nn.Conv2d(inp, oup, 1, 1, 0, bias=False) | ||||||
|  | 
 | ||||||
|  |         if expansion == 1: | ||||||
|  |             self.conv = nn.Sequential( | ||||||
|  |                 # dw | ||||||
|  |                 nn.Conv2d(hidden_dim, hidden_dim, 3, stride, | ||||||
|  |                           1, groups=hidden_dim, bias=False), | ||||||
|  |                 nn.BatchNorm2d(hidden_dim), | ||||||
|  |                 nn.GELU(), | ||||||
|  |                 # pw-linear | ||||||
|  |                 nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False), | ||||||
|  |                 nn.BatchNorm2d(oup), | ||||||
|  |             ) | ||||||
|  |         else: | ||||||
|  |             self.conv = nn.Sequential( | ||||||
|  |                 # pw | ||||||
|  |                 # down-sample in the first conv | ||||||
|  |                 nn.Conv2d(inp, hidden_dim, 1, stride, 0, bias=False), | ||||||
|  |                 nn.BatchNorm2d(hidden_dim), | ||||||
|  |                 nn.GELU(), | ||||||
|  |                 # dw | ||||||
|  |                 nn.Conv2d(hidden_dim, hidden_dim, 3, 1, 1, | ||||||
|  |                           groups=hidden_dim, bias=False), | ||||||
|  |                 nn.BatchNorm2d(hidden_dim), | ||||||
|  |                 nn.GELU(), | ||||||
|  |                 SE(inp, hidden_dim), | ||||||
|  |                 # pw-linear | ||||||
|  |                 nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False), | ||||||
|  |                 nn.BatchNorm2d(oup), | ||||||
|  |             ) | ||||||
|  |          | ||||||
|  |         self.conv = PreNorm(inp, self.conv, nn.BatchNorm2d) | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         if self.downsample: | ||||||
|  |             return self.proj(self.pool(x)) + self.conv(x) | ||||||
|  |         else: | ||||||
|  |             return x + self.conv(x) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Attention(nn.Module): | ||||||
|  |     def __init__(self, inp, oup, image_size, heads=8, dim_head=32, dropout=0.): | ||||||
|  |         super().__init__() | ||||||
|  |         inner_dim = dim_head * heads | ||||||
|  |         project_out = not (heads == 1 and dim_head == inp) | ||||||
|  | 
 | ||||||
|  |         self.ih, self.iw = image_size | ||||||
|  | 
 | ||||||
|  |         self.heads = heads | ||||||
|  |         self.scale = dim_head ** -0.5 | ||||||
|  | 
 | ||||||
|  |         # parameter table of relative position bias | ||||||
|  |         self.relative_bias_table = nn.Parameter( | ||||||
|  |             torch.zeros((2 * self.ih - 1) * (2 * self.iw - 1), heads)) | ||||||
|  | 
 | ||||||
|  |         coords = torch.meshgrid((torch.arange(self.ih), torch.arange(self.iw))) | ||||||
|  |         coords = torch.flatten(torch.stack(coords), 1) | ||||||
|  |         relative_coords = coords[:, :, None] - coords[:, None, :] | ||||||
|  | 
 | ||||||
|  |         relative_coords[0] += self.ih - 1 | ||||||
|  |         relative_coords[1] += self.iw - 1 | ||||||
|  |         relative_coords[0] *= 2 * self.iw - 1 | ||||||
|  |         relative_coords = rearrange(relative_coords, 'c h w -> h w c') | ||||||
|  |         relative_index = relative_coords.sum(-1).flatten().unsqueeze(1) | ||||||
|  |         self.register_buffer("relative_index", relative_index) | ||||||
|  | 
 | ||||||
|  |         self.attend = nn.Softmax(dim=-1) | ||||||
|  |         self.to_qkv = nn.Linear(inp, inner_dim * 3, bias=False) | ||||||
|  | 
 | ||||||
|  |         self.to_out = nn.Sequential( | ||||||
|  |             nn.Linear(inner_dim, oup), | ||||||
|  |             nn.Dropout(dropout) | ||||||
|  |         ) if project_out else nn.Identity() | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         qkv = self.to_qkv(x).chunk(3, dim=-1) | ||||||
|  |         q, k, v = map(lambda t: rearrange( | ||||||
|  |             t, 'b n (h d) -> b h n d', h=self.heads), qkv) | ||||||
|  | 
 | ||||||
|  |         dots = torch.matmul(q, k.transpose(-1, -2)) * self.scale | ||||||
|  | 
 | ||||||
|  |         # Use "gather" for more efficiency on GPUs | ||||||
|  |         relative_bias = self.relative_bias_table.gather( | ||||||
|  |             0, self.relative_index.repeat(1, self.heads)) | ||||||
|  |         relative_bias = rearrange( | ||||||
|  |             relative_bias, '(h w) c -> 1 c h w', h=self.ih*self.iw, w=self.ih*self.iw) | ||||||
|  |         #print(dots.shape,relative_bias.shape) | ||||||
|  |         dots = dots + relative_bias | ||||||
|  | 
 | ||||||
|  |         attn = self.attend(dots) | ||||||
|  |         out = torch.matmul(attn, v) | ||||||
|  |         out = rearrange(out, 'b h n d -> b n (h d)') | ||||||
|  |         out = self.to_out(out) | ||||||
|  |         return out | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Transformer(nn.Module): | ||||||
|  |     def __init__(self, inp, oup, image_size, heads=8, dim_head=32, downsample=False, dropout=0.): | ||||||
|  |         super().__init__() | ||||||
|  |         hidden_dim = int(inp * 4) | ||||||
|  | 
 | ||||||
|  |         self.ih, self.iw = image_size | ||||||
|  |         self.downsample = downsample | ||||||
|  | 
 | ||||||
|  |         if self.downsample: | ||||||
|  |             self.pool1 = nn.MaxPool2d(3, 2, 1) | ||||||
|  |             self.pool2 = nn.MaxPool2d(3, 2, 1) | ||||||
|  |             self.proj = nn.Conv2d(inp, oup, 1, 1, 0, bias=False) | ||||||
|  | 
 | ||||||
|  |         self.attn = Attention(inp, oup, image_size, heads, dim_head, dropout) | ||||||
|  |         self.ff = FeedForward(oup, hidden_dim, dropout) | ||||||
|  | 
 | ||||||
|  |         self.attn = nn.Sequential( | ||||||
|  |             Rearrange('b c ih iw -> b (ih iw) c'), | ||||||
|  |             PreNorm(inp, self.attn, nn.LayerNorm), | ||||||
|  |             Rearrange('b (ih iw) c -> b c ih iw', ih=self.ih, iw=self.iw) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         self.ff = nn.Sequential( | ||||||
|  |             Rearrange('b c ih iw -> b (ih iw) c'), | ||||||
|  |             PreNorm(oup, self.ff, nn.LayerNorm), | ||||||
|  |             Rearrange('b (ih iw) c -> b c ih iw', ih=self.ih, iw=self.iw) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         if self.downsample: | ||||||
|  |             x = self.proj(self.pool1(x)) + self.attn(self.pool2(x)) | ||||||
|  |         else: | ||||||
|  |             x = x + self.attn(x) | ||||||
|  |         x = x + self.ff(x) | ||||||
|  |         return x | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class CoAtNet(nn.Module): | ||||||
|  |     def __init__(self, image_size, in_channels, num_blocks, channels, num_classes=1000, block_types=['C', 'C', 'T', 'T']): | ||||||
|  |         super().__init__() | ||||||
|  |         ih, iw = image_size | ||||||
|  |         block = {'C': MBConv, 'T': Transformer} | ||||||
|  | 
 | ||||||
|  |         self.s0 = self._make_layer( | ||||||
|  |             conv_3x3_bn, in_channels, channels[0], num_blocks[0], (ih // 2, iw // 2)) | ||||||
|  |         self.s1 = self._make_layer( | ||||||
|  |             block[block_types[0]], channels[0], channels[1], num_blocks[1], (ih // 4, iw // 4)) | ||||||
|  |         self.s2 = self._make_layer( | ||||||
|  |             block[block_types[1]], channels[1], channels[2], num_blocks[2], (ih // 8, iw // 8)) | ||||||
|  |         self.s3 = self._make_layer( | ||||||
|  |             block[block_types[2]], channels[2], channels[3], num_blocks[3], (ih // 16, iw // 16)) | ||||||
|  |         self.s4 = self._make_layer( | ||||||
|  |             block[block_types[3]], channels[3], channels[4], num_blocks[4], (ih // 32, iw // 32)) | ||||||
|  | 
 | ||||||
|  |         self.pool = nn.AvgPool2d(ih // 32, 1) | ||||||
|  |         self.fc = nn.Linear(channels[-1], num_classes, bias=False) | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         x = self.s0(x) | ||||||
|  |         x = self.s1(x) | ||||||
|  |         x = self.s2(x) | ||||||
|  |         x = self.s3(x) | ||||||
|  |         x = self.s4(x) | ||||||
|  | 
 | ||||||
|  |         x = self.pool(x).view(-1, x.shape[1]) | ||||||
|  |         x = self.fc(x) | ||||||
|  |         return x | ||||||
|  | 
 | ||||||
|  |     def _make_layer(self, block, inp, oup, depth, image_size): | ||||||
|  |         layers = nn.ModuleList([]) | ||||||
|  |         for i in range(depth): | ||||||
|  |             if i == 0: | ||||||
|  |                 layers.append(block(inp, oup, image_size, downsample=True)) | ||||||
|  |             else: | ||||||
|  |                 layers.append(block(oup, oup, image_size)) | ||||||
|  |         return nn.Sequential(*layers) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def coatnet_0(): | ||||||
|  |     num_blocks = [2, 2, 3, 5, 2]            # L | ||||||
|  |     channels = [64, 96, 192, 384, 768]      # D | ||||||
|  |     return CoAtNet((224, 224), 3, num_blocks, channels, num_classes=1000) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def coatnet_1(): | ||||||
|  |     num_blocks = [2, 2, 6, 14, 2]           # L | ||||||
|  |     channels = [64, 96, 192, 384, 768]      # D | ||||||
|  |     return CoAtNet((224, 224), 3, num_blocks, channels, num_classes=1000) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def coatnet_2(): | ||||||
|  |     num_blocks = [2, 2, 6, 14, 2]           # L | ||||||
|  |     channels = [128, 128, 256, 512, 1026]   # D | ||||||
|  |     return CoAtNet((224, 224), 3, num_blocks, channels, num_classes=1000) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def coatnet_3(): | ||||||
|  |     num_blocks = [2, 2, 6, 14, 2]           # L | ||||||
|  |     channels = [192, 192, 384, 768, 1536]   # D | ||||||
|  |     return CoAtNet((224, 224), 3, num_blocks, channels, num_classes=1000) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def coatnet_4(): | ||||||
|  |     num_blocks = [2, 2, 12, 28, 2]          # L | ||||||
|  |     channels = [192, 192, 384, 768, 1536]   # D | ||||||
|  |     return CoAtNet((224, 224), 3, num_blocks, channels, num_classes=1000) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def count_parameters(model): | ||||||
|  |     return sum(p.numel() for p in model.parameters() if p.requires_grad) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  |     img = torch.randn(1, 3, 224, 224) | ||||||
|  | 
 | ||||||
|  |     net = coatnet_0() | ||||||
|  |     out = net(img) | ||||||
|  |     print(out.shape, count_parameters(net)) | ||||||
|  | 
 | ||||||
|  |     net = coatnet_1() | ||||||
|  |     out = net(img) | ||||||
|  |     print(out.shape, count_parameters(net)) | ||||||
|  | 
 | ||||||
|  |     net = coatnet_2() | ||||||
|  |     out = net(img) | ||||||
|  |     print(out.shape, count_parameters(net)) | ||||||
|  | 
 | ||||||
|  |     net = coatnet_3() | ||||||
|  |     out = net(img) | ||||||
|  |     print(out.shape, count_parameters(net)) | ||||||
|  | 
 | ||||||
|  |     net = coatnet_4() | ||||||
|  |     out = net(img) | ||||||
|  |     print(out.shape, count_parameters(net)) | ||||||
							
								
								
									
										58
									
								
								coordatt.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,58 @@ | |||||||
|  | import torch | ||||||
|  | import torch.nn as nn | ||||||
|  | import math | ||||||
|  | import torch.nn.functional as F | ||||||
|  | 
 | ||||||
|  | class h_sigmoid(nn.Module): | ||||||
|  |     def __init__(self, inplace=True): | ||||||
|  |         super(h_sigmoid, self).__init__() | ||||||
|  |         self.relu = nn.ReLU6(inplace=inplace) | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         return self.relu(x + 3) / 6 | ||||||
|  | 
 | ||||||
|  | class h_swish(nn.Module): | ||||||
|  |     def __init__(self, inplace=True): | ||||||
|  |         super(h_swish, self).__init__() | ||||||
|  |         self.sigmoid = h_sigmoid(inplace=inplace) | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         return x * self.sigmoid(x) | ||||||
|  | 
 | ||||||
|  | class CoordAtt(nn.Module): | ||||||
|  |     def __init__(self, inp, oup, reduction=32): | ||||||
|  |         super(CoordAtt, self).__init__() | ||||||
|  |         self.pool_h = nn.AdaptiveAvgPool2d((None, 1)) | ||||||
|  |         self.pool_w = nn.AdaptiveAvgPool2d((1, None)) | ||||||
|  | 
 | ||||||
|  |         mip = max(8, inp // reduction) | ||||||
|  | 
 | ||||||
|  |         self.conv1 = nn.Conv2d(inp, mip, kernel_size=1, stride=1, padding=0) | ||||||
|  |         self.bn1 = nn.BatchNorm2d(mip) | ||||||
|  |         self.act = h_swish() | ||||||
|  |          | ||||||
|  |         self.conv_h = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0) | ||||||
|  |         self.conv_w = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0) | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |     def forward(self, x): | ||||||
|  |         identity = x | ||||||
|  |          | ||||||
|  |         n,c,h,w = x.size() | ||||||
|  |         x_h = self.pool_h(x) | ||||||
|  |         x_w = self.pool_w(x).permute(0, 1, 3, 2) | ||||||
|  | 
 | ||||||
|  |         y = torch.cat([x_h, x_w], dim=2) | ||||||
|  |         y = self.conv1(y) | ||||||
|  |         y = self.bn1(y) | ||||||
|  |         y = self.act(y)  | ||||||
|  |          | ||||||
|  |         x_h, x_w = torch.split(y, [h, w], dim=2) | ||||||
|  |         x_w = x_w.permute(0, 1, 3, 2) | ||||||
|  | 
 | ||||||
|  |         a_h = self.conv_h(x_h).sigmoid() | ||||||
|  |         a_w = self.conv_w(x_w).sigmoid() | ||||||
|  | 
 | ||||||
|  |         out = identity * a_w * a_h | ||||||
|  | 
 | ||||||
|  |         return out | ||||||
							
								
								
									
										118
									
								
								cwt_main.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,118 @@ | |||||||
|  | import argparse, json | ||||||
|  | import datetime | ||||||
|  | import os | ||||||
|  | import logging | ||||||
|  | import os | ||||||
|  | os.environ["CUDA_VISIBLE_DEVICES"] = "1" | ||||||
|  | import torch, random | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | from server import * | ||||||
|  | from client import * | ||||||
|  | import models, datasets | ||||||
|  | from torchvision.datasets import ImageFolder | ||||||
|  |   | ||||||
|  | import torch | ||||||
|  | from torchvision import transforms, datasets | ||||||
|  | import torch.nn as nn | ||||||
|  | from torch.utils.data import DataLoader | ||||||
|  | import torchvision | ||||||
|  | import matplotlib.pyplot as plt | ||||||
|  | import numpy as np | ||||||
|  | from log import get_log | ||||||
|  | 
 | ||||||
|  | from torch import randperm | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import os  | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | logger = get_log('/home/ykn/cds/chapter03_Python_image_classification/log/log.txt') | ||||||
|  | #logger.info("MSE: %.6f" % (mse)) | ||||||
|  | #logger.info("RMSE: %.6f" % (rmse)) | ||||||
|  | #logger.info("MAE: %.6f" % (mae)) | ||||||
|  | #logger.info("MAPE: %.6f" % (mape)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | transforms = transforms.Compose([ | ||||||
|  |     transforms.Resize(256),    # 将图片短边缩放至256,长宽比保持不变: | ||||||
|  |     transforms.CenterCrop(224),   #将图片从中心切剪成3*224*224大小的图片 | ||||||
|  |     transforms.ToTensor()          #把图片进行归一化,并把数据转换成Tensor类型 | ||||||
|  | ])  | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  | 
 | ||||||
|  | 	parser = argparse.ArgumentParser(description='Federated Learning') | ||||||
|  | 	parser.add_argument('--conf', default = '/home/ykn/cds/chapter03_Python_image_classification/utils/conf.json', dest='conf') | ||||||
|  | 	args = parser.parse_args() | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 	with open(args.conf, 'r') as f: | ||||||
|  | 		conf = json.load(f)	 | ||||||
|  | 	 | ||||||
|  | 	path1 = '/home/ykn/cds/chapter03_Python_image_classification/data/Brain Tumor MRI Dataset/archive/Training' | ||||||
|  | 	path2 = '/home/ykn/cds/chapter03_Python_image_classification/data/Brain Tumor MRI Dataset/archive/Testing' | ||||||
|  | 	data_train = datasets.ImageFolder(path1, transform=transforms) | ||||||
|  | 	data_test = datasets.ImageFolder(path2, transform=transforms) | ||||||
|  | 	print(data_train) | ||||||
|  | 	# data_loader = DataLoader(data_train, batch_size=64, shuffle=True) | ||||||
|  |   | ||||||
|  | 	# for i, data in enumerate(data_loader): | ||||||
|  | 	# 	images, labels = data | ||||||
|  | 	# img = torchvision.utils.make_grid(images).numpy() | ||||||
|  | 	# plt.imshow(np.transpose(img, (1, 2, 0))) | ||||||
|  | 	# #plt.show()	 | ||||||
|  | 
 | ||||||
|  | 	# train_datasets, eval_datasets = datasets.get_dataset("./data/", conf["type"]) | ||||||
|  | 	# data_train_shuffle = DataLoader(data_train, batch_size=64, shuffle=True) | ||||||
|  | 	# data_test_shuffle = DataLoader(data_test, batch_size=64, shuffle=True) | ||||||
|  | 	# print(data_train_shuffle) | ||||||
|  | 
 | ||||||
|  | 	lenth_train = randperm(len(data_train)).tolist() # 生成乱序的索引 | ||||||
|  | 	data_train_shuffle = torch.utils.data.Subset(data_train, lenth_train) | ||||||
|  | 	lenth_test = randperm(len(data_test)).tolist() # 生成乱序的索引 | ||||||
|  | 	data_test_shuffle = torch.utils.data.Subset(data_test, lenth_test) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	train_datasets, eval_datasets = data_train_shuffle, data_test_shuffle | ||||||
|  | 	server = Server(conf, eval_datasets) | ||||||
|  | 	clients = [] | ||||||
|  | 	 | ||||||
|  | 	for c in range(conf["no_models"]): | ||||||
|  | 		clients.append(Client(conf, server.global_model, train_datasets, c)) | ||||||
|  | 		 | ||||||
|  | 	print("\n\n") | ||||||
|  | 	for e in range(conf["global_epochs"]): | ||||||
|  | 		random.shuffle(clients) | ||||||
|  | 		for client in clients[:conf['k']]: | ||||||
|  | 			print(client.client_id)		 | ||||||
|  | 			weight_accumulator = {} | ||||||
|  | 				 | ||||||
|  | 			for name, params in server.global_model.state_dict().items(): | ||||||
|  | 				weight_accumulator[name] = torch.zeros_like(params) | ||||||
|  | 				 | ||||||
|  | 
 | ||||||
|  | 			diff = client.local_train(server.global_model) | ||||||
|  | 					 | ||||||
|  | 			for name, params in server.global_model.state_dict().items(): | ||||||
|  | 				weight_accumulator[name].add_(diff[name]) | ||||||
|  | 					 | ||||||
|  | 				 | ||||||
|  | 			server.model_aggregate(weight_accumulator) | ||||||
|  | 				 | ||||||
|  | 			acc, loss = server.model_eval() | ||||||
|  | 				 | ||||||
|  | 			print("Epoch %d, acc: %f, loss: %f\n" % (e, acc, loss)) | ||||||
|  | 
 | ||||||
|  | 	 | ||||||
|  | 				 | ||||||
|  | 			 | ||||||
|  | 		 | ||||||
|  | 		 | ||||||
|  | 	 | ||||||
|  | 		 | ||||||
|  | 		 | ||||||
|  | 	 | ||||||
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 20 KiB | 
| After Width: | Height: | Size: 13 KiB | 
| After Width: | Height: | Size: 26 KiB | 
| After Width: | Height: | Size: 21 KiB | 
| After Width: | Height: | Size: 18 KiB | 
| After Width: | Height: | Size: 22 KiB | 
| After Width: | Height: | Size: 20 KiB | 
| After Width: | Height: | Size: 21 KiB | 
| After Width: | Height: | Size: 20 KiB | 
| After Width: | Height: | Size: 22 KiB | 
| After Width: | Height: | Size: 23 KiB | 
| After Width: | Height: | Size: 19 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 16 KiB | 
| After Width: | Height: | Size: 23 KiB | 
| After Width: | Height: | Size: 19 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 19 KiB | 
| After Width: | Height: | Size: 21 KiB | 
| After Width: | Height: | Size: 23 KiB | 
| After Width: | Height: | Size: 20 KiB | 
| After Width: | Height: | Size: 20 KiB | 
| After Width: | Height: | Size: 18 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 22 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 19 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 21 KiB | 
| After Width: | Height: | Size: 19 KiB | 
| After Width: | Height: | Size: 18 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 16 KiB | 
| After Width: | Height: | Size: 29 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 27 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 23 KiB | 
| After Width: | Height: | Size: 21 KiB | 
| After Width: | Height: | Size: 24 KiB | 
| After Width: | Height: | Size: 14 KiB | 
| After Width: | Height: | Size: 24 KiB | 
| After Width: | Height: | Size: 26 KiB | 
| After Width: | Height: | Size: 24 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 18 KiB | 
| After Width: | Height: | Size: 23 KiB | 
| After Width: | Height: | Size: 20 KiB | 
| After Width: | Height: | Size: 15 KiB | 
| After Width: | Height: | Size: 20 KiB | 
| After Width: | Height: | Size: 20 KiB | 
| After Width: | Height: | Size: 16 KiB | 
| After Width: | Height: | Size: 24 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 26 KiB | 
| After Width: | Height: | Size: 27 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 24 KiB | 
| After Width: | Height: | Size: 24 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 23 KiB | 
| After Width: | Height: | Size: 25 KiB | 
| After Width: | Height: | Size: 22 KiB | 
| After Width: | Height: | Size: 27 KiB | 
| After Width: | Height: | Size: 23 KiB | 
| After Width: | Height: | Size: 24 KiB | 
| After Width: | Height: | Size: 16 KiB | 
| After Width: | Height: | Size: 21 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 14 KiB | 
| After Width: | Height: | Size: 14 KiB | 
| After Width: | Height: | Size: 15 KiB | 
| After Width: | Height: | Size: 16 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 15 KiB | 
| After Width: | Height: | Size: 19 KiB | 
| After Width: | Height: | Size: 14 KiB | 
| After Width: | Height: | Size: 20 KiB | 
| After Width: | Height: | Size: 19 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 14 KiB | 
| After Width: | Height: | Size: 12 KiB | 
| After Width: | Height: | Size: 12 KiB | 
| After Width: | Height: | Size: 20 KiB |