Kaggle 題目 Dogs vs。 Cats Redux: Kernels Edition
框架:Tensorflow(上層框架使用TF-slim)
問題描述:輸入圖片,判斷圖片中為貓還是狗。
實現方法:Fine-tune TF-slim中提供的VGG-19神經網路。
預訓練模型引數:
https://
github。com/tensorflow/m
odels/tree/master/research/slim
資料集:Dogs vs。 Cats Redux: Kernels Edition
程式碼:2012013382/Cat_or_dog-kaggle-vgg16-tensorflow
資料預處理
讀入資料將圖片整理為矩陣形式,將標籤整理為one_hot形式。注意VGG_19的輸入必須為[Batch_size, 224, 224, 3]。
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
numpy
as
np
from
scipy。misc
import
imread
,
imresize
from
os
import
walk
from
os。path
import
join
import
tensorflow
as
tf
def
read_images
(
path
,
classes
,
img_height
=
224
,
img_width
=
224
,
img_channels
=
3
):
filenames
=
(
walk
(
path
))
。
next
()[
2
]
num_files
=
len
(
filenames
)
images
=
np
。
zeros
((
num_files
,
img_height
,
img_width
,
img_channels
),
dtype
=
np
。
float32
)
labels
=
np
。
zeros
((
num_files
,
),
dtype
=
np
。
int32
)
for
i
,
filename
in
enumerate
(
filenames
):
img
=
imread
(
join
(
path
,
filename
))
#read train data
img
=
imresize
(
img
,
(
img_height
,
img_width
))
#resize image to 224x224
img
。
astype
(
np
。
float32
)
images
[
i
,
:,
:,
:]
=
img
labels
[
i
]
=
classes
。
index
(
filename
[
0
:
3
])
# Luckily both ‘cat’ and ‘dog’ have 3 characters
# Convert from [0, 255] -> [-0。5, 0。5] floats。
#images[i, :, :, :] = images[i, :, :, :] * (1。 / 255) - 0。5
one_hot_labels
=
np
。
zeros
((
num_files
,
len
(
classes
)))
if
i
%
1000
==
0
:
(
‘Load the
%d
image of 25000。’
%
(
i
))
for
i
in
range
(
num_files
):
one_hot_labels
[
i
,
labels
[
i
]]
=
1
return
images
,
one_hot_labels
#Read image function for kaggle test data
def
read_images_kaggle_result
(
path
,
img_height
=
224
,
img_width
=
224
,
img_channels
=
3
):
filenames
=
(
walk
(
path
))
。
next
()[
2
]
num_files
=
len
(
filenames
)
images
=
np
。
zeros
((
num_files
,
img_height
,
img_width
,
img_channels
),
dtype
=
np
。
float32
)
for
i
,
filename
in
enumerate
(
filenames
):
img
=
imread
(
join
(
path
,
filename
))
#read train data
img
=
imresize
(
img
,
(
img_height
,
img_width
))
#resize image to 224x224
img
。
astype
(
np
。
float32
)
images
[
int
(
filename
[:
-
4
])
-
1
,
:,
:,
:]
=
img
#images[int(filename[:-4]) - 1, :, :, :] = images[int(filename[:-4]) - 1, :, :, :] * (1。 / 255) - 0。5
if
i
%
1000
==
0
:
(
‘Load the
%d
image of 12500。’
%
(
i
))
return
images
Kaggle提供的訓練集中共有25000張圖片,取其中30%作為驗證集,用於調參;其他作為訓練集,用於訓練模型。TensorFlow有利用佇列讀取資料的方式,能夠高效從磁碟中讀取資料,具體可以參考其官方教程。這裡為了方便,我使用簡單的一次性讀取的方法將資料弄成一batch的形式,用於之後的輸入。
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
manage_images
import
numpy
as
np
IMG_CLASSES
=
[
‘cat’
,
‘dog’
]
DATA_DIR
=
‘data/’
TRAIN_DATA_PATH
=
‘data/train/’
TEST_DATA_PATH
=
‘data/test/’
IMG_HEIGHT
=
int
(
224
)
#image shape [224,224,3] to fit VGG_16 input shape。
IMG_WIDTH
=
int
(
224
)
IMG_CHANNELS
=
3
NUM_FILES_DATASET
=
25000
#data size 25000; train data size 17500; test data size 7500
VALIDATION_SET_FRACTION
=
0。3
#validation size properbility
NUM_TRAIN_EXAMPLES
=
int
((
1
-
VALIDATION_SET_FRACTION
)
*
NUM_FILES_DATASET
)
NUM_VALIDATION_EXAMPLES
=
int
((
VALIDATION_SET_FRACTION
)
*
NUM_FILES_DATASET
)
NUM_KAGGLE_TEST
=
12500
def
pre_processing
(
data_set
=
‘train’
,
batch_size
=
32
):
if
data_set
is
‘train’
:
images
,
labels
=
manage_images
。
read_images
(
TRAIN_DATA_PATH
,
IMG_CLASSES
,
IMG_HEIGHT
,
IMG_WIDTH
,
IMG_CHANNELS
)
#Substract mean value
train_mean
=
np
。
mean
(
images
,
axis
=
0
)
# Random sample
validation_images
=
[]
validation_labels
=
[]
train_images
=
[]
train_labels
=
[]
validation_size
=
int
(
VALIDATION_SET_FRACTION
*
len
(
images
))
idx
=
np
。
random
。
permutation
(
len
(
images
))
for
i
in
idx
:
if
i
<
validation_size
:
validation_images
。
append
(
images
[
i
]
-
train_mean
)
validation_labels
。
append
(
labels
[
i
])
else
:
train_images
。
append
(
images
[
i
]
-
train_mean
)
train_labels
。
append
(
labels
[
i
])
train_batch_num
=
NUM_TRAIN_EXAMPLES
//
batch_size
validation_batch_num
=
NUM_VALIDATION_EXAMPLES
//
batch_size
pointer
=
0
batch_train_images
=
[]
batch_train_labels
=
[]
batch_validation_images
=
[]
batch_validation_labels
=
[]
for
_
in
range
(
train_batch_num
):
batch_train_images
。
append
(
train_images
[
pointer
:
pointer
+
batch_size
])
batch_train_labels
。
append
(
train_labels
[
pointer
:
pointer
+
batch_size
])
pointer
=
pointer
+
batch_size
pointer
=
0
for
_
in
range
(
validation_batch_num
):
batch_validation_images
。
append
(
validation_images
[
pointer
:
pointer
+
batch_size
])
batch_validation_labels
。
append
(
validation_labels
[
pointer
:
pointer
+
batch_size
])
pointer
=
pointer
+
batch_size
batch_validation_set
=
{
‘images’
:
batch_validation_images
,
‘labels’
:
batch_validation_labels
}
batch_train_set
=
{
‘images’
:
batch_train_images
,
‘labels’
:
batch_train_labels
}
image_num
=
{
‘train’
:
NUM_TRAIN_EXAMPLES
,
‘validation’
:
NUM_VALIDATION_EXAMPLES
}
return
batch_train_set
,
batch_validation_set
,
image_num
elif
data_set
is
‘test’
:
images
=
manage_images
。
read_images_kaggle_result
(
TEST_DATA_PATH
,
IMG_HEIGHT
,
IMG_WIDTH
,
IMG_CHANNELS
)
#Substract mean
mean
=
np
。
mean
(
images
,
axis
=
0
)
images
=
images
-
mean
batch_test_images
=
[]
batch_num
=
NUM_KAGGLE_TEST
//
batch_size
pointer
=
0
for
_
in
range
(
batch_num
):
batch_test_images
。
append
(
images
[
pointer
:
pointer
+
batch_size
])
pointer
=
pointer
+
batch_size
batch_test_set
=
{
‘images’
:
batch_test_images
}
return
batch_test_set
訓練
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
numpy
as
np
import
time
import
data_processing
import
tensorflow
as
tf
import
tensorflow。contrib。slim
as
slim
import
tensorflow。contrib。slim。nets
as
nets
import
os
import
os。path
import
time
TRAIN_LOG_DIR
=
os
。
path
。
join
(
‘Log/train/’
,
time
。
strftime
(
‘%Y-%m-
%d
%H:%M:%S’
,
time
。
localtime
(
time
。
time
())))
TRAIN_CHECK_POINT
=
‘check_point/train_model。ckpt’
VALIDATION_LOG_DIR
=
‘Log/validation/’
VGG_19_MODEL_DIR
=
‘check_point/vgg_19。ckpt’
BATCH_SIZE
=
32
EPOCH
=
3
if
not
tf
。
gfile
。
Exists
(
TRAIN_LOG_DIR
):
tf
。
gfile
。
MakeDirs
(
TRAIN_LOG_DIR
)
if
not
tf
。
gfile
。
Exists
(
VALIDATION_LOG_DIR
):
tf
。
gfile
。
MakeDirs
(
VALIDATION_LOG_DIR
)
batch_train_set
,
batch_validation_set
,
images_num
=
data_processing
。
pre_processing
(
data_set
=
‘train’
,
batch_size
=
BATCH_SIZE
)
def
get_accuracy
(
logits
,
labels
):
correct_prediction
=
tf
。
equal
(
tf
。
argmax
(
logits
,
1
),
tf
。
argmax
(
labels
,
1
))
accuracy
=
tf
。
reduce_mean
(
tf
。
cast
(
correct_prediction
,
tf
。
float32
))
return
accuracy
with
tf
。
Graph
()
。
as_default
():
images
=
tf
。
placeholder
(
tf
。
float32
,
[
BATCH_SIZE
,
224
,
224
,
3
])
labels
=
tf
。
placeholder
(
tf
。
float32
,
[
BATCH_SIZE
,
len
(
data_processing
。
IMG_CLASSES
)])
keep_prob
=
tf
。
placeholder
(
tf
。
float32
)
with
slim
。
arg_scope
(
nets
。
vgg
。
vgg_arg_scope
()):
logits
,
_
=
nets
。
vgg
。
vgg_19
(
inputs
=
images
,
num_classes
=
2
,
dropout_keep_prob
=
keep_prob
,
is_training
=
True
)
variables_to_restore
=
slim
。
get_variables_to_restore
(
exclude
=
[
‘vgg_19/fc8’
])
restorer
=
tf
。
train
。
Saver
(
variables_to_restore
)
with
tf
。
name_scope
(
‘cross_entropy’
):
loss
=
tf
。
reduce_mean
(
tf
。
nn
。
softmax_cross_entropy_with_logits
(
logits
=
logits
,
labels
=
labels
))
tf
。
summary
。
scalar
(
‘cross_entropy’
,
loss
)
learning_rate
=
1e-4
optimizer
=
tf
。
train
。
AdamOptimizer
(
learning_rate
)
。
minimize
(
loss
)
with
tf
。
name_scope
(
‘accuracy’
):
accuracy
=
get_accuracy
(
logits
,
labels
)
tf
。
summary
。
scalar
(
‘accuracy’
,
accuracy
)
merged
=
tf
。
summary
。
merge_all
()
saver
=
tf
。
train
。
Saver
()
config
=
tf
。
ConfigProto
()
config
。
gpu_options
。
allow_growth
=
True
with
tf
。
Session
(
config
=
config
)
as
sess
:
train_writer
=
tf
。
summary
。
FileWriter
(
TRAIN_LOG_DIR
)
#train_writer。add_summary(sess。graph)
sess
。
run
(
tf
。
global_variables_initializer
())
sess
。
run
(
tf
。
local_variables_initializer
())
restorer
。
restore
(
sess
,
VGG_19_MODEL_DIR
)
step
=
0
for
ep
in
range
(
EPOCH
):
all_accuracy
=
0
all_loss
=
0
for
i
in
range
(
images_num
[
‘train’
]
//
BATCH_SIZE
):
_
,
accuracy_out
,
loss_out
,
summary
=
sess
。
run
([
optimizer
,
accuracy
,
loss
,
merged
],
feed_dict
=
{
images
:
batch_train_set
[
‘images’
][
i
],
\
labels
:
batch_train_set
[
‘labels’
][
i
],
keep_prob
:
0。5
})
train_writer
。
add_summary
(
summary
,
step
)
step
+=
1
all_accuracy
+=
accuracy_out
all_loss
+=
loss_out
if
i
%
10
==
0
:
(
“Epoch
%d
: Batch
%d
accuracy is
%。2f
; Batch loss is
%。5f
”
%
(
ep
+
1
,
i
,
accuracy_out
,
loss_out
))
(
“Epoch
%d
: Train accuracy is
%。2f
; Train loss is
%。5f
”
%
(
ep
+
1
,
all_accuracy
/
(
images_num
[
‘train’
]
//
BATCH_SIZE
),
all_loss
/
(
images_num
[
‘train’
]
//
BATCH_SIZE
)))
all_accuracy
=
0
all_loss
=
0
for
i
in
range
(
images_num
[
‘validation’
]
//
BATCH_SIZE
):
accuracy_out
,
loss_out
=
sess
。
run
([
accuracy
,
loss
],
feed_dict
=
{
images
:
batch_validation_set
[
‘images’
][
i
],
\
labels
:
batch_validation_set
[
‘labels’
][
i
],
keep_prob
:
1。0
})
all_accuracy
+=
accuracy_out
all_loss
+=
loss_out
(
“Epoch
%d
: Validation accuracy is
%。2f
; Validation loss is
%。5f
”
%
(
ep
+
1
,
all_accuracy
/
(
images_num
[
‘validation’
]
//
BATCH_SIZE
),
all_loss
/
(
images_num
[
‘validation’
]
//
BATCH_SIZE
)))
saver
。
save
(
sess
,
TRAIN_CHECK_POINT
,
global_step
=
ep
)
在我的實驗中驗證集上的準去率為97%。
測試
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
print_function
import
data_processing
import
tensorflow
as
tf
import
tensorflow。contrib。slim
as
slim
import
tensorflow。contrib。slim。nets
as
nets
import
csv
as
csv
CHECK_POINT_PATH
=
‘check_point/train_model。ckpt-2’
NUM_KAGGLE_TEST
=
12500
BATCH_SIZE
=
50
batch_test_set
=
data_processing
。
pre_processing
(
data_set
=
‘test’
,
batch_size
=
BATCH_SIZE
)
prediction_file
=
open
(
‘kaggle_result_file。csv’
,
‘wb’
)
prediction_file_object
=
csv
。
writer
(
prediction_file
)
prediction_file_object
。
writerow
([
‘id’
,
‘label’
])
with
tf
。
Graph
()
。
as_default
():
images
=
tf
。
placeholder
(
tf
。
float32
,
[
BATCH_SIZE
,
224
,
224
,
3
])
keep_prob
=
tf
。
placeholder
(
tf
。
float32
)
logits
,
_
=
nets
。
vgg
。
vgg_19
(
inputs
=
images
,
num_classes
=
2
,
dropout_keep_prob
=
keep_prob
,
is_training
=
False
)
variables_to_restore
=
slim
。
get_variables_to_restore
()
restorer
=
tf
。
train
。
Saver
(
variables_to_restore
)
pros
=
tf
。
nn
。
softmax
(
logits
)
config
=
tf
。
ConfigProto
()
config
。
gpu_options
。
allow_growth
=
True
with
tf
。
Session
(
config
=
config
)
as
sess
:
sess
。
run
(
tf
。
global_variables_initializer
())
sess
。
run
(
tf
。
local_variables_initializer
())
restorer
。
restore
(
sess
,
CHECK_POINT_PATH
)
for
i
in
range
(
NUM_KAGGLE_TEST
//
BATCH_SIZE
):
batch_pros
=
sess
。
run
(
pros
,
feed_dict
=
{
images
:
batch_test_set
[
‘images’
][
i
],
keep_prob
:
1。0
})
(
‘Batch
%d
of
%d
’
%
(
i
,
NUM_KAGGLE_TEST
//
BATCH_SIZE
))
for
j
in
range
(
BATCH_SIZE
):
temp
=
0。0
if
batch_pros
[
j
,
1
]
>
0。5
:
temp
=
0。995
else
:
temp
=
0。005
prediction_file_object
。
writerow
([
i
*
BATCH_SIZE
+
j
+
1
,
temp
])
prediction_file
。
close
()