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 |