mid-checkpoint-fastai-resnet50

From: https://www.kaggle.com/calemolech/mid-checkpoint-fastai-resnet50

Author: Huy Tran

Score: 0.605

EDA CSV

In [1]:
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np 
import pandas as pd 
import gc
import os
import PIL

from scipy import stats
from multiprocessing import Pool
from PIL import ImageOps, ImageFilter
from tqdm import tqdm
pd.set_option("max_columns",300)
pd.set_option("max_rows",1103)
from wordcloud import WordCloud

tqdm.pandas()
In [2]:
df_train = pd.read_csv('../input/imet-2019-fgvc6/train.csv')
train_path = '../input/imet-2019-fgvc6/train/'
label_df = pd.read_csv('../input/imet-2019-fgvc6/labels.csv')
In [3]:
label_names = label_df['attribute_name'].values

num_labels = np.zeros((df_train.shape[0],))
train_labels = np.zeros((df_train.shape[0], len(label_names)))

for row_index, row in enumerate(df_train['attribute_ids']):
    num_labels[row_index] = len(row.split())    
    for label in row.split():
        train_labels[row_index, int(label)] = 1
In [4]:
culture, tag, unknown = 0, 0, 0

for l in label_names:
    if l[:3] == 'cul':
        culture += 1
    elif l[:3] == 'tag':
        tag += 1
    else:
        unknown += 1
        
print(f'Culture : {culture}')
print(f'Tag     : {tag}')
print(f'Unknown : {unknown}')
print(f'Total   : {culture + tag + unknown}')
Culture : 398
Tag     : 705
Unknown : 0
Total   : 1103
In [5]:
label_df['is_culture'] = label_df['attribute_name'].apply(lambda x: 1 if 'culture' in x else 0)
attribute_count = label_df['is_culture'].value_counts()

ax = sns.barplot(['Tag', 'Culture'], attribute_count.values, alpha=0.8)
for p in ax.patches:
    ax.annotate(f'{p.get_height()}\n{p.get_height() * 100 / label_df.shape[0]:.2f}%',
                (p.get_x() + p.get_width()/2., p.get_height()), 
                ha='center', 
                va='center', 
                fontsize=12, 
                color='black',
                xytext=(2,-20), 
                textcoords='offset points')
plt.title('Culture/Tag')
plt.xlabel('attribute type')
plt.ylabel('Frequency')
Out[5]:
Text(0, 0.5, 'Frequency')
In [6]:
label_sum = np.sum(train_labels, axis=0)

culture_sequence = label_sum[:398].argsort()[::-1]
tag_sequence = label_sum[398:].argsort()[::-1]

culture_labels = [label_names[x][9:] for x in culture_sequence]
culture_counts = [label_sum[x] for x in culture_sequence]

tag_labels = [label_names[x + 398][5:] for x in tag_sequence]
tag_counts = [label_sum[x + 398] for x in tag_sequence]
In [7]:
for i in range(len(culture_labels)):
    print(culture_labels[i],':',culture_counts[i])
french : 13522.0
italian : 10375.0
american : 9151.0
british : 7615.0
japan : 7394.0
egyptian : 6542.0
china : 5382.0
german : 5163.0
turkish or venice : 4416.0
islamic : 3500.0
greek : 2050.0
roman : 1881.0
dutch : 1762.0
spanish : 1403.0
cypriot : 1327.0
netherlandish : 1302.0
london : 838.0
central european : 831.0
paris : 810.0
flemish : 787.0
attic : 676.0
mexican : 595.0
india : 593.0
indonesia : 580.0
iran : 545.0
austrian : 530.0
venice : 523.0
bohemian : 515.0
european : 499.0
etruscan : 494.0
sasanian : 467.0
american or european : 408.0
meissen : 403.0
staffordshire : 388.0
russian : 368.0
moche : 362.0
swiss : 328.0
sevres : 317.0
south italian : 293.0
babylonian : 292.0
minoan : 281.0
korea : 269.0
florence : 254.0
assyrian : 244.0
byzantine : 240.0
paracas : 233.0
south netherlandish : 219.0
thailand : 210.0
naples : 207.0
augsburg : 177.0
rome : 157.0
pakistan : 152.0
vienna : 148.0
chimu : 146.0
belgian : 141.0
chelsea : 133.0
eastern mediterranean : 127.0
apulian : 121.0
bactria-margiana archaeological complex : 119.0
inca : 118.0
worcester : 118.0
tibet : 118.0
laconian : 116.0
lydian : 114.0
swedish : 112.0
nuremberg : 111.0
italic : 108.0
brussels : 106.0
achaemenid : 100.0
milan : 97.0
peruvian : 96.0
irish : 95.0
for british market : 94.0
for european market : 93.0
nasca : 93.0
parthian : 93.0
scandinavian : 90.0
hungarian : 88.0
nepal : 82.0
birmingham : 82.0
rouen : 81.0
southern german : 81.0
delft : 80.0
turkish : 77.0
maya : 76.0
cambodia : 74.0
aztec : 72.0
danish : 72.0
catalan : 72.0
campanian : 71.0
mezcala : 71.0
old assyrian trading colony : 71.0
italian or spanish : 69.0
genoa : 69.0
wari : 68.0
unknown : 66.0
sumerian : 64.0
geneva : 64.0
limoges : 63.0
mycenaean : 63.0
st. petersburg : 63.0
lyons : 62.0
portuguese : 61.0
crete : 61.0
east greek : 60.0
tarentine : 60.0
philippine : 60.0
corinthian : 59.0
vietnam : 59.0
east greek/sardis : 58.0
northern italian : 56.0
olmec : 56.0
greek islands : 55.0
greek or roman : 53.0
sheffield : 52.0
hochst : 52.0
frankish : 52.0
syrian : 50.0
berlin : 50.0
beauvais : 48.0
neo-sumerian : 48.0
scottish : 46.0
seville : 45.0
dublin : 45.0
colima : 44.0
jouy-en-josas : 44.0
urbino : 44.0
central asia : 43.0
nymphenburg : 43.0
cretan : 43.0
north china : 43.0
atlantic watershed : 41.0
deruta : 41.0
tibetan : 40.0
saint-cloud : 40.0
etruria : 40.0
norwegian : 39.0
sicily : 39.0
ica : 38.0
frankenthal : 38.0
padua : 38.0
mitanni : 38.0
french or italian : 37.0
saxony : 37.0
javanese : 36.0
ghassulian : 36.0
boeotian : 35.0
versailles : 35.0
nantes : 35.0
bow : 34.0
amsterdam : 34.0
burslem : 33.0
nabataean : 33.0
polish : 33.0
for american market : 32.0
neolithic : 32.0
villanovan : 32.0
strasbourg : 32.0
elamite : 32.0
north italian : 30.0
lambayeque : 30.0
copenhagen : 30.0
ptolemaic : 30.0
thuringia : 29.0
zurich : 29.0
chantilly : 29.0
bristol : 29.0
for portuguese market : 29.0
chiriqui : 28.0
akkadian : 28.0
northwest china : 28.0
seleucid : 27.0
hattian : 27.0
gubbio : 26.0
dresden : 26.0
fulda : 26.0
silesia : 26.0
vincennes : 25.0
derby : 25.0
chaumont-sur-loire : 24.0
siena : 23.0
hilt : 23.0
egypt : 23.0
mughal : 22.0
madrid : 22.0
urartian : 22.0
calima : 22.0
costa rica : 22.0
asia minor : 22.0
stoke-on-trent : 22.0
french or swiss : 22.0
caucasian : 22.0
veraguas : 21.0
tairona : 21.0
helladic : 21.0
ludwigsburg : 21.0
munich : 21.0
mennecy : 21.0
veracruz : 20.0
antwerp : 20.0
valencia : 19.0
nayarit : 19.0
colonial american : 19.0
tlatilco : 19.0
for continental market : 19.0
cycladic : 19.0
gaul : 18.0
abruzzi : 18.0
sri lankan : 18.0
malayan : 18.0
umbria : 18.0
eastern mediterranean or italian : 17.0
north netherlandish : 17.0
british or french : 17.0
sumatran : 17.0
meissen with german : 17.0
nevers : 17.0
spitalfields : 17.0
after german : 17.0
sceaux : 16.0
teotihuacan : 16.0
hittite : 16.0
chupicuaro : 16.0
thessaly : 16.0
quechua : 16.0
western european : 16.0
leuven : 15.0
qajar : 15.0
tiwanaku : 15.0
scythian : 15.0
furstenberg : 14.0
german or swiss : 14.0
aegean : 14.0
after russian original : 14.0
chelsea-derby : 14.0
mixtec : 14.0
alsace : 14.0
for french market : 14.0
northern european : 14.0
castel durante : 13.0
augsburg decoration : 13.0
canosan : 13.0
cyclades : 13.0
south german : 13.0
london original : 13.0
teano : 13.0
after british : 13.0
augsburg original : 12.0
muisca : 12.0
moustiers : 12.0
the hague : 12.0
central italian : 12.0
ansbach : 12.0
french or german : 12.0
brescia : 12.0
bologna : 11.0
canaanite : 11.0
lambeth : 11.0
potsdam : 11.0
villeroy : 11.0
catalonia : 11.0
orleans : 10.0
salinar : 10.0
colombian : 10.0
remojadas : 10.0
for swedish market : 10.0
guanacaste-nicoya : 10.0
burma : 10.0
moroccan : 10.0
macaracas : 10.0
brunswick : 10.0
manteno : 10.0
sulawesi : 10.0
bayreuth : 10.0
alexandria-hadra : 10.0
lille : 10.0
inuit : 9.0
italic-native : 9.0
roman egyptian : 9.0
praenestine : 9.0
kievan rus' : 9.0
rhenish : 9.0
pesaro : 9.0
bordeaux : 9.0
verona : 8.0
zenu : 8.0
chorrera : 8.0
naxos : 8.0
huastec : 8.0
hanau : 8.0
lowestoft : 8.0
wurzburg : 8.0
caughley : 8.0
thanjavur : 7.0
ubaid : 7.0
surrey : 7.0
chalcidian : 7.0
stockholm : 7.0
bavaria : 7.0
southall : 7.0
arabian : 7.0
tolita-tumaco : 7.0
mali : 7.0
czech : 7.0
european bronze age : 7.0
moro : 7.0
kathmandu valley : 7.0
edomite : 7.0
montelupo : 7.0
mimbres : 7.0
gnathian : 7.0
for danish market : 6.0
edinburgh : 6.0
ferrara : 6.0
macao : 6.0
euboean : 6.0
haida : 6.0
visigothic : 6.0
north indian : 6.0
west slavic : 6.0
savoy : 6.0
salzburg : 6.0
isin-larsa : 6.0
tlingit : 6.0
chinese with french mounts : 6.0
indian or nepalese : 6.0
parthian or sasanian : 6.0
eastern european : 5.0
arica : 5.0
provincial : 5.0
topara : 5.0
avon : 5.0
proto-elamite : 5.0
avignon : 5.0
chinese with dutch decoration : 5.0
langobardic : 5.0
liverpool : 5.0
northern india : 5.0
huron : 4.0
after german original : 4.0
gurkha : 4.0
hungary : 4.0
longton hall : 4.0
turin : 4.0
aragon : 4.0
piedmont : 4.0
flemish or italian : 4.0
faliscan : 4.0
coromandel coast : 4.0
neuwied am rhein : 4.0
sinceny : 4.0
babylonian or kassite : 4.0
ottonian : 4.0
michoacan : 4.0
parita : 4.0
phrygian : 4.0
deccan : 4.0
colonial : 4.0
urbino with gubbio luster : 3.0
after italian : 3.0
afghan : 3.0
united states : 3.0
italian or sicilian : 3.0
costa rica or panama : 3.0
balinese : 3.0
cypriot or phoenician : 3.0
la rochelle : 3.0
gonia : 3.0
for iberian market : 3.0
nailsea : 3.0
england : 3.0
kazakhstan : 3.0
beautiran : 3.0
smyrna : 3.0
british or scottish : 3.0
for russian market : 2.0
san sabastian : 2.0
isin-larsaold babylonian : 2.0
devonshire : 2.0
northwest china/eastern central asia : 2.0
central highlands : 2.0
konigsberg : 2.0
vulci : 2.0
moche-wari : 2.0
mennecy or sceaux : 1.0
zoroastrian : 1.0
kholmogory : 1.0
macedonian : 1.0
chinese with european decoration : 1.0
freiburg im breisgau : 1.0
algerian : 1.0
populonia : 1.0
skyros : 1.0
tsimshian : 1.0
dyak : 1.0
palermo : 1.0
dehua : 1.0
nimes : 1.0
In [8]:
df = pd.DataFrame({'Culture_label': culture_labels,'Culture_count': culture_counts})
df.to_csv('cutr_labe.csv',index=True)
In [9]:
for i in range(len(tag_labels)):
    print(tag_labels[i],':',tag_counts[i])
men : 19970.0
women : 14281.0
flowers : 8419.0
utilitarian objects : 6564.0
portraits : 5955.0
trees : 5591.0
leaves : 5259.0
inscriptions : 3890.0
birds : 3692.0
human figures : 3665.0
textile fragments : 3570.0
mythical creatures : 3005.0
profiles : 2552.0
animals : 2548.0
writing systems : 2327.0
clothing and accessories : 2180.0
books : 2097.0
landscapes : 2075.0
bowls : 2045.0
tools and equipment : 2001.0
horse riding : 1895.0
dishes : 1789.0
seals : 1744.0
bottles : 1685.0
buildings : 1667.0
vases : 1540.0
sculpture : 1526.0
christ : 1492.0
horses : 1480.0
bodies of water : 1472.0
actresses : 1457.0
houses : 1446.0
decorative elements : 1428.0
boats : 1414.0
heads : 1397.0
coat of arms : 1390.0
female nudes : 1286.0
cups : 1283.0
dogs : 1278.0
angels : 1260.0
architecture : 1213.0
lace : 1200.0
musical instruments : 1138.0
hieroglyphs : 1083.0
soldiers : 1073.0
saints : 1053.0
dresses : 1050.0
lions : 1016.0
swords : 977.0
girls : 965.0
weapons : 961.0
boys : 959.0
mountains : 957.0
pendants : 956.0
jewelry : 921.0
male nudes : 902.0
children : 901.0
architectural fragments : 888.0
christian imagery : 866.0
beads : 859.0
virgin mary : 816.0
documents : 810.0
textiles : 775.0
faces : 773.0
buddhism : 766.0
embroidery : 750.0
cross : 745.0
vase fragments : 744.0
scarabs : 682.0
actors : 676.0
columns : 672.0
madonna and child : 637.0
arches : 636.0
fans : 630.0
ships : 627.0
carriages : 622.0
working : 622.0
dragons : 613.0
flags : 600.0
ornament : 593.0
hats : 583.0
armors : 582.0
jugs : 582.0
fish : 570.0
samples : 568.0
kings : 566.0
amulets : 565.0
bridges : 564.0
insignia : 560.0
crowd : 555.0
earrings : 551.0
plants : 543.0
chairs : 540.0
rivers : 518.0
infants : 515.0
netsuke : 504.0
rings : 493.0
writing implements : 487.0
christianity : 481.0
deer : 480.0
ruins : 477.0
gods : 462.0
jesus : 461.0
tablets : 454.0
interiors : 453.0
cutlery : 446.0
design elements : 440.0
helmets : 433.0
cupid : 427.0
lamps : 422.0
satire : 422.0
satyrs : 413.0
fruit : 399.0
mirrors : 393.0
cuneiform : 387.0
shields : 382.0
arabic : 373.0
tables : 371.0
saucers : 369.0
goddess : 369.0
funerary objects : 358.0
beakers : 357.0
masks : 355.0
cartouches : 354.0
battles : 338.0
cows : 332.0
crucifixion : 332.0
saint john the baptist : 329.0
coins : 329.0
dancing : 327.0
churches : 327.0
arrowheads : 323.0
hills : 322.0
robes : 312.0
eagles : 303.0
sword guards : 303.0
buddha : 302.0
bracelets : 298.0
firearms : 297.0
death : 296.0
butterflies : 295.0
reading : 290.0
daggers : 289.0
insects : 286.0
bulls : 284.0
temples : 273.0
candlesticks : 273.0
costumes : 270.0
manuscripts : 269.0
ewers : 266.0
knives : 265.0
capitals : 263.0
snakes : 262.0
lighting : 262.0
shoes : 258.0
garlands : 257.0
greek figures : 257.0
hilts : 256.0
clouds : 256.0
boxes : 254.0
architectural elements : 254.0
spears : 253.0
bow and arrow : 253.0
windows : 251.0
teapots : 251.0
chariots : 244.0
cats : 243.0
diamonds : 240.0
necklaces : 239.0
elephants : 236.0
venus : 236.0
liturgical objects : 234.0
military equipment : 233.0
gardens : 230.0
hinduism : 229.0
weights and measures : 228.0
pins : 227.0
badges : 226.0
musicians : 225.0
monkeys : 224.0
putti : 223.0
hands : 221.0
bodhisattva : 221.0
trays : 220.0
athletes : 219.0
geometric patterns : 219.0
journals : 218.0
coptic : 216.0
sheep : 216.0
palmettes : 215.0
hercules : 208.0
suffering : 207.0
poetry : 206.0
carpets and rugs : 205.0
couples : 205.0
hunting : 205.0
goats : 204.0
pocket watches : 204.0
flutes : 203.0
grapes : 202.0
roses : 200.0
fountains : 196.0
undergarment : 195.0
music : 194.0
streets : 193.0
skeletons : 188.0
drinking glasses : 186.0
brooches : 186.0
cities : 185.0
roosters : 184.0
medallions : 182.0
coats : 181.0
seas : 181.0
tombs : 180.0
peacocks : 179.0
queens : 179.0
ducks : 177.0
footwear : 176.0
sleep : 174.0
snow : 173.0
donkeys : 170.0
roads : 170.0
apostles : 169.0
pediments : 167.0
games : 167.0
doors : 165.0
towers : 162.0
holy family : 160.0
emblems : 160.0
stairs : 160.0
shepherds : 159.0
writing : 158.0
gates : 156.0
smoking : 156.0
nymphs : 155.0
moon : 153.0
castles : 153.0
forests : 150.0
drinking : 150.0
clocks : 150.0
sphinx : 148.0
shells : 148.0
sadness : 147.0
rabbits : 147.0
lotuses : 147.0
dancers : 146.0
palaces : 144.0
vines : 143.0
waterfalls : 143.0
apollo : 142.0
playing cards : 141.0
axes : 140.0
playing : 139.0
cabinets : 137.0
skulls : 137.0
tents : 137.0
wreaths : 137.0
cranes : 135.0
friezes : 133.0
buckles : 131.0
mothers : 130.0
monuments : 130.0
rams : 129.0
incense burners : 128.0
cameos : 127.0
urns : 126.0
tigers : 124.0
horns : 124.0
demons : 124.0
drums : 124.0
fireplaces : 123.0
buttons : 123.0
chess : 121.0
griffins : 120.0
villages : 120.0
squares : 120.0
fishing : 120.0
jackets : 119.0
doorways : 119.0
saint peter : 119.0
domes : 118.0
camels : 117.0
altars : 115.0
family : 115.0
waves : 114.0
correspondence : 114.0
grotesques : 114.0
bamboo : 114.0
lovers : 113.0
saint paul : 113.0
violins : 113.0
eros : 112.0
jainism : 112.0
mary magdalene : 111.0
beds : 111.0
frogs : 111.0
vestments : 110.0
cannons : 110.0
purses : 110.0
facades : 108.0
pilasters : 107.0
painting : 106.0
annunciation : 106.0
boars : 106.0
swans : 104.0
bathing : 104.0
furniture : 104.0
jockeys : 103.0
lakes : 103.0
feet : 103.0
buildings and structures : 102.0
vests : 100.0
circles : 99.0
food : 99.0
taoism : 98.0
chinoiserie : 98.0
self-portraits : 97.0
scrolls : 97.0
centaurs : 97.0
serpents : 97.0
monks : 97.0
spectators : 96.0
saint jerome : 96.0
screens : 96.0
trumpets : 95.0
burials : 95.0
abstraction : 95.0
tapestries : 95.0
owls : 94.0
riding : 94.0
parks : 94.0
generals : 93.0
eve : 93.0
curtains : 92.0
watches : 92.0
chests : 92.0
princes : 92.0
adoration of the magi : 91.0
keys : 91.0
diana : 90.0
fire : 90.0
adam : 89.0
foxes : 88.0
jupiter : 88.0
obelisks : 88.0
saint john the evangelist : 87.0
falcons : 87.0
feathers : 87.0
chickens : 86.0
nativity : 86.0
bacchus : 86.0
zigzag pattern : 85.0
harps : 85.0
turtles : 85.0
corsets : 85.0
coffeepots : 84.0
sun : 83.0
stripes : 81.0
saint catherine : 81.0
baseball : 81.0
candelabra : 81.0
pitchers : 80.0
peonies : 80.0
canals : 80.0
maps : 79.0
saint joseph : 79.0
theatre : 79.0
mythology : 79.0
bishops : 79.0
parrots : 79.0
bears : 79.0
decorative designs : 78.0
walking : 78.0
night : 78.0
reliquaries : 77.0
percussion instruments : 77.0
balconies : 77.0
bats : 76.0
mercury : 76.0
daily life : 75.0
basins : 75.0
monsters : 74.0
goblets : 73.0
boots : 72.0
winter : 72.0
docks : 71.0
adoration of the sheperds : 71.0
mice : 70.0
caryatids : 70.0
censers : 70.0
dolphins : 69.0
neptune : 69.0
horus : 69.0
gloves : 68.0
suits : 68.0
strapwork : 68.0
beaches : 68.0
lutes : 67.0
corpses : 67.0
seating furniture : 67.0
eyes : 67.0
pianos : 67.0
still life : 67.0
towns : 66.0
pigs : 66.0
punishment : 66.0
guitars : 66.0
tunics : 66.0
athena : 66.0
army : 66.0
psyche : 66.0
servants : 65.0
seascapes : 65.0
popes : 64.0
tea caddy : 64.0
ladders : 64.0
rain : 64.0
dionysus : 63.0
arrows : 63.0
george washington : 63.0
cornucopia : 62.0
moses : 62.0
worshiping : 62.0
windmills : 62.0
dining : 61.0
scarves : 61.0
coffins : 61.0
krishna : 60.0
sky : 60.0
paisley : 59.0
stars : 59.0
triangles : 59.0
poets : 59.0
globes : 59.0
david : 58.0
princesses : 58.0
alexander the great : 58.0
farms : 58.0
diadems : 58.0
avalokiteshvara : 58.0
prisoners : 58.0
love : 57.0
fireworks : 57.0
trophies : 57.0
crescents : 57.0
hexagons : 57.0
transportation : 57.0
civil war : 56.0
mars : 56.0
railways : 56.0
dance : 56.0
military : 56.0
storage furniture : 55.0
tureens : 55.0
greek deities : 55.0
saint francis : 54.0
crocodiles : 54.0
fortification : 53.0
markets : 53.0
vishnu : 53.0
aphrodite : 53.0
evening : 52.0
desks : 52.0
candles : 52.0
stools : 52.0
wars : 52.0
qur'an : 52.0
devil : 51.0
shirts : 51.0
shiva : 51.0
doves : 51.0
fear : 51.0
saint anne : 51.0
mosques : 51.0
pheasants : 51.0
entombment : 50.0
storms : 50.0
couches : 50.0
isis : 50.0
uniforms : 49.0
lambs : 49.0
party : 49.0
hammers : 49.0
abraham : 48.0
trains : 48.0
chalices : 48.0
vegetables : 48.0
wells : 48.0
apocalypse : 48.0
fluting : 48.0
sarcophagus : 48.0
maenads : 48.0
hair : 47.0
minerva : 47.0
juno : 47.0
autumn : 47.0
bedrooms : 47.0
crabs : 47.0
courtyards : 46.0
performance : 46.0
leopards : 46.0
last supper : 46.0
contemplation : 45.0
pants : 45.0
triton : 45.0
muses : 45.0
spring : 45.0
judith : 44.0
funerals : 44.0
bes : 43.0
ladles : 43.0
taweret : 42.0
prisons : 42.0
saint george : 41.0
acanthus : 41.0
bagpipes : 41.0
apples : 41.0
belts : 41.0
shakespeare : 41.0
lamentation : 40.0
military clothing : 40.0
volcanoes : 40.0
body parts : 40.0
commodes : 39.0
saint matthew : 39.0
coverlets and quilts : 39.0
egg and dart : 39.0
saint michael : 38.0
landforms : 38.0
squirrels : 38.0
gadrooning : 38.0
caves : 37.0
roman deities : 37.0
nonrepresentational art : 37.0
illness : 37.0
doctors : 36.0
air transports : 36.0
louis xiv : 36.0
saint anthony : 36.0
sibyl : 36.0
historical figures : 36.0
silenus : 36.0
anklet : 36.0
skirts : 36.0
farmers : 35.0
ceremony : 35.0
artists : 35.0
hermes : 35.0
archangel gabriel : 35.0
hathor : 34.0
assumption of the virgin : 34.0
julius caesar : 34.0
last judgement : 34.0
violas : 34.0
vulcan : 34.0
fauns : 34.0
bicycles : 34.0
watermills : 33.0
lizards : 32.0
lobsters : 32.0
nike : 32.0
chinese : 31.0
adonis : 31.0
zodiac : 31.0
pomegranates : 31.0
factories : 31.0
holofernes : 30.0
zeus : 30.0
calendars : 30.0
snails : 30.0
ceres : 30.0
ponds : 30.0
scorpions : 30.0
buffalos : 29.0
sports : 29.0
summer : 29.0
prisms : 29.0
anger : 28.0
schools : 28.0
drunkenness : 28.0
buddhist religious figures : 28.0
toys : 28.0
dolls : 28.0
perseus : 27.0
hawks : 27.0
circus : 27.0
navy : 27.0
napoleon i : 27.0
dice : 27.0
benjamin franklin : 26.0
sundials : 26.0
benches : 26.0
emperor augustus : 26.0
sailors : 26.0
artemis : 26.0
jars : 26.0
fathers : 26.0
kettles : 25.0
bees : 25.0
orpheus : 25.0
washing : 25.0
burial grounds : 25.0
baptism of christ : 24.0
peaches : 24.0
deserts : 24.0
drawing : 24.0
cleopatra : 24.0
massacres : 24.0
manjushri : 24.0
mandolins : 24.0
street scene : 23.0
gardeners : 23.0
merchants : 23.0
inns : 22.0
victory : 22.0
abbies : 22.0
acorns : 22.0
pyramids : 22.0
singers : 22.0
literature : 22.0
pigeons : 22.0
genre scene : 22.0
necktie : 22.0
barns : 21.0
descent from the cross : 21.0
organs : 21.0
durga : 21.0
teachers : 21.0
ancient greek : 21.0
students : 21.0
rosaries : 20.0
saint lawrence : 20.0
occupations : 20.0
tea drinking : 20.0
leda : 20.0
kitchens : 20.0
hospitals : 20.0
amazons : 19.0
amun : 19.0
acrobats : 19.0
ariadne : 19.0
octagons : 19.0
daisies : 19.0
shakyamuni : 18.0
bobbins : 18.0
admirals : 18.0
galatea : 18.0
saint mark : 18.0
lockets : 17.0
singing : 17.0
wine : 17.0
cauldrons : 17.0
tabernacles : 17.0
europa : 17.0
cradles : 16.0
boxing : 16.0
wind : 16.0
maitreya : 16.0
opera : 16.0
rowing : 15.0
wagons : 14.0
dawn : 14.0
octopus : 14.0
astronomy : 14.0
tulips : 13.0
tricorns : 13.0
world war i : 12.0
law : 12.0
religious events : 12.0
gingham pattern : 12.0
poseidon : 11.0
bible : 11.0
telescopes : 11.0
hell : 10.0
jason : 10.0
religious texts : 10.0
bakers : 9.0
magicians : 9.0
billiards : 9.0
old testament : 9.0
cathedrals : 9.0
esther : 9.0
deities : 8.0
concerts : 8.0
bathsheba : 8.0
fairies : 8.0
medea : 8.0
easter : 7.0
polka-dot pattern : 7.0
new testament : 7.0
rectangles : 7.0
christmas : 7.0
celestial bodies : 6.0
nero : 6.0
pinecones : 6.0
architects : 5.0
vajrapani : 5.0
pentecost : 5.0
living rooms : 4.0
olive trees : 4.0
hindu religious figures : 3.0
sunflowers : 3.0
slavery : 2.0
prostitutes : 2.0
mark antony : 1.0
In [10]:
df = pd.DataFrame({'Tags_label': tag_labels,'Tags_count': tag_counts})
df.to_csv('tags_label.csv',index=True)
In [11]:
plt.figure(figsize=(20,15))

plt.subplot(1,2,1)
ax1 = sns.barplot(y=culture_labels[:20], x=culture_counts[:20], orient="h")
plt.title('Label Counts by Culture (Top 20)',fontsize=15)
plt.xlim((0, max(culture_counts)*1.15))
plt.yticks(fontsize=15)

for p in ax1.patches:
    ax1.annotate(f'{int(p.get_width())}\n{p.get_width() * 100 / df_train.shape[0]:.2f}%',
                (p.get_width(), p.get_y() + p.get_height() / 2.), 
                ha='left', 
                va='center', 
                fontsize=12, 
                color='black',
                xytext=(7,0), 
                textcoords='offset points')

plt.subplot(1,2,2)    
ax2 = sns.barplot(y=tag_labels[:20], x=tag_counts[:20], orient="h")
plt.title('Label Counts by Tag (Top 20)',fontsize=15)
plt.xlim((0, max(tag_counts)*1.15))
plt.yticks(fontsize=15)

for p in ax2.patches:
    ax2.annotate(f'{int(p.get_width())}\n{p.get_width() * 100 / df_train.shape[0]:.2f}%',
                (p.get_width(), p.get_y() + p.get_height() / 2.), 
                ha='left', 
                va='center', 
                fontsize=12, 
                color='black',
                xytext=(7,0), 
                textcoords='offset points')

plt.tight_layout()
plt.show()
In [12]:
plt.figure(figsize=(20,8))

ax = sns.countplot(num_labels)
plt.xlabel('Number of Labels')
plt.title('Number of Labels per Image', fontsize=20)

for p in ax.patches:
    ax.annotate(f'{p.get_height() * 100 / df_train.shape[0]:.3f}%',
            (p.get_x() + p.get_width() / 2., p.get_height()), 
            ha='center', 
            va='center', 
            fontsize=11, 
            color='black',
            xytext=(0,7), 
            textcoords='offset points')
In [13]:
train_attr_ohot = np.zeros((len(df_train), len(label_df)), dtype=int)

for idx, attr_arr in enumerate(df_train.attribute_ids.str.split(" ").apply(lambda l: list(map(int, l))).values):
    train_attr_ohot[idx, attr_arr] = 1
In [14]:
names_arr = label_df.attribute_name.values
df_train["attribute_names"] = [", ".join(names_arr[arr == 1]) for arr in train_attr_ohot]
In [15]:
df_train["attr_num"] = train_attr_ohot.sum(axis=1)
df_train["culture_attr_num"] = train_attr_ohot[:, :398].sum(axis=1)
df_train["tag_attr_num"] = train_attr_ohot[:, 398:].sum(axis=1)
In [16]:
df_train.head()
Out[16]:
id attribute_ids attribute_names attr_num culture_attr_num tag_attr_num
0 1000483014d91860 147 616 813 culture::french, tag::dogs, tag::men 3 1 2
1 1000fe2e667721fe 51 616 734 813 culture::british, tag::dogs, tag::horses, tag:... 4 1 3
2 1001614cb89646ee 776 tag::landscapes 1 0 1
3 10041eb49b297c08 51 671 698 813 1092 culture::british, tag::flowers, tag::girls, ta... 5 1 4
4 100501c227f8beea 13 404 492 903 1093 culture::american, tag::actors, tag::boys, tag... 5 1 4
In [17]:
#for i in range(len(df_train["attribute_names"])):
#    print(df_train["attribute_names"][i],':',df_train["culture_attr_num"][i])
In [18]:
fig = plt.figure(figsize=(15, 10))
fig.subplots_adjust(hspace=0.4)
ax2 = fig.add_subplot(3,1,2,)
sns.countplot(df_train.culture_attr_num, ax=ax2)
ax2.set_title("number of 'culture' attributes each art has")
for p in ax2.patches:
    ax2.annotate(f'{p.get_height() * 100 / df_train.shape[0]:.3f}%',
            (p.get_x() + p.get_width() / 2., p.get_height()), 
            ha='center', 
            va='center', 
            fontsize=11, 
            color='black',
            xytext=(0,7), 
            textcoords='offset points')
ax3 = fig.add_subplot(3,1,3,)
ax3.set_title("number of 'tag' attributes each art has")
sns.countplot(df_train.tag_attr_num, ax=ax3)
for p in ax3.patches:
    ax3.annotate(f'{p.get_height() * 100 / df_train.shape[0]:.3f}%',
            (p.get_x() + p.get_width() / 2., p.get_height()), 
            ha='center', 
            va='center', 
            fontsize=11, 
            color='black',
            xytext=(0,7), 
            textcoords='offset points')

EDA by Visualize Images

Example of images with tags

In [19]:
from cv2 import cv2
i = 1
df_train["attribute_ids"]=df_train["attribute_ids"].apply(lambda x:x.split(" "))
df_train["id"]=df_train["id"].apply(lambda x:x+".png")
plt.figure(figsize=[30,30])
for img_name in os.listdir("../input/imet-2019-fgvc6/train/")[5:10]:   
    img = cv2.imread("../input/imet-2019-fgvc6/train/%s" % img_name)[...,[2, 1, 0]]
    plt.subplot(5, 1, i)
    plt.imshow(img)
    ids = df_train[df_train["id"] == img_name]["attribute_ids"]
    print(ids)
    title_val = []
    for tag_id in ids.values[0]:
        att_name = label_df[label_df['attribute_id'].astype(str) == tag_id]['attribute_name'].values[0]
        title_val.append(att_name)
    plt.title(title_val)
    i += 1
    
plt.show()
57105    [147, 420, 813]
Name: attribute_ids, dtype: object
43228    [259, 663, 800, 1046]
Name: attribute_ids, dtype: object
6651    [147, 626]
Name: attribute_ids, dtype: object
67679    [305, 415]
Name: attribute_ids, dtype: object
34529    [147, 485, 738]
Name: attribute_ids, dtype: object

Check duplicated images

In [20]:
import os
import numpy as np
from PIL import Image
import pandas as pd
import hashlib
In [21]:
def check_md5(fname):
    hash_md5 = hashlib.md5()
    with open(fname, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()
In [22]:
file_names = []
path_root = '../input/imet-2019-fgvc6/train/'
for filename in os.listdir(path_root)[0:20]:
    file_names.append(check_md5(path_root+filename))
print(len(file_names))
20
In [23]:
unit = np.unique(file_names,return_counts=True)
count = 0
for i in range(len(unit[1])):
    if unit[1][i]>1:
        count += 1
        print('Duplicated Images')
if count == 0:
    print('NOT Duplicated Images')
NOT Duplicated Images

Padding image

In [24]:
def padding_image(path_img):
    image_old = Image.open(path_img)
    width, height = image_old.size

    if width > height:
        distance_max = width
        array = np.zeros([distance_max, distance_max, 3], dtype=np.uint8)
        array.fill(0)
        image_new = Image.fromarray(array)

        xmin = 0
        ymin = int((distance_max / 2) - (height / 2))
        xmax = distance_max
        ymax = int((distance_max / 2) + (height / 2))

        image_new.paste(image_old, (xmin, ymin, xmax, ymax))
        return image_new

    elif width < height:
        distance_max = height
        array = np.zeros([distance_max, distance_max, 3], dtype=np.uint8)
        array.fill(0)
        image_new = Image.fromarray(array)

        xmin = int((distance_max / 2) - (width / 2))
        ymin = 0
        xmax = int((distance_max / 2) + (width / 2))
        ymax = distance_max

        image_new.paste(image_old, (xmin, ymin, xmax, ymax))
        return image_new

    else:
        return image_old
In [25]:
import random
random_filenames = random.choices(os.listdir(path_root), k=5)
for filename in random_filenames:
    plt.imshow(np.array(Image.open(path_root+filename)))
    plt.figure()
    plt.imshow(padding_image(path_root+filename))
    plt.figure()
<Figure size 432x288 with 0 Axes>
In [26]:
import fastai
from fastai.vision import *
fastai.__version__
Out[26]:
'1.0.51'

Setup

In [27]:
BATCH  = 126
SIZE   = 250
path = Path('../input/imet-2019-fgvc6/') # iMet data path
In [28]:
!ls ../input/resnet50/
resnet50.pth
In [29]:
# Making pretrained weights work without needing to find the default filename
from torch.utils import model_zoo
Path('models').mkdir(exist_ok=True)
!cp '../input/resnet50/resnet50.pth' 'models/'
def load_url(*args, **kwargs):
    model_dir = Path('models')
    filename  = 'resnet50.pth'
    if not (model_dir/filename).is_file(): raise FileNotFoundError
    return torch.load(model_dir/filename)
model_zoo.load_url = load_url

Data

In [30]:
# Load train dataframe
train_df = pd.read_csv(path/'train.csv')
train_df.head()
Out[30]:
id attribute_ids
0 1000483014d91860 147 616 813
1 1000fe2e667721fe 51 616 734 813
2 1001614cb89646ee 776
3 10041eb49b297c08 51 671 698 813 1092
4 100501c227f8beea 13 404 492 903 1093
In [31]:
# Load labels dataframe
labels_df = pd.read_csv(path/'labels.csv')
labels_df.head()
Out[31]:
attribute_id attribute_name
0 0 culture::abruzzi
1 1 culture::achaemenid
2 2 culture::aegean
3 3 culture::afghan
4 4 culture::after british
In [32]:
# Load sample submission
test_df = pd.read_csv(path/'sample_submission.csv')
test_df.head()
Out[32]:
id attribute_ids
0 10023b2cc4ed5f68 0 1 2
1 100fbe75ed8fd887 0 1 2
2 101b627524a04f19 0 1 2
3 10234480c41284c6 0 1 2
4 1023b0e2636dcea8 0 1 2

Create data object using datablock API

In [33]:
tfms = get_transforms(do_flip=True, flip_vert=False, max_rotate=0.10, max_zoom=1.5, max_warp=0.2, max_lighting=0.2,
                     xtra_tfms=[(symmetric_warp(magnitude=(-0,0), p=0)),])
In [34]:
train, test = [ImageList.from_df(df, path=path, cols='id', folder=folder, suffix='.png') 
               for df, folder in zip([train_df, test_df], ['train', 'test'])]
data = (train.split_by_rand_pct(0.05, seed=42)
        .label_from_df(cols='attribute_ids', label_delim=' ')
        .add_test(test)
        .transform(tfms, size=SIZE, resize_method=ResizeMethod.PAD, padding_mode='border',)
        .databunch(path=Path('.'), bs=BATCH).normalize(imagenet_stats))
In [35]:
data
Out[35]:
ImageDataBunch;

Train: LabelList (103776 items)
x: ImageList
Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250)
y: MultiCategoryList
147;616;813,51;616;734;813,776,51;671;698;813;1092,13;404;492;903;1093
Path: ../input/imet-2019-fgvc6;

Valid: LabelList (5461 items)
x: ImageList
Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250)
y: MultiCategoryList
872,147;542;733;813;1092,51;393;584;671;746;784;954,13;813;896,498;637;704
Path: ../input/imet-2019-fgvc6;

Test: LabelList (7443 items)
x: ImageList
Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250)
y: EmptyLabelList
,,,,
Path: ../input/imet-2019-fgvc6

Create learner with pretrenet model and FocalLoss

For problems with high class imbalance Focal Loss is usually a better choice than the usual Cross Entropy Loss.

In [36]:
# Source: https://www.kaggle.com/c/human-protein-atlas-image-classification/discussion/78109
class FocalLoss(nn.Module):
    def __init__(self, gamma=2):
        super().__init__()
        self.gamma = gamma

    def forward(self, logit, target):
        target = target.float()
        max_val = (-logit).clamp(min=0)
        loss = logit - logit * target + max_val + \
               ((-max_val).exp() + (-logit - max_val).exp()).log()

        invprobs = F.logsigmoid(-logit * (target * 2.0 - 1.0))
        loss = (invprobs * self.gamma).exp() * loss
        if len(loss.size())==2:
            loss = loss.sum(dim=1)
        return loss.mean()
In [37]:
learn = cnn_learner(data, base_arch=models.resnet50, loss_func=FocalLoss(), metrics=fbeta)
In [38]:
ls ../input
imet-2019-fgvc6/  models/  models2/  resnet50/
In [39]:
!cp '../input/models2/stage-1.pth' 'models/'
In [40]:
def find_best_fixed_threshold(preds, targs, do_plot=True):
    score = []
    thrs = np.arange(0, 0.5, 0.01)
    for thr in progress_bar(thrs):
        score.append(fbeta(valid_preds[0],valid_preds[1], thresh=thr))
    score = np.array(score)
    pm = score.argmax()
    best_thr, best_score = thrs[pm], score[pm].item()
    print(f'thr={best_thr:.3f}', f'F2={best_score:.3f}')
    if do_plot:
        plt.plot(thrs, score)
        plt.vlines(x=best_thr, ymin=score.min(), ymax=score.max())
        plt.text(best_thr+0.03, best_score-0.01, f'$F_{2}=${best_score:.3f}', fontsize=14);
        plt.show()
    return best_thr

i2c = np.array([[i, c] for c, i in learn.data.train_ds.y.c2i.items()]).astype(int) # indices to class number correspondence

def join_preds(preds, thr):
    return [' '.join(i2c[np.where(t==1)[0],1].astype(str)) for t in (preds[0].sigmoid()>thr).long()]
In [41]:
learn.load('stage-1')
/opt/conda/lib/python3.6/site-packages/torch/serialization.py:251: UserWarning: Couldn't retrieve source code for container of type FocalLoss. It won't be checked for correctness upon loading.
  "type " + obj.__name__ + ". It won't be checked "
Out[41]:
Learner(data=ImageDataBunch;

Train: LabelList (103776 items)
x: ImageList
Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250)
y: MultiCategoryList
147;616;813,51;616;734;813,776,51;671;698;813;1092,13;404;492;903;1093
Path: ../input/imet-2019-fgvc6;

Valid: LabelList (5461 items)
x: ImageList
Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250)
y: MultiCategoryList
872,147;542;733;813;1092,51;393;584;671;746;784;954,13;813;896,498;637;704
Path: ../input/imet-2019-fgvc6;

Test: LabelList (7443 items)
x: ImageList
Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250),Image (3, 250, 250)
y: EmptyLabelList
,,,,
Path: ../input/imet-2019-fgvc6, model=Sequential(
  (0): Sequential(
    (0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
    (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (2): ReLU(inplace)
    (3): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
    (4): Sequential(
      (0): Bottleneck(
        (conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
        (downsample): Sequential(
          (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
          (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (1): Bottleneck(
        (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
      (2): Bottleneck(
        (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
    )
    (5): Sequential(
      (0): Bottleneck(
        (conv1): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
        (downsample): Sequential(
          (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
          (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (1): Bottleneck(
        (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
      (2): Bottleneck(
        (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
      (3): Bottleneck(
        (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
    )
    (6): Sequential(
      (0): Bottleneck(
        (conv1): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
        (downsample): Sequential(
          (0): Conv2d(512, 1024, kernel_size=(1, 1), stride=(2, 2), bias=False)
          (1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (1): Bottleneck(
        (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
      (2): Bottleneck(
        (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
      (3): Bottleneck(
        (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
      (4): Bottleneck(
        (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
      (5): Bottleneck(
        (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
    )
    (7): Sequential(
      (0): Bottleneck(
        (conv1): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
        (downsample): Sequential(
          (0): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(2, 2), bias=False)
          (1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        )
      )
      (1): Bottleneck(
        (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
      (2): Bottleneck(
        (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
        (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
        (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (relu): ReLU(inplace)
      )
    )
  )
  (1): Sequential(
    (0): AdaptiveConcatPool2d(
      (ap): AdaptiveAvgPool2d(output_size=1)
      (mp): AdaptiveMaxPool2d(output_size=1)
    )
    (1): Flatten()
    (2): BatchNorm1d(4096, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (3): Dropout(p=0.25)
    (4): Linear(in_features=4096, out_features=512, bias=True)
    (5): ReLU(inplace)
    (6): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (7): Dropout(p=0.5)
    (8): Linear(in_features=512, out_features=1103, bias=True)
  )
), opt_func=functools.partial(<class 'torch.optim.adam.Adam'>, betas=(0.9, 0.99)), loss_func=FocalLoss(), metrics=[<function fbeta at 0x7fc03fbef950>], true_wd=True, bn_wd=True, wd=0.01, train_bn=True, path=PosixPath('.'), model_dir='models', callback_fns=[functools.partial(<class 'fastai.basic_train.Recorder'>, add_time=True)], callbacks=[], layer_groups=[Sequential(
  (0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (2): ReLU(inplace)
  (3): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (4): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (5): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (6): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (7): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (8): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (9): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (10): ReLU(inplace)
  (11): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (12): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (13): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (14): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (15): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (16): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (17): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (18): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (19): ReLU(inplace)
  (20): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (21): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (22): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (23): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (24): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (25): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (26): ReLU(inplace)
  (27): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (28): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (29): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
  (30): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (31): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (32): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (33): ReLU(inplace)
  (34): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
  (35): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (36): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (37): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (38): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (39): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (40): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (41): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (42): ReLU(inplace)
  (43): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (44): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (45): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (46): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (47): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (48): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (49): ReLU(inplace)
  (50): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (51): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (52): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (53): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (54): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (55): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (56): ReLU(inplace)
), Sequential(
  (0): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (2): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
  (3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (4): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (5): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (6): ReLU(inplace)
  (7): Conv2d(512, 1024, kernel_size=(1, 1), stride=(2, 2), bias=False)
  (8): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (9): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (10): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (11): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (12): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (13): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (14): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (15): ReLU(inplace)
  (16): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (17): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (18): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (19): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (20): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (21): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (22): ReLU(inplace)
  (23): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (24): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (25): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (26): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (27): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (28): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (29): ReLU(inplace)
  (30): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (31): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (32): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (33): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (34): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (35): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (36): ReLU(inplace)
  (37): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (38): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (39): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (40): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (41): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (42): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (43): ReLU(inplace)
  (44): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (45): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (46): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
  (47): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (48): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (49): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (50): ReLU(inplace)
  (51): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(2, 2), bias=False)
  (52): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (53): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (54): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (55): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (56): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (57): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (58): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (59): ReLU(inplace)
  (60): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (61): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (62): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
  (63): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (64): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)
  (65): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (66): ReLU(inplace)
), Sequential(
  (0): AdaptiveAvgPool2d(output_size=1)
  (1): AdaptiveMaxPool2d(output_size=1)
  (2): Flatten()
  (3): BatchNorm1d(4096, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (4): Dropout(p=0.25)
  (5): Linear(in_features=4096, out_features=512, bias=True)
  (6): ReLU(inplace)
  (7): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (8): Dropout(p=0.5)
  (9): Linear(in_features=512, out_features=1103, bias=True)
)], add_time=True)
In [42]:
# Validation predictions
valid_preds = learn.get_preds(DatasetType.Valid)
best_thr = find_best_fixed_threshold(*valid_preds)
100.00% [50/50 00:03<00:00]
thr=0.300 F2=0.597

Train the model

In [43]:
# Find a good learning rate
learn.lr_find()
learn.recorder.plot()
LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.
In [44]:
learn.unfreeze()
learn.fit_one_cycle(16, slice(1e-4,1e-3))
learn.freeze()
learn.save('stage-2', return_path=True)
25.00% [4/16 1:32:58<4:38:56]
epoch train_loss valid_loss fbeta time
0 2.064818 2.478988 0.533298 23:14
1 2.137841 2.506469 0.518565 23:09
2 2.236237 2.577312 0.516406 23:13
3 2.323974 2.592269 0.510388 23:21

82.62% [680/823 18:23<03:52 2.3346]
In [45]:
# Validation predictions
valid_preds = learn.get_preds(DatasetType.Valid)
best_thr = find_best_fixed_threshold(*valid_preds)
100.00% [50/50 00:03<00:00]
thr=0.300 F2=0.601
In [46]:
learn.recorder.plot()
learn.recorder.plot_losses()
learn.recorder.plot_metrics()
In [47]:
learn.export()
/opt/conda/lib/python3.6/site-packages/torch/serialization.py:251: UserWarning: Couldn't retrieve source code for container of type FocalLoss. It won't be checked for correctness upon loading.
  "type " + obj.__name__ + ". It won't be checked "

Get predictions

In [48]:
# Test predictions
#test_preds = learn.get_preds(DatasetType.Test)
#test_df.attribute_ids = join_preds(test_preds, best_thr)
#test_df.head()
In [49]:
#test_df.to_csv('submission.csv', index=False)

TTA

In [50]:
# Validation predictions with TTA
#valid_preds = learn.TTA(ds_type=DatasetType.Valid)
#best_thr = find_best_fixed_threshold(*valid_preds)
In [51]:
# Test predictions with TTA
test_preds = learn.TTA(ds_type=DatasetType.Test)
test_df.attribute_ids = join_preds(test_preds, best_thr)
test_df.head()
Out[51]:
id attribute_ids
0 10023b2cc4ed5f68 1059 195 223 369 766
1 100fbe75ed8fd887 1039 872 93
2 101b627524a04f19 420 624 784 79
3 10234480c41284c6 1046 147 480 483 725 738 776 830 923
4 1023b0e2636dcea8 1046 1092 147 283 322 477 584 738 813 954
In [52]:
test_df.to_csv('submission.csv', index=False) 
In [53]:
# Find a good learning rate
learn.lr_find()
learn.recorder.plot()
LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.