forked from toimcio/SegNet-tensorflow
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathevaluation_object.py
More file actions
144 lines (122 loc) · 5.92 KB
/
Copy pathevaluation_object.py
File metadata and controls
144 lines (122 loc) · 5.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import tensorflow as tf
import numpy as np
def cal_loss(logits, labels, n_classes):
loss_weight = np.array(
[
0.02765, # Background
1.23494, # Cylinder
0.84016, # Cube
1.59231, # Sphere
]
)
labels = tf.to_int64(labels)
loss, accuracy, prediction = weighted_loss(logits, labels, number_class=n_classes, frequency=loss_weight)
return loss, accuracy, prediction
def weighted_loss(logits, labels, number_class, frequency):
"""
The reference paper is : https://arxiv.org/pdf/1411.4734.pdf
Median Frequency Balancing: alpha_c = median_freq/freq(c).
median_freq is the median of these frequencies
freq(c) is the number of pixles of class c divided by the total number of pixels in images where c is present
we weight each pixels by alpha_c
Inputs:
logits is the output from the inference, which is the output of the decoder layers without softmax.
labels: true label information
number_class: In the CamVid data set, it's 11 classes, or 12, because class 11 seems to be background?
frequency: is the frequency of each class
Outputs:
Loss
Accuracy
"""
label_flatten = tf.reshape(labels, [-1])
label_onehot = tf.one_hot(label_flatten, depth=number_class)
logits_reshape = tf.reshape(logits, [-1, number_class])
cross_entropy = tf.nn.weighted_cross_entropy_with_logits(targets=label_onehot, logits=logits_reshape,
pos_weight=frequency)
cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
tf.summary.scalar('loss', cross_entropy_mean)
correct_prediction = tf.equal(tf.argmax(logits_reshape, -1), label_flatten)
accuracy = tf.reduce_mean(tf.to_float(correct_prediction))
tf.summary.scalar('accuracy', accuracy)
return cross_entropy_mean, accuracy, tf.argmax(logits_reshape, -1)
def normal_loss(logits, labels, number_class):
"""
Calculate the normal loss instead of median frequency balancing
Inputs:
logits, the output from decoder layers, without softmax, shape [Num_batch,height,width,Number_class]
lables: the atual label information, shape [Num_batch,height,width,1]
number_class:12
Output:loss,and accuracy
Using tf.nn.sparse_softmax_cross_entropy_with_logits assume that each pixel have and only have one specific
label, instead of having a probability belongs to labels. Also assume that logits is not softmax, because it
will conduct a softmax internal to be efficient, this is the reason that we don't do softmax in the inference
function!
"""
label_flatten = tf.to_int64(tf.reshape(labels, [-1]))
logits_reshape = tf.reshape(logits, [-1, number_class])
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=label_flatten, logits=logits_reshape,
name='normal_cross_entropy')
cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
tf.summary.scalar('mean cross entropy', cross_entropy_mean)
correct_prediction = tf.equal(tf.argmax(logits_reshape, -1), label_flatten)
accuracy = tf.reduce_mean(tf.to_float(correct_prediction))
tf.summary.scalar('accuracy', accuracy)
return cross_entropy_mean, accuracy, tf.argmax(logits_reshape, -1)
def per_class_acc(predictions, label_tensor, num_class):
"""
This function is copied from "Implement slightly different segnet on tensorflow"
"""
labels = label_tensor
size = predictions.shape[0]
hist = np.zeros((num_class, num_class))
for i in range(size):
hist += fast_hist(labels[i].flatten(), predictions[i].argmax(2).flatten(), num_class)
acc_total = np.diag(hist).sum() / hist.sum()
print('accuracy = %f' % np.nanmean(acc_total))
iu = np.diag(hist) / (hist.sum(1) + hist.sum(0) - np.diag(hist))
print('mean IU = %f' % np.nanmean(iu))
for ii in range(num_class):
if float(hist.sum(1)[ii]) == 0:
acc = 0.0
else:
acc = np.diag(hist)[ii] / float(hist.sum(1)[ii])
print(" class # %d accuracy = %f " % (ii, acc))
def fast_hist(a, b, n):
"""
This function is copied from "Implement slightly different segnet on tensorflow"
"""
k = (a >= 0) & (a < n)
return np.bincount(n * a[k].astype(int) + b[k], minlength=n ** 2).reshape(n, n)
def get_hist(predictions, labels):
"""
This function is copied from "Implement slightly different segnet on tensorflow"
"""
num_class = predictions.shape[3] # becomes 2 for aerial - correct
batch_size = predictions.shape[0]
hist = np.zeros((num_class, num_class))
for i in range(batch_size):
hist += fast_hist(labels[i].flatten(), predictions[i].argmax(2).flatten(), num_class)
return hist
def print_hist_summary(hist):
"""
This function is copied from "Implement slightly different segnet on tensorflow"
"""
acc_total = np.diag(hist).sum() / hist.sum()
print('accuracy = %f' % np.nanmean(acc_total))
iu = np.diag(hist) / (hist.sum(1) + hist.sum(0) - np.diag(hist))
print('mean IU = %f' % np.nanmean(iu))
for ii in range(hist.shape[0]):
if float(hist.sum(1)[ii]) == 0:
acc = 0.0
else:
acc = np.diag(hist)[ii] / float(hist.sum(1)[ii])
print(" class # %d accuracy = %f " % (ii, acc))
def train_op(total_loss, learning_rate):
global_step = tf.train.get_or_create_global_step()
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
training_op = tf.train.AdamOptimizer(learning_rate=learning_rate,
beta1=0.5).minimize(loss=total_loss,
global_step=global_step,
var_list=tf.trainable_variables())
return training_op, global_step