一、加载模型

from keras.models import load_model
model = load_model(r"E:\Kaggle\salt\competition_data/model\Kaggle_Salt_02-0.924.hdf5")

 

二、识别图片

从验证集随机选择图片,识别显示:

max_images = 10
grid_width = 10
grid_height = int(max_images / grid_width) + 2
show_ids = np.random.randint(0,len(valid_ids),size=max_images)
fig, axs
= plt.subplots(grid_height, grid_width, figsize=(20, 4)) for i, idx in enumerate(valid_ids[show_ids]): img = train_df.loc[idx].images mask = train_df.loc[idx].masks ax = axs[int(i / grid_width), i % grid_width] ax.imshow(img, cmap="Greys") ax = axs[int(i / grid_width)+1, i % grid_width] ax.imshow(mask, cmap="Greens") ax = axs[int(i / grid_width)+2, i % grid_width] ax.imshow(preds_valid[i], cmap="Greens") ax.set_yticklabels([]) ax.set_xticklabels([]) plt.show()

 

Kaggle图像分割比赛:keras平台训练unet++模型识别盐沉积区(二)

 

 

结果识别的好像不太好。 

 

三、根据验证集找最佳阈值

# src: https://www.kaggle.com/aglotero/another-iou-metric
def iou_metric(y_true_in, y_pred_in, print_table=False):
    labels = y_true_in
    y_pred = y_pred_in
    
    true_objects = 2
    pred_objects = 2

    intersection = np.histogram2d(labels.flatten(), y_pred.flatten(), bins=(true_objects, pred_objects))[0]

    # Compute areas (needed for finding the union between all objects)
    area_true = np.histogram(labels, bins = true_objects)[0]
    area_pred = np.histogram(y_pred, bins = pred_objects)[0]
    area_true = np.expand_dims(area_true, -1)
    area_pred = np.expand_dims(area_pred, 0)

    # Compute union
    union = area_true + area_pred - intersection

    # Exclude background from the analysis
    intersection = intersection[1:,1:]
    union = union[1:,1:]
    union[union == 0] = 1e-9

    # Compute the intersection over union
    iou = intersection / union

    # Precision helper function
    def precision_at(threshold, iou):
        matches = iou > threshold
        true_positives = np.sum(matches, axis=1) == 1   # Correct objects
        false_positives = np.sum(matches, axis=0) == 0  # Missed objects
        false_negatives = np.sum(matches, axis=1) == 0  # Extra objects
        tp, fp, fn = np.sum(true_positives), np.sum(false_positives), np.sum(false_negatives)
        return tp, fp, fn

    # Loop over IoU thresholds
    prec = []
    if print_table:
        print("Thresh\tTP\tFP\tFN\tPrec.")
    for t in np.arange(0.5, 1.0, 0.05):
        tp, fp, fn = precision_at(t, iou)
        if (tp + fp + fn) > 0:
            p = tp / (tp + fp + fn)
        else:
            p = 0
        if print_table:
            print("{:1.3f}\t{}\t{}\t{}\t{:1.3f}".format(t, tp, fp, fn, p))
        prec.append(p)
    
    if print_table:
        print("AP\t-\t-\t-\t{:1.3f}".format(np.mean(prec)))
    return np.mean(prec)

def iou_metric_batch(y_true_in, y_pred_in):
    batch_size = y_true_in.shape[0]
    metric = []
    for batch in range(batch_size):
        value = iou_metric(y_true_in[batch], y_pred_in[batch])
        metric.append(value)
    return np.mean(metric)

识别验证集:

preds_valid = model.predict(valid_x).reshape(-1, train_img_w, train_img_h)
preds_valid = np.array([train2orig(x) for x in preds_valid])
valid_y_ori = np.array([train_df.loc[idx].masks for idx in valid_ids])

thresholds = np.linspace(0, 1, 50)
ious = np.array([iou_metric_batch(valid_y_ori, np.int32(preds_valid > threshold)) for threshold in thresholds])

根据iou和阈值的对应关系得到最佳阈值:

threshold_best_index = np.argmax(ious)
iou_best = ious[threshold_best_index]
threshold_best = thresholds[threshold_best_index]
plt.plot(thresholds, ious)
plt.plot(threshold_best, iou_best, "xr", label="Best threshold")
plt.xlabel("Threshold")
plt.ylabel("IoU")
plt.title("Threshold vs IoU ({}, {})".format(threshold_best, iou_best))
plt.legend()
plt.show()

Kaggle图像分割比赛:keras平台训练unet++模型识别盐沉积区(二)

 

 

 

四、生成结果文件

得到测试集id:

depths_df = pd.read_csv(depths_csv, index_col="id")
train_df = train_df.join(depths_df)
test_df = depths_df[~depths_df.index.isin(train_df.index)]
# Source https://www.kaggle.com/bguberfain/unet-with-depth
def RLenc(img, order='F', format=True):
    """
    img is binary mask image, shape (r,c)
    order is down-then-right, i.e. Fortran
    format determines if the order needs to be preformatted (according to submission rules) or not

    returns run length as an array or string (if format is True)
    """
    bytes = img.reshape(img.shape[0] * img.shape[1], order=order)
    runs = []  ## list of run lengths
    r = 0  ## the current run length
    pos = 1  ## count starts from 1 per WK
    for c in bytes:
        if (c == 0):
            if r != 0:
                runs.append((pos, r))
                pos += r
                r = 0
            pos += 1
        else:
            r += 1

    # if last run is unsaved (i.e. data ends with 1)
    if r != 0:
        runs.append((pos, r))
        pos += r
        r = 0

    if format:
        z = ''

        for rr in runs:
            z += '{} {} '.format(rr[0], rr[1])
        return z[:-1]
    else:
        return runs

读取测试集图片:

x_test = np.array([orig2tain(np.array(load_img("{}/images/{}.png".format(test_imgs_path, idx), grayscale=False))) / 255 for idx in test_df.index]).reshape(-1, train_img_w, train_img_h, 3)

识别:

preds_test = model.predict(x_test)

根据最佳阈值得到结果文件:

threshold_best = round(threshold_best, 5)
pred_dict = {idx: RLenc(np.round(train2orig(preds_test[i]) > threshold_best)) for i, idx in enumerate(test_df.index.values)}

sub = pd.DataFrame.from_dict(pred_dict,orient='index')
sub.index.names = ['id']
sub.columns = ['rle_mask']
sub.to_csv(root + r'\submission.csv')

 

五、结果提交到Kaggle

需先注册,才能参加比赛,提交结果。提交后Public Score:0.68594、Private Score:0.72593,和第一名0.89646还有不小距离,排名2500/3229,很一般。

Kaggle图像分割比赛:keras平台训练unet++模型识别盐沉积区(二)