Kaggle competition: University of Liverpool - Ion Switching
<SOS> metric: MacroFScore Kaggle data source: university-of-liverpool-ion-switching<categorify>
seed = 42
test_size = 0.2
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
 workspace = "./unet"
backbone = [1, 1, 1, 1]
encoder_channels = np.array([64, 128, 256, 512, 1024])*2
decoder_channels = np.array([512, 256, 128, 64])*2
fold = 0
time_step = 4000
time_step_test = 10000
stride = 2
batch_size = 8
TRAIN = True
PREDICT = True
ENSEMBLE = False
np.random.seed(seed)
 torch.manual_seed(seed)
 torch.cuda.manual_seed_all(seed)
 print(device )
def find_equal_segment(inp: np.ndarray, bad_segment: np.ndarray, extra_color: int)-> np.ndarray:

 segment_len = bad_segment.size
for i in range(inp.shape[0]):
for col in range(inp.shape[1] - segment_len + 1):
current_segment = inp[i, col:col + segment_len]
if(is_similar(current_segment, bad_segment, extra_color)) :
return current_segment
for j in range(inp.shape[1]):
for row in range(inp.shape[0] - segment_len + 1):
current_segment = inp[row:row + segment_len, j]
if(is_similar(current_segment, bad_segment, extra_color)) :
return current_segment
return None<count_unique_values>
df_train = pd.read_csv(".. /input/liverpool-ion-switching/train.csv")
 df_test = pd.read_csv(".. /input/liverpool-ion-switching/test.csv" )
def delete_extra_color(inp: np.ndarray, extra_color: int):

 bad_rows, bad_cols = np.where(inp == extra_color)
 bad_rows = np.unique(bad_rows)
 bad_cols = np.unique(bad_cols)
 if(len(bad_rows)> inp.shape[0] // 2 or len(bad_cols)> inp.shape[0] // 2):
return
for i in bad_rows:
for segment_len in range(10, inp.shape[1] + 1, 1):
for col in range(inp.shape[1] - segment_len + 1):
bad_segment = inp[i, col: col + segment_len]
if(not np.any(bad_segment == extra_color)) :
continue
correct_segment = find_equal_segment(inp, bad_segment, extra_color)
 if(correct_segment is not None):
inp[i, col:col + segment_len] = correct_segment
for j in bad_cols:
for segment_len in range(10, inp.shape[0] + 1, 1):
for row in range(inp.shape[0] - segment_len + 1):
bad_segment = inp[row:row + segment_len, j]
if(not np.any(bad_segment == extra_color)) :
continue
correct_segment = find_equal_segment(inp, bad_segment, extra_color)
 if(correct_segment is not None):
inp[row:row + segment_len, j] = correct_segment 
<predict_on_test>
def do_identity(image, label):
return image, label
def do_flip(image, label):
image = np.ascontiguousarray(np.flip(image, axis=1))
label = np.ascontiguousarray(np.flip(label))
return image, label
def train_augment(image, label):
for op in np.random.choice([
lambda image, label: do_identity(image, label),
lambda image, label: do_flip(image, label),
], 1):
image, label = op(image, label)
 return image, label
def valid_augment(image, label):
return image, label
def prediction(inp: np.ndarray,
symmetric_axis_horizontal: list,
symmetric_axis_vertical: list,
symmetric_main_diagonal: bool,
symmetric_side_diagonal: bool,
shift_i: int,
shift_j: int,
size: int,
extra_color: int)-> bool:

 res = inp.copy()
for i in range(inp.shape[0]):
for j in range(inp.shape[1]):
if(inp[i][j] != extra_color):
res[i][j] = inp[i][j]
continue
if symmetric_axis_horizontal is not None:
if(symmetric_axis_horizontal[1] != 0):
vertical_len = min(abs(i - symmetric_axis_horizontal[0]), abs(i - symmetric_axis_horizontal[1]))
row = i + vertical_len * 2 + 1
if(i >= symmetric_axis_horizontal[1]):
row = i - vertical_len * 2 - 1
if(0 <= row and row < inp.shape[0] and inp[row][j] != extra_color):
res[i][j] = inp[row][j]
else:
vertical_len = abs(i - symmetric_axis_horizontal[0])
 row = i + vertical_len * 2
if(i >= symmetric_axis_horizontal[0]):
row = i - vertical_len * 2
if(0 <= row and row < inp.shape[0] and inp[row][j] != extra_color):
res[i][j] = inp[row][j]
if symmetric_axis_vertical is not None:
if(symmetric_axis_vertical[1] != 0):
horizontal_len = min(abs(j - symmetric_axis_vertical[0]), abs(j - symmetric_axis_vertical[1]))
column = j + horizontal_len * 2 + 1
if(j >= symmetric_axis_vertical[1]):
column = j - horizontal_len * 2 - 1
if(0 <= column and column < inp.shape[1] and inp[i][column] != extra_color):
res[i][j] = inp[i][column]
else:
horizontal_len = abs(j - symmetric_axis_vertical[0])
 column = j + horizontal_len * 2
if(j >= symmetric_axis_vertical[0]):
column = j - horizontal_len * 2
if(0 <= column and column < inp.shape[1] and inp[i][column] != extra_color):
res[i][j] = inp[i][column]
if(symmetric_main_diagonal):
if i - shift_i > j - shift_j:
new_i = j + abs(shift_j - shift_i)
 new_j = i - abs(shift_j - shift_i)
 elif i - shift_i < j - shift_j:
new_i = j - abs(shift_j - shift_i)
 new_j = i + abs(shift_j - shift_i)
 else:
new_i, new_j = -1, -1
if(0 <= new_i and new_i < inp.shape[0] and 0 <= new_j and new_j < inp.shape[1] and inp[new_i][new_j] != extra_color):
res[i][j] = inp[new_i][new_j]
if(symmetric_side_diagonal):
side_diag_sum = shift_i + shift_j + size - 1
delta = side_diag_sum - i - j
if(delta % 2 == 0):
if(delta > 0):
delta += 1
elif(delta < 0):
delta -= 1
new_i = i + delta
new_j = j + delta
if(0 <= new_i and new_i < inp.shape[0] and 0 <= new_j and new_j < inp.shape[1] and
inp[new_i][new_j] != extra_color):
res[i][j] = inp[new_i][new_j]
if(np.any(res == extra_color)) :
delete_extra_color(res, extra_color)
 return res<categorify>
class IonDataset(Dataset):
def __init__(self, data, labels=None, type='train', transform=None):
self.data = data
self.labels = labels
self.type = type
self.transform = transform
def __getitem__(self, i):
signal = self.data[i].astype(np.float32)
 if self.type == 'train':
label = self.labels[i].astype(np.int64)
 if self.transform is not None:
signal, label = self.transform(signal, label)
 return signal, label
else:
return signal
def __len__(self):
return len(self.data )
def find_restored_matrix(inp: np.ndarray, out: np.ndarray, mode = 'train')-> list:

 min_possible_size = max(11, inp.shape[0] // 2)
 for size in range(min_possible_size, inp.shape[0] + 1, 1):
symmetric_axis_horizontal = None
symmetric_axis_vertical = None
for i in range(inp.shape[0] - size + 1):
for j in range(inp.shape[1] - size + 1):
sub_matrix = inp[i:i + size, j:j + size].copy()
result_horizontal = is_symmetric(sub_matrix, 1)
 result_vertical = is_symmetric(sub_matrix, 2)
 result_main_diag = is_symmetric(sub_matrix, 3)
 result_side_diag = is_symmetric(sub_matrix, 4)
 if(result_horizontal[0]):
extra_color = result_horizontal[1]
elif(result_vertical[0]):
extra_color = result_vertical[1]
elif(result_main_diag[0]):
extra_color = result_main_diag[1]
elif(result_side_diag[0]):
extra_color = result_side_diag[1]
else:
break
if(result_horizontal[0] and extra_color != result_horizontal[1]):
break
if(result_vertical[0] and extra_color != result_vertical[1]):
break
if(result_main_diag[0] and extra_color != result_main_diag[1]):
break
if(result_side_diag[0] and extra_color != result_side_diag[1]):
break
if(size % 2 == 0):
vertical_index = [0, 0]
vertical_index[0] =(j + j + size)// 2 - 1
vertical_index[1] =(j + j + size)// 2
horizontal_index = [0, 0]
horizontal_index[0] =(i + i + size)// 2 - 1
horizontal_index[1] =(i + i + size)// 2
if(result_horizontal[0]):
symmetric_axis_horizontal = horizontal_index
if(result_vertical[0]):
symmetric_axis_vertical = vertical_index
else:
vertical_index =(j + j + size)// 2
horizontal_index =(i + i + size)// 2
if(result_horizontal[0]):
symmetric_axis_horizontal = [horizontal_index, 0]
if(result_vertical[0]):
symmetric_axis_vertical = [vertical_index, 0]
cur = prediction(inp, symmetric_axis_horizontal, symmetric_axis_vertical,
result_main_diag[0], result_side_diag[0], i, j, size, extra_color)
 if(np.any(cur == extra_color)) :
continue
if(mode == 'train' and np.array_equal(cur, out)) :
return cur
elif(mode == 'test'):
return cur
return None<categorify>
class SEModule(nn.Module):
def __init__(self, in_channels, reduction=4):
super().__init__()
self.conv1 = nn.Conv1d(in_channels, in_channels//reduction, kernel_size=1, padding=0)
 self.conv2 = nn.Conv1d(in_channels//reduction, in_channels, kernel_size=1, padding=0)
 def forward(self, x):
s = F.adaptive_avg_pool1d(x, 1)
 s = self.conv1(s)
 s = F.relu(s, inplace=True)
 s = self.conv2(s)
 x = x + torch.sigmoid(s)
 return x
class ConvBR1d(nn.Module):
def __init__(self, in_channels, out_channels, kernel_size=1, padding=0, dilation=1, stride=1, groups=1, is_activation=True):
super().__init__()
self.conv = nn.Conv1d(in_channels, out_channels, kernel_size=kernel_size, padding=padding, dilation=dilation, stride=stride, groups=groups, bias=False)
 self.bn = nn.BatchNorm1d(out_channels)
 self.is_activation = is_activation
if is_activation:
self.relu = nn.ReLU(inplace=True)
 def forward(self, x):
x = self.bn(self.conv(x))
if self.is_activation:
x = self.relu(x)
 return x
class SENextBottleneck(nn.Module):
def __init__(self, in_channels, out_channels, stride=1, groups=32, reduction=16, pool=None, is_shortcut=False):
super().__init__()
mid_channels = out_channels // 2
self.conv1 = ConvBR1d(in_channels, mid_channels, 1, 0, 1,)
 self.conv2 = ConvBR1d(mid_channels, mid_channels, 3, 1, 1, groups=groups)
 self.conv3 = ConvBR1d(mid_channels, out_channels, 1, 0, 1, is_activation=False)
 self.se = SEModule(out_channels, reduction)
 self.stride = stride
self.is_shortcut = is_shortcut
if is_shortcut:
self.shortcut = ConvBR1d(in_channels, out_channels, 1, 0, 1, is_activation=False)
 if stride > 1:
if pool == 'max':
self.pool = nn.MaxPool1d(stride, stride)
 elif pool == 'avg':
self.pool = nn.AvgPool1d(stride, stride)
 def forward(self, x):
s = self.conv1(x)
 s = self.conv2(s)
 if self.stride > 1:
s = self.pool(s)
 s = self.conv3(s)
 s = self.se(s)
 if self.is_shortcut:
if self.stride > 1:
x = F.avg_pool1d(x, self.stride, self.stride)
 x = self.shortcut(x)
 x = x + s
x = F.relu(x, inplace=True)
 return x
class Encoder(nn.Module):
def __init__(self, num_features=1):
super().__init__()
self.block0 = nn.Sequential(
 ConvBR1d(num_features, encoder_channels[0], kernel_size=5, stride=1, padding=2),
ConvBR1d(encoder_channels[0], encoder_channels[0], kernel_size=3, stride=1, padding=1),
ConvBR1d(encoder_channels[0], encoder_channels[0], kernel_size=3, stride=1, padding=1), 
)
 self.block1 = nn.Sequential(
 SENextBottleneck(encoder_channels[0], encoder_channels[1], stride=stride, is_shortcut=True, pool='max'),
*[SENextBottleneck(encoder_channels[1], encoder_channels[1], stride=1, is_shortcut=False)for i in range(backbone[0])] 
)
 self.block2 = nn.Sequential(
 SENextBottleneck(encoder_channels[1], encoder_channels[2], stride=stride, is_shortcut=True, pool='max'),
*[SENextBottleneck(encoder_channels[2], encoder_channels[2], stride=1, is_shortcut=False)for i in range(backbone[1])] 
)
 self.block3 = nn.Sequential(
 SENextBottleneck(encoder_channels[2], encoder_channels[3], stride=stride, is_shortcut=True, pool='max'),
*[SENextBottleneck(encoder_channels[3], encoder_channels[3], stride=1, is_shortcut=False)for i in range(backbone[2])] 
)
 self.block4 = nn.Sequential(
 SENextBottleneck(encoder_channels[3], encoder_channels[4], stride=stride, is_shortcut=True, pool='avg'),
*[SENextBottleneck(encoder_channels[4], encoder_channels[4], stride=1, is_shortcut=False)for i in range(backbone[3])] 
)
 def forward(self, x):
x0 = self.block0(x)
 x1 = self.block1(x0)
 x2 = self.block2(x1)
 x3 = self.block3(x2)
 x4 = self.block4(x3)
 return [x0, x1, x2, x3, x4]
class SCSEModule(nn.Module):
def __init__(self, in_channels, reduction=16):
super().__init__()
self.cSE = nn.Sequential(
 nn.AdaptiveAvgPool1d(1),
nn.Conv1d(in_channels, in_channels // reduction, 1),
nn.ReLU(inplace=True),
nn.Conv1d(in_channels // reduction, in_channels, 1),
nn.Sigmoid() , 
)
 self.sSE = nn.Sequential(nn.Conv1d(in_channels, 1, 1), nn.Sigmoid())
 def forward(self, x):
return x * self.cSE(x)+ x * self.sSE(x)
 class DecoderBlock(nn.Module):
def __init__(self, in_channels, skip_channels, out_channels):
super().__init__()
self.conv1 = ConvBR1d(in_channels + skip_channels, out_channels, kernel_size=3, padding=1)
 self.conv2 = ConvBR1d(out_channels, out_channels, kernel_size=3, padding=1)
 def forward(self, x, skip=None):
x = F.interpolate(x, scale_factor=stride, mode="linear", align_corners=True)
 if skip is not None:
x = torch.cat([x, skip], dim=1)
 x = self.conv1(x)
 x = self.conv2(x)
 return x
class Decoder(nn.Module):
def __init__(self):
super().__init__()
self.block4 = DecoderBlock(encoder_channels[-1], encoder_channels[-2], decoder_channels[0])
 self.block3 = DecoderBlock(decoder_channels[0], encoder_channels[-3], decoder_channels[1])
 self.block2 = DecoderBlock(decoder_channels[1], encoder_channels[-4], decoder_channels[2])
 self.block1 = DecoderBlock(decoder_channels[2], encoder_channels[-5], decoder_channels[3])
 def forward(self, xs):
x = self.block4(xs[4], xs[3])
 x = self.block3(x, xs[2])
 x = self.block2(x, xs[1])
 x = self.block1(x, xs[0])
 return x
class Unet(nn.Module):
def __init__(self, num_features=1, num_classes=11):
super().__init__()
self.num_features = num_features
self.num_classes = num_classes
self.encoder = Encoder(num_features=num_features)
 self.decoder = Decoder()
self.segmentation_head = nn.Conv1d(decoder_channels[-1], num_classes, kernel_size=1, padding=0, stride=1)
 def forward(self, x):
features = self.encoder(x)
 x = self.decoder(features)
 x = self.segmentation_head(x)
 return x
def symmetry_algo(train_in: list, train_out: list, test_in: list)-> list:

 for inp, out in zip(train_in, train_out):
if(inp.shape[0] < 11):
return None
predict = find_restored_matrix(inp, out)
 if(predict is None):
return None
result = []
for test_inp in test_in:
if(test_inp.shape[0] < 11):
return None
predict = find_restored_matrix(test_inp, inp, mode = 'test')
 if(predict is None):
return None
result.append(predict)
 return result<define_variables>
class ClassificationMeter:

 def __init__(self, nCls, eps=1e-5, names=None):
self.nCls = nCls
self.names = names
self.eps = eps
self.N = 0
self.table = np.zeros(( self.nCls, 4), dtype=np.int32)
 self._measure = None
def clear(self):
self.N = 0
self.table = np.zeros(( self.nCls, 4), dtype=np.int32)
 def prepare_inputs(self, outputs, truths):

 if torch.is_tensor(outputs):
outputs = outputs.detach().cpu().numpy()
if torch.is_tensor(truths):
truths = truths.detach().cpu().numpy()
return outputs, truths
def update(self, preds, truths):
preds, truths = self.prepare_inputs(preds, truths)
 self.N += np.prod(truths.shape)
 for Cls in range(self.nCls):
true_positive = np.count_nonzero(np.bitwise_and(preds == Cls, truths == Cls))
true_negative = np.count_nonzero(np.bitwise_and(preds != Cls, truths != Cls))
false_positive = np.count_nonzero(np.bitwise_and(preds == Cls, truths != Cls))
false_negative = np.count_nonzero(np.bitwise_and(preds != Cls, truths == Cls))
self.table[Cls] += [true_positive, true_negative, false_positive, false_negative]
def measure(self):
return self._measure
def better(self, A, B):
return A > B
def write(self, writer, global_step, prefix=""):
writer.add_scalar(os.path.join(prefix, "Accuracy"), self.measure() , global_step)
 def report(self, each_class=False):
precisions = []
recalls = []
f1s = []
for Cls in range(self.nCls):
recall = self.table[Cls,0] /(self.table[Cls,0] + self.table[Cls,3] + self.eps)
 precision = self.table[Cls,0] /(self.table[Cls,0] + self.table[Cls,2] + self.eps)
 f1 = 2 * precision * recall /(precision + recall + self.eps)
 precisions.append(precision)
 recalls.append(recall)
 f1s.append(f1)
 total_TP = np.sum(self.table[:, 0])
 accuracy = total_TP/self.N
accuracy_mean_class = np.mean(precisions)
 macro_f1 = np.mean(f1s)
 self._measure = macro_f1
text = f"Macro F1 = {macro_f1:.4f}
"
text += f"\tOverall Accuracy = {accuracy:.4f}({total_TP}/{self.N})
 "
text += f"\tMean-class Accuracy = {accuracy_mean_class:.4f}
"
if each_class:
for Cls in range(self.nCls):
text += f"\tClass {str(Cls)+'('+self.names[Cls]+')' if self.names is not None else Cls}: precision = {precisions[Cls]:.3f} recall = {recalls[Cls]:.3f}
"
return text
data_folder = '.. /input/abstraction-and-reasoning-challenge/evaluation/'
results = pd.DataFrame(columns =('output_id', 'output'))
mode = 'Train'
correct_predictions = 0
total_predictions = 0
for filename in tqdm(os.listdir(data_folder)) :
full_path = os.path.join(data_folder, filename)
 train_input_matrices, train_output_matrices, test_input_matrices = load_task(full_path)
 if(mode == 'Train'):
with open(full_path, 'r')as jfile:
json_file = json.load(jfile)
 test_output_matrices = get_output_matrices_test(json_file)
 solution_found = False
if(check_size_1piece(train_input_matrices, train_output_matrices)) :
predictions = symmetry_algo(train_input_matrices, train_output_matrices, test_input_matrices)
 total_predictions += len(test_input_matrices)
 if predictions is not None:
print('Found for: ', filename)
 solution_found = True
for ind, test_out in enumerate(predictions):
filename = filename.split('.')[0]
results = results.append({'output_id': filename + '_' + str(ind), 'output': make_output(test_out)}, ignore_index = True)
 if(mode == 'Train'):
if(np.array_equal(test_out, test_output_matrices[ind])) :
correct_predictions += 1
plt.figure(figsize =(10, 5), dpi = 150)
 plot_matrix(test_input_matrices[ind], 131, 'Test input matrix')
 plot_matrix(test_output_matrices[ind], 132, 'Test output matrix')
 plot_matrix(test_out, 133, 'Test predicted matrix')
 plt.show()
if(not solution_found):
predictions = np.array([])
 for ind in range(len(test_input_matrices)) :
results = results.append({'output_id': filename.split('.')[0] + '_' + str(ind), 'output': make_output(predictions)}, ignore_index = True)
 if(mode == 'Train'):
print(f'Solved {correct_predictions} of {total_predictions}')
 results.to_csv('submission.csv', index = False )<import_modules>
def five_type_remove_drift(train):
a=500000; b=600000
train.loc[train.index[a:b],'signal'] = train.signal[a:b].values - 3*(train.time.values[a:b] - 50)/10.
 def f(x,low,high,mid):
return -(( -low+high)/625)*(x-mid)**2+high -low
batch = 7; a = 500000*(batch-1); b = 500000*batch
train.loc[train.index[a:b],'signal'] = train.signal.values[a:b] - f(train.time[a:b].values,-1.817,3.186,325)
 batch = 8; a = 500000*(batch-1); b = 500000*batch
train.loc[train.index[a:b],'signal'] = train.signal.values[a:b] - f(train.time[a:b].values,-0.094,4.936,375)
 batch = 9; a = 500000*(batch-1); b = 500000*batch
train.loc[train.index[a:b],'signal'] = train.signal.values[a:b] - f(train.time[a:b].values,1.715,6.689,425)
 batch = 10; a = 500000*(batch-1); b = 500000*batch
train.loc[train.index[a:b],'signal'] = train.signal.values[a:b] - f(train.time[a:b].values,3.361,8.45,475)
 return train
import numpy as np
import pandas as pd
from tqdm import tqdm<load_pretrained>
if TRAIN:
df_train = five_type_remove_drift(df_train)
 batch = 1; a = 500000*(batch-1); b = 500000*batch
batch = 2; c = 500000*(batch-1); d = 500000*batch
X_train_1s = np.concatenate([df_train.signal.values[a:b],df_train.signal.values[c:d]] ).reshape(( -1,1))
y_train_1s = np.concatenate([df_train.open_channels.values[a:b],df_train.open_channels.values[c:d]] ).reshape(( -1,1))
batch = 3; a = 500000*(batch-1); b = 500000*batch
batch = 7; c = 500000*(batch-1); d = 500000*batch
X_train_1f = np.concatenate([df_train.signal.values[a:b],df_train.signal.values[c:d]] ).reshape(( -1,1))
y_train_1f = np.concatenate([df_train.open_channels.values[a:b],df_train.open_channels.values[c:d]] ).reshape(( -1,1))
batch = 4; a = 500000*(batch-1); b = 500000*batch
batch = 8; c = 500000*(batch-1); d = 500000*batch
X_train_3 = np.concatenate([df_train.signal.values[a:b],df_train.signal.values[c:d]] ).reshape(( -1,1))
y_train_3 = np.concatenate([df_train.open_channels.values[a:b],df_train.open_channels.values[c:d]] ).reshape(( -1,1))
batch = 6; a = 500000*(batch-1); b = 500000*batch
batch = 9; c = 500000*(batch-1); d = 500000*batch
X_train_5 = np.concatenate([df_train.signal.values[a:b],df_train.signal.values[c:d]] ).reshape(( -1,1))
y_train_5 = np.concatenate([df_train.open_channels.values[a:b],df_train.open_channels.values[c:d]] ).reshape(( -1,1))
batch = 5; a = 500000*(batch-1); b = 500000*batch
batch = 10; c = 500000*(batch-1); d = 500000*batch
X_train_10 = np.concatenate([df_train.signal.values[a:b],df_train.signal.values[c:d]] ).reshape(( -1,1))
y_train_10 = np.concatenate([df_train.open_channels.values[a:b],df_train.open_channels.values[c:d]] ).reshape(( -1,1))
for X, y, num_classes, model_name, max_epoch in zip(
 [X_train_1s, X_train_1f, X_train_3, X_train_5, X_train_10],
[y_train_1s, y_train_1f, y_train_3, y_train_5, y_train_10],
np.array([1, 1, 3, 5, 10])+1,
['1s', '1f', '3', '5', '10'],
[30, 30, 60, 60, 120], 
):
X = X.reshape(-1, 1, time_step)
 y = y.reshape(-1, time_step)
 idx = np.arange(X.shape[0])
 kf = model_selection.KFold(5, shuffle=True, random_state=seed)
 train_idx, val_idx = list(kf.split(idx)) [fold]
print("model_name:", model_name)
 print("train dataset shape:", X[train_idx].shape, y[train_idx].shape)
 train_dataset = IonDataset(X[train_idx], y[train_idx], 'train', train_augment)
 valid_dataset = IonDataset(X[val_idx], y[val_idx], 'train', valid_augment)
 loaders = {
'train': DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4, pin_memory=True),
'valid': DataLoader(valid_dataset, batch_size=batch_size, shuffle=False, num_workers=4, pin_memory=True),
}
model = Unet(num_classes=num_classes)
 loss_function = nn.CrossEntropyLoss()
optimizer = optim.AdamW(model.parameters() , lr=0.001, weight_decay=1e-5)
 scheduler = lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=10, factor=0.1, min_lr=1e-8)
 metrics = [ClassificationMeter(num_classes),]
trainer = Trainer(device, workspace, model, optimizer, scheduler, loss_function, loaders, metrics,
model_name=model_name,
report_step_interval=-1, 
)
 trainer.train(max_epoch)
<load_pretrained><EOS> 
if PREDICT:
start=500
a = 0; b = 100000
df_test.loc[df_test.index[a:b],'signal'] = df_test.signal.values[a:b] - 3*(df_test.time.values[a:b]-start)/10.
 start=510
a = 100000; b = 200000
df_test.loc[df_test.index[a:b],'signal'] = df_test.signal.values[a:b] - 3*(df_test.time.values[a:b]-start)/10.
 start=540
a = 400000; b = 500000
df_test.loc[df_test.index[a:b],'signal'] = df_test.signal.values[a:b] - 3*(df_test.time.values[a:b]-start)/10.
 start=560
a = 600000; b = 700000
df_test.loc[df_test.index[a:b],'signal'] = df_test.signal.values[a:b] - 3*(df_test.time.values[a:b]-start)/10.
 start=570
a = 700000; b = 800000
df_test.loc[df_test.index[a:b],'signal'] = df_test.signal.values[a:b] - 3*(df_test.time.values[a:b]-start)/10.
 start=580
a = 800000; b = 900000
df_test.loc[df_test.index[a:b],'signal'] = df_test.signal.values[a:b] - 3*(df_test.time.values[a:b]-start)/10.
 def f(x):
return -(0.00788)*(x-625)**2+2.345 +2.58
a = 1000000; b = 1500000
df_test.loc[df_test.index[a:b],'signal'] = df_test.signal.values[a:b] - f(df_test.time[a:b].values)
 sub = pd.read_csv(".. /input/liverpool-ion-switching/sample_submission.csv", dtype={'time':str})
 predictors = {}
for num_classes, model_name in zip(
 np.array([1, 1, 3, 5, 10])+1,
['1s', '1f', '3', '5', '10'] 
):
if not ENSEMBLE:
models = [Unet(num_classes=num_classes),]
predictor = Predictor(device, models)
 predictor.load_checkpoint(os.path.join(workspace, f"{model_name}_best.pth.tar"), 0)
 else:
models = [
Unet(num_classes=num_classes),
]
predictor = Predictor(device, models)
 predictor.load_checkpoint(os.path.join("workspace/unet-wide-4k-f0", f"{model_name}_best.pth.tar"), 0)
 predictors[model_name] = predictor
for start, end, model_type in zip(
 np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])*100000,
np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20])*100000,
['1s', '3', '5', '1s', '1f', '10', '5', '10', '1s', '3', '1s'], 
):
X = df_test.signal.values[start:end].reshape(-1, 1, time_step_test)
 test_dataset = IonDataset(X, type='test')
 test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
 res = predictors[model_type].predict(test_loader)
 sub.iloc[start:end,1] = res
sub.to_csv("pred.csv", index=False)
 plt.figure(figsize=(20,5))
res = 1000
let = ['A','B','C','D','E','F','G','H','I','J']
plt.plot(range(0,df_test.shape[0],res),sub.open_channels[0::res])
 for i in range(5): plt.plot([i*500000,i*500000],[-5,12.5],'r')
 for i in range(21): plt.plot([i*100000,i*100000],[-5,12.5],'r:')
 for k in range(4): plt.text(k*500000+250000,10,str(k+1),size=20)
 for k in range(10): plt.text(k*100000+40000,7.5,let[k],size=16)
 plt.title('Test Data Predictions',size=16)
 plt.show()