Spaces:
Sleeping
Sleeping
Upload 15 files
Browse files- Flickr8k.token.txt +0 -0
- Flickr_8k.testImages.txt +1000 -0
- Flickr_8k.trainImages.txt +0 -0
- Img-captioning-project.ipynb +869 -0
- README.md +33 -12
- captions.txt +0 -0
- descriptions.txt +0 -0
- descriptions1.txt +0 -0
- features.pkl +3 -0
- img_captioning_project.ipynb +1224 -0
- img_captioning_project.py +581 -0
- model_18.h5 +3 -0
- requirements.txt +13 -0
- streamlit.py +113 -0
- tokenizer1.pkl +3 -0
Flickr8k.token.txt
ADDED
The diff for this file is too large to render.
See raw diff
|
|
Flickr_8k.testImages.txt
ADDED
@@ -0,0 +1,1000 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
3385593926_d3e9c21170.jpg
|
2 |
+
2677656448_6b7e7702af.jpg
|
3 |
+
311146855_0b65fdb169.jpg
|
4 |
+
1258913059_07c613f7ff.jpg
|
5 |
+
241347760_d44c8d3a01.jpg
|
6 |
+
2654514044_a70a6e2c21.jpg
|
7 |
+
2339106348_2df90aa6a9.jpg
|
8 |
+
256085101_2c2617c5d0.jpg
|
9 |
+
280706862_14c30d734a.jpg
|
10 |
+
3072172967_630e9c69d0.jpg
|
11 |
+
3482062809_3b694322c4.jpg
|
12 |
+
1167669558_87a8a467d6.jpg
|
13 |
+
2847615962_c330bded6e.jpg
|
14 |
+
3344233740_c010378da7.jpg
|
15 |
+
2435685480_a79d42e564.jpg
|
16 |
+
3110649716_c17e14670e.jpg
|
17 |
+
2511019188_ca71775f2d.jpg
|
18 |
+
2521770311_3086ca90de.jpg
|
19 |
+
2723477522_d89f5ac62b.jpg
|
20 |
+
2218609886_892dcd6915.jpg
|
21 |
+
3745451546_fc8ec70cbd.jpg
|
22 |
+
2844018783_524b08e5aa.jpg
|
23 |
+
3100251515_c68027cc22.jpg
|
24 |
+
2207244634_1db1a1890b.jpg
|
25 |
+
2943023421_e297f05e11.jpg
|
26 |
+
3286822339_5535af6b93.jpg
|
27 |
+
2479652566_8f9fac8af5.jpg
|
28 |
+
1394368714_3bc7c19969.jpg
|
29 |
+
872622575_ba1d3632cc.jpg
|
30 |
+
2309860995_c2e2a0feeb.jpg
|
31 |
+
241347204_007d83e252.jpg
|
32 |
+
3502343542_f9b46688e5.jpg
|
33 |
+
757332692_6866ae545c.jpg
|
34 |
+
2748729903_3c7c920c4d.jpg
|
35 |
+
494792770_2c5f767ac0.jpg
|
36 |
+
3213992947_3f3f967a9f.jpg
|
37 |
+
2295750198_6d152d7ceb.jpg
|
38 |
+
2358898017_24496b80e8.jpg
|
39 |
+
3222055946_45f7293bb2.jpg
|
40 |
+
444481722_690d0cadcf.jpg
|
41 |
+
2647049174_0fb47cee2e.jpg
|
42 |
+
1174629344_a2e1a2bdbf.jpg
|
43 |
+
2921094201_2ed70a7963.jpg
|
44 |
+
2553550034_5901aa9d6c.jpg
|
45 |
+
3045613316_4e88862836.jpg
|
46 |
+
2706766641_a9df81969d.jpg
|
47 |
+
510531976_90bbee22a2.jpg
|
48 |
+
485245061_5a5de43e20.jpg
|
49 |
+
3070011270_390e597783.jpg
|
50 |
+
1352410176_af6b139734.jpg
|
51 |
+
1131932671_c8d17751b3.jpg
|
52 |
+
3155451946_c0862c70cb.jpg
|
53 |
+
2762301555_48a0d0aa24.jpg
|
54 |
+
3442242092_e579538d82.jpg
|
55 |
+
2415803492_56a673dc25.jpg
|
56 |
+
2884301336_dc8e974431.jpg
|
57 |
+
3453259666_9ecaa8bb4b.jpg
|
58 |
+
3016606751_0e8be20abd.jpg
|
59 |
+
3642220260_3aa8a52670.jpg
|
60 |
+
2612488996_9450de0e54.jpg
|
61 |
+
1499581619_a5f65a882c.jpg
|
62 |
+
1427391496_ea512cbe7f.jpg
|
63 |
+
3601843201_4809e66909.jpg
|
64 |
+
3584561689_b6eb24dd70.jpg
|
65 |
+
138718600_f430ebca17.jpg
|
66 |
+
3220126881_b0a4f7cccb.jpg
|
67 |
+
300314926_0b2e4b64f5.jpg
|
68 |
+
3128164023_ebe8da4c32.jpg
|
69 |
+
324208502_674488bcea.jpg
|
70 |
+
3647750811_395fbd397e.jpg
|
71 |
+
3458211052_bb73084398.jpg
|
72 |
+
2414397449_2ac3b78e0d.jpg
|
73 |
+
3085226474_62aba51179.jpg
|
74 |
+
968081289_cdba83ce2e.jpg
|
75 |
+
2436081047_bca044c1d3.jpg
|
76 |
+
2813992915_f732cf8539.jpg
|
77 |
+
3627011534_485f667b10.jpg
|
78 |
+
3214237686_6566b8b52f.jpg
|
79 |
+
1248940539_46d33ed487.jpg
|
80 |
+
2064790732_219e52e19c.jpg
|
81 |
+
544576742_283b65fa0d.jpg
|
82 |
+
2731171552_4a808c7d5a.jpg
|
83 |
+
3609032038_005c789f64.jpg
|
84 |
+
3119875880_22f9129a1c.jpg
|
85 |
+
3339140382_2e49bc324a.jpg
|
86 |
+
2712787899_d85048eb6a.jpg
|
87 |
+
3655155990_b0e201dd3c.jpg
|
88 |
+
3325497914_f9014d615b.jpg
|
89 |
+
468310111_d9396abcbd.jpg
|
90 |
+
747921928_48eb02aab2.jpg
|
91 |
+
3639967449_137f48b43d.jpg
|
92 |
+
2374652725_32f90fa15c.jpg
|
93 |
+
3363750526_efcedc47a9.jpg
|
94 |
+
2689001252_e0016c89f0.jpg
|
95 |
+
3154641421_d1b9b8c24c.jpg
|
96 |
+
2631300484_be8621d17b.jpg
|
97 |
+
3677318686_b018862bb7.jpg
|
98 |
+
405615014_03be7ef618.jpg
|
99 |
+
533979933_a95b03323b.jpg
|
100 |
+
3437654963_c4fdc17e8b.jpg
|
101 |
+
3462454965_a481809cea.jpg
|
102 |
+
2256133102_e2c8314ecb.jpg
|
103 |
+
3186412658_2ab2ebd397.jpg
|
104 |
+
3554634863_5f6f616639.jpg
|
105 |
+
3223055565_68973f5d20.jpg
|
106 |
+
1554713437_61b64527dd.jpg
|
107 |
+
3150742439_b8a352e1e0.jpg
|
108 |
+
2238019823_79318d1f11.jpg
|
109 |
+
3484832904_08619300d9.jpg
|
110 |
+
3365783912_e12c3510d8.jpg
|
111 |
+
3185409663_95f6b958d8.jpg
|
112 |
+
3207358897_bfa61fa3c6.jpg
|
113 |
+
3263497678_8bb688ca01.jpg
|
114 |
+
1897025969_0c41688fa6.jpg
|
115 |
+
3657016761_d553e514d9.jpg
|
116 |
+
3537400880_8f410d747d.jpg
|
117 |
+
2419221084_01a14176b4.jpg
|
118 |
+
172097782_f0844ec317.jpg
|
119 |
+
244571201_0339d8e8d1.jpg
|
120 |
+
3467219837_7d62213dec.jpg
|
121 |
+
2928152792_b16c73434a.jpg
|
122 |
+
401079494_562454c4d6.jpg
|
123 |
+
2396691909_6b8c2f7c44.jpg
|
124 |
+
3243588540_b418ac7eda.jpg
|
125 |
+
3592992234_6d3fe58a70.jpg
|
126 |
+
1417031097_ab656bc4bd.jpg
|
127 |
+
1122944218_8eb3607403.jpg
|
128 |
+
3149919755_f9272b10b3.jpg
|
129 |
+
2682382530_f9f8fd1e89.jpg
|
130 |
+
2453971388_76616b6a82.jpg
|
131 |
+
3079787482_0757e9d167.jpg
|
132 |
+
2900274587_f2cbca4c58.jpg
|
133 |
+
3301859683_2d5e4b40a3.jpg
|
134 |
+
1287073593_f3d2a62455.jpg
|
135 |
+
2718495608_d8533e3ac5.jpg
|
136 |
+
2054869561_ff723e9eab.jpg
|
137 |
+
3567061016_62768dcce1.jpg
|
138 |
+
3221036999_3f7b152d8a.jpg
|
139 |
+
2554081584_233bdf289a.jpg
|
140 |
+
3250695024_93e8ab7305.jpg
|
141 |
+
3630332976_fdba22c50b.jpg
|
142 |
+
2902269566_419d9f1d8e.jpg
|
143 |
+
2544182005_3aa1332bf9.jpg
|
144 |
+
2999730677_0cfa1c146e.jpg
|
145 |
+
3354883962_170d19bfe4.jpg
|
146 |
+
2346401538_f5e8da66fc.jpg
|
147 |
+
3605676864_0fb491267e.jpg
|
148 |
+
3658427967_6e2e57458d.jpg
|
149 |
+
2868575889_2c030aa8ae.jpg
|
150 |
+
3494394662_3edfd4a34c.jpg
|
151 |
+
3452127051_fa54a902b3.jpg
|
152 |
+
3143155555_32b6d24f34.jpg
|
153 |
+
470373679_98dceb19e7.jpg
|
154 |
+
542317719_ed4dd95dc2.jpg
|
155 |
+
2844641033_dab3715a99.jpg
|
156 |
+
2588927489_f4da2f11ec.jpg
|
157 |
+
2041867793_552819a40b.jpg
|
158 |
+
2594042571_2e4666507e.jpg
|
159 |
+
493109089_468e105233.jpg
|
160 |
+
3109704348_c6416244ce.jpg
|
161 |
+
241345811_46b5f157d4.jpg
|
162 |
+
3457045393_2bbbb4e941.jpg
|
163 |
+
2797149878_bb8e27ecf9.jpg
|
164 |
+
543007912_23fc735b99.jpg
|
165 |
+
3364026240_645d533fda.jpg
|
166 |
+
466956209_2ffcea3941.jpg
|
167 |
+
2300168895_a9b83e16fc.jpg
|
168 |
+
106490881_5a2dd9b7bd.jpg
|
169 |
+
3694991841_141804da1f.jpg
|
170 |
+
1523984678_edd68464da.jpg
|
171 |
+
2529116152_4331dabf50.jpg
|
172 |
+
1773928579_5664a810dc.jpg
|
173 |
+
191003285_edd8d0cf58.jpg
|
174 |
+
1392272228_cf104086e6.jpg
|
175 |
+
2910758605_73a3f5a5c2.jpg
|
176 |
+
3507076266_8b17993fbb.jpg
|
177 |
+
535830521_aa971319fc.jpg
|
178 |
+
70995350_75d0698839.jpg
|
179 |
+
909808296_23c427022d.jpg
|
180 |
+
3364861247_d590fa170d.jpg
|
181 |
+
3545652636_0746537307.jpg
|
182 |
+
2869491449_1041485a6b.jpg
|
183 |
+
2901074943_041aba4607.jpg
|
184 |
+
3480051754_18e5802558.jpg
|
185 |
+
3234401637_84e0d14414.jpg
|
186 |
+
1317292658_ba29330a0b.jpg
|
187 |
+
2140182410_8e2a06fbda.jpg
|
188 |
+
3095225232_2e6e6dc92e.jpg
|
189 |
+
2280525192_81911f2b00.jpg
|
190 |
+
2763044275_aa498eb88b.jpg
|
191 |
+
2559503010_84f20b3bc9.jpg
|
192 |
+
496110746_a93ca191ae.jpg
|
193 |
+
468608014_09fd20eb9b.jpg
|
194 |
+
398662202_97e5819b79.jpg
|
195 |
+
3141293960_74459f0a24.jpg
|
196 |
+
2271755053_e1b1ec8442.jpg
|
197 |
+
3181701312_70a379ab6e.jpg
|
198 |
+
3523471597_87e0bf3b21.jpg
|
199 |
+
2083434441_a93bc6306b.jpg
|
200 |
+
54501196_a9ac9d66f2.jpg
|
201 |
+
751109943_2a7f8e117f.jpg
|
202 |
+
3121521593_18f0ec14f7.jpg
|
203 |
+
1432179046_8e3d75cf81.jpg
|
204 |
+
3234115903_f4dfc8fc75.jpg
|
205 |
+
3497224764_6e17544e0d.jpg
|
206 |
+
2878272032_fda05ffac7.jpg
|
207 |
+
1536774449_e16b1b6382.jpg
|
208 |
+
2228022180_9597b2a458.jpg
|
209 |
+
2708686056_1b8f356264.jpg
|
210 |
+
1402640441_81978e32a9.jpg
|
211 |
+
3437147889_4cf26dd525.jpg
|
212 |
+
448658518_eec0b648a6.jpg
|
213 |
+
211295363_49010ca38d.jpg
|
214 |
+
583174725_6b522b621f.jpg
|
215 |
+
2830869109_c4e403eae6.jpg
|
216 |
+
488590040_35a3e96c89.jpg
|
217 |
+
3217266166_4e0091860b.jpg
|
218 |
+
3246991821_750a3097e2.jpg
|
219 |
+
3048597471_5697538daf.jpg
|
220 |
+
2854959952_3991a385ab.jpg
|
221 |
+
2084217208_7bd9bc85e5.jpg
|
222 |
+
435827376_4384c3005a.jpg
|
223 |
+
2944362789_aebbc22db4.jpg
|
224 |
+
2497420371_74788d7ba1.jpg
|
225 |
+
309687244_4bdf3b591f.jpg
|
226 |
+
3433982387_3fa993cf5a.jpg
|
227 |
+
2782433864_5a0c311d87.jpg
|
228 |
+
136552115_6dc3e7231c.jpg
|
229 |
+
1679617928_a73c1769be.jpg
|
230 |
+
352981175_16ff5c07e4.jpg
|
231 |
+
1808370027_2088394eb4.jpg
|
232 |
+
3651971126_309e6a5e22.jpg
|
233 |
+
3708177171_529bb4ff1d.jpg
|
234 |
+
2450299735_62c095f40e.jpg
|
235 |
+
1387785218_cee67735f5.jpg
|
236 |
+
224369028_b1ac40d1fa.jpg
|
237 |
+
464251704_b0f0c4c87a.jpg
|
238 |
+
2648165716_02e2e74fd6.jpg
|
239 |
+
3085667767_66041b202e.jpg
|
240 |
+
3211556865_d1d9becf69.jpg
|
241 |
+
3503689049_63212220be.jpg
|
242 |
+
1107246521_d16a476380.jpg
|
243 |
+
3201427741_3033f5b625.jpg
|
244 |
+
3540416981_4e74f08cbb.jpg
|
245 |
+
410453140_5401bf659a.jpg
|
246 |
+
3702436188_2c26192fd0.jpg
|
247 |
+
2216695423_1362cb25f3.jpg
|
248 |
+
2345984157_724823b1e4.jpg
|
249 |
+
3317073508_7e13565c1b.jpg
|
250 |
+
2101457132_69c950bc45.jpg
|
251 |
+
3285993030_87b0f1d202.jpg
|
252 |
+
3220161734_77f42734b9.jpg
|
253 |
+
2393264648_a280744f97.jpg
|
254 |
+
506367606_7cca2bba9b.jpg
|
255 |
+
422763475_0bc814dac6.jpg
|
256 |
+
1982852140_56425fa7a2.jpg
|
257 |
+
2929506802_5432054d77.jpg
|
258 |
+
541063517_35044c554a.jpg
|
259 |
+
2595186208_9b16fa0ee3.jpg
|
260 |
+
2922973230_5a769ef92a.jpg
|
261 |
+
166507476_9be5b9852a.jpg
|
262 |
+
114051287_dd85625a04.jpg
|
263 |
+
3582742297_1daa29968e.jpg
|
264 |
+
396360611_941e5849a3.jpg
|
265 |
+
3504881781_6a842e043b.jpg
|
266 |
+
3558370311_5734a15890.jpg
|
267 |
+
2542662402_d781dd7f7c.jpg
|
268 |
+
3532205154_5674b628ea.jpg
|
269 |
+
2675685200_0913d84d9b.jpg
|
270 |
+
3565598162_56044bc2f7.jpg
|
271 |
+
3024172109_a10198e1dd.jpg
|
272 |
+
3116769029_f5a76f04ba.jpg
|
273 |
+
2061354254_faa5bd294b.jpg
|
274 |
+
3576259024_9c05b163aa.jpg
|
275 |
+
476759700_8911f087f8.jpg
|
276 |
+
2932740428_b15384f389.jpg
|
277 |
+
3348385580_10b53391f9.jpg
|
278 |
+
2510020918_b2ca0fb2aa.jpg
|
279 |
+
1517721825_10176d0683.jpg
|
280 |
+
2788945468_74a9618cfa.jpg
|
281 |
+
2608289957_044849f73e.jpg
|
282 |
+
3328646934_5cca4cebce.jpg
|
283 |
+
537532165_e4b7c0e61a.jpg
|
284 |
+
2933637854_984614e18b.jpg
|
285 |
+
3080056515_3013830309.jpg
|
286 |
+
1425069308_488e5fcf9d.jpg
|
287 |
+
261490838_2f3ac98b12.jpg
|
288 |
+
2926233397_71e617f3a3.jpg
|
289 |
+
2963573792_dd51b5fbfb.jpg
|
290 |
+
3416091866_a96003d652.jpg
|
291 |
+
2431470169_0eeba7d602.jpg
|
292 |
+
3099923914_fd450f6d51.jpg
|
293 |
+
524105255_b346f288be.jpg
|
294 |
+
56489627_e1de43de34.jpg
|
295 |
+
2587818583_4aa8e7b174.jpg
|
296 |
+
460935487_75b2da7854.jpg
|
297 |
+
3316725440_9ccd9b5417.jpg
|
298 |
+
2573625591_70291c894a.jpg
|
299 |
+
3030566410_393c36a6c5.jpg
|
300 |
+
1131800850_89c7ffd477.jpg
|
301 |
+
3375549004_beee810e60.jpg
|
302 |
+
2470486377_c3a39ccb7b.jpg
|
303 |
+
436009777_440c7679a1.jpg
|
304 |
+
2862004252_53894bb28b.jpg
|
305 |
+
3361990489_92244a58ef.jpg
|
306 |
+
293879742_5fe0ffd894.jpg
|
307 |
+
3203453897_6317aac6ff.jpg
|
308 |
+
1772859261_236c09b861.jpg
|
309 |
+
509123893_07b8ea82a9.jpg
|
310 |
+
3168123064_d1983b8f92.jpg
|
311 |
+
2238759450_6475641bdb.jpg
|
312 |
+
246055693_ccb69ac5c6.jpg
|
313 |
+
3521374954_37371b49a4.jpg
|
314 |
+
3143982558_9e2d44c155.jpg
|
315 |
+
3119076670_64b5340530.jpg
|
316 |
+
2502905671_c6039804ab.jpg
|
317 |
+
1267711451_e2a754b4f8.jpg
|
318 |
+
2683963310_20dcd5e566.jpg
|
319 |
+
302983277_69a4e732e4.jpg
|
320 |
+
3584534971_b44f82c4b9.jpg
|
321 |
+
143688283_a96ded20f1.jpg
|
322 |
+
1282392036_5a0328eb86.jpg
|
323 |
+
2704934519_457dc38986.jpg
|
324 |
+
3499720588_c32590108e.jpg
|
325 |
+
506738508_327efdf9c3.jpg
|
326 |
+
512101751_05a6d93e19.jpg
|
327 |
+
2317714088_bcd081f926.jpg
|
328 |
+
3275704430_a75828048f.jpg
|
329 |
+
2518508760_68d8df7365.jpg
|
330 |
+
3254817653_632e840423.jpg
|
331 |
+
3113322995_13781860f2.jpg
|
332 |
+
2103568100_5d018c495b.jpg
|
333 |
+
3518126579_e70e0cbb2b.jpg
|
334 |
+
2192131110_8a40e7c028.jpg
|
335 |
+
2581066814_179d28f306.jpg
|
336 |
+
480505313_2dc686e5db.jpg
|
337 |
+
1056338697_4f7d7ce270.jpg
|
338 |
+
532457586_bddfc5251d.jpg
|
339 |
+
3471841031_a949645ba8.jpg
|
340 |
+
3295680663_af21ea648b.jpg
|
341 |
+
415793623_6c1225ae27.jpg
|
342 |
+
2666205903_8d287669e1.jpg
|
343 |
+
3323988406_e3c8fce690.jpg
|
344 |
+
3347666612_659e6e2207.jpg
|
345 |
+
3439382048_d2e23b2b4c.jpg
|
346 |
+
2522297487_57edf117f7.jpg
|
347 |
+
3003691049_f4363c2d5c.jpg
|
348 |
+
2472980433_210ec62874.jpg
|
349 |
+
2307118114_c258e3a47e.jpg
|
350 |
+
2410320522_d967f0b75c.jpg
|
351 |
+
1408958345_68eea9a4e4.jpg
|
352 |
+
498444334_a680d318a1.jpg
|
353 |
+
3596131692_91b8a05606.jpg
|
354 |
+
2208310655_a3d83080c5.jpg
|
355 |
+
2340206885_58754a799a.jpg
|
356 |
+
2968182121_b3b491df85.jpg
|
357 |
+
3514019869_7de4ece2a5.jpg
|
358 |
+
2162564553_96de62c7e6.jpg
|
359 |
+
766099402_cdda6964f0.jpg
|
360 |
+
3593392955_a4125087f6.jpg
|
361 |
+
1472230829_803818a383.jpg
|
362 |
+
2774554310_007e980a90.jpg
|
363 |
+
2289068031_fe26990183.jpg
|
364 |
+
3411393875_a9ff73c67a.jpg
|
365 |
+
3406930103_4db7b4dde0.jpg
|
366 |
+
497791037_93499238d8.jpg
|
367 |
+
3255482333_5bcee79f7e.jpg
|
368 |
+
3040033126_9f4b88261b.jpg
|
369 |
+
2354540393_a149722680.jpg
|
370 |
+
2739331794_4ae78f69a0.jpg
|
371 |
+
241346508_0b3907a95b.jpg
|
372 |
+
2877503811_4e311253ec.jpg
|
373 |
+
3484649669_7bfe62080b.jpg
|
374 |
+
1084040636_97d9633581.jpg
|
375 |
+
3027397797_4f1d305ced.jpg
|
376 |
+
2398605966_1d0c9e6a20.jpg
|
377 |
+
2533424347_cf2f84872b.jpg
|
378 |
+
189721896_1ffe76d89e.jpg
|
379 |
+
2089426086_7acc98a3a8.jpg
|
380 |
+
2718024196_3ff660416a.jpg
|
381 |
+
3072114570_e1c0127529.jpg
|
382 |
+
3516825206_5750824874.jpg
|
383 |
+
3224227640_31865b3651.jpg
|
384 |
+
200771289_31902164a7.jpg
|
385 |
+
3502993968_4ee36afb0e.jpg
|
386 |
+
3692593096_fbaea67476.jpg
|
387 |
+
447111935_5af98563e3.jpg
|
388 |
+
3568197730_a071d7595b.jpg
|
389 |
+
3569979711_6507841268.jpg
|
390 |
+
180506881_de0f59770f.jpg
|
391 |
+
3017521547_f5ef8848e3.jpg
|
392 |
+
3503623999_bbd5dcfb18.jpg
|
393 |
+
3301811927_a2797339e5.jpg
|
394 |
+
3592968286_b63c81bcd2.jpg
|
395 |
+
2311690895_0d6efe11c8.jpg
|
396 |
+
452419961_6d42ab7000.jpg
|
397 |
+
2641770481_c98465ff35.jpg
|
398 |
+
2878190821_6e4e03dc5f.jpg
|
399 |
+
3725202807_12fbfdd207.jpg
|
400 |
+
2938747424_64e64784f0.jpg
|
401 |
+
1322323208_c7ecb742c6.jpg
|
402 |
+
2458269558_277012780d.jpg
|
403 |
+
2985679744_75a7102aab.jpg
|
404 |
+
317383917_d8bfa350b6.jpg
|
405 |
+
2482629385_f370b290d1.jpg
|
406 |
+
293327462_20dee0de56.jpg
|
407 |
+
359837950_9e22ffe6c2.jpg
|
408 |
+
354642192_3b7666a2dd.jpg
|
409 |
+
1786425974_c7c5ad6aa1.jpg
|
410 |
+
3767841911_6678052eb6.jpg
|
411 |
+
2884420269_225d27f242.jpg
|
412 |
+
2715035273_8fc8b1291c.jpg
|
413 |
+
3123463486_f5b36a3624.jpg
|
414 |
+
2194286203_5dc620006a.jpg
|
415 |
+
2815256108_fc1302117d.jpg
|
416 |
+
1348304997_afe60a61df.jpg
|
417 |
+
888425986_e4b6c12324.jpg
|
418 |
+
3485425825_c2f3446e73.jpg
|
419 |
+
3217187564_0ffd89dec1.jpg
|
420 |
+
3589895574_ee08207d26.jpg
|
421 |
+
317109978_cb557802e1.jpg
|
422 |
+
2224450291_4c133fabe8.jpg
|
423 |
+
3155390408_8e1a81efb2.jpg
|
424 |
+
3562050678_4196a7fff3.jpg
|
425 |
+
2696866120_254a0345bc.jpg
|
426 |
+
3114944484_28b5bb9842.jpg
|
427 |
+
751737218_b89839a311.jpg
|
428 |
+
352382023_7605223d1c.jpg
|
429 |
+
247704641_d883902277.jpg
|
430 |
+
3461041826_0e24cdf597.jpg
|
431 |
+
3358558292_6ab14193ed.jpg
|
432 |
+
525863257_053333e612.jpg
|
433 |
+
2112921744_92bf706805.jpg
|
434 |
+
375392855_54d46ed5c8.jpg
|
435 |
+
1917265421_aeccf1ca38.jpg
|
436 |
+
1659358141_0433c9bf99.jpg
|
437 |
+
2533642917_a5eace85e6.jpg
|
438 |
+
2204550058_2707d92338.jpg
|
439 |
+
2764178773_d63b502812.jpg
|
440 |
+
180094434_b0f244832d.jpg
|
441 |
+
2308978137_bfe776d541.jpg
|
442 |
+
3358682439_be4b83544c.jpg
|
443 |
+
2602085456_d1beebcb29.jpg
|
444 |
+
2589241160_3832440850.jpg
|
445 |
+
421322723_3470543368.jpg
|
446 |
+
2124040721_bffc0a091a.jpg
|
447 |
+
3145967309_b33abe4d84.jpg
|
448 |
+
300550441_f44ec3701a.jpg
|
449 |
+
1584315962_5b0b45d02d.jpg
|
450 |
+
2460797929_66446c13db.jpg
|
451 |
+
2909875716_25c8652614.jpg
|
452 |
+
3085667865_fa001816be.jpg
|
453 |
+
3624327440_bef4f33f32.jpg
|
454 |
+
979383193_0a542a059d.jpg
|
455 |
+
3009644534_992e9ea2a7.jpg
|
456 |
+
561940436_64d6fc125d.jpg
|
457 |
+
3393926562_66cc01b001.jpg
|
458 |
+
3299820401_c2589186c5.jpg
|
459 |
+
3545586120_283d728a97.jpg
|
460 |
+
1467533293_a2656cc000.jpg
|
461 |
+
373394550_1b2296b8c4.jpg
|
462 |
+
539751252_2bd88c456b.jpg
|
463 |
+
2621415349_ef1a7e73be.jpg
|
464 |
+
2077079696_03380d218b.jpg
|
465 |
+
566397227_a469e9e415.jpg
|
466 |
+
115684808_cb01227802.jpg
|
467 |
+
3387542157_81bfd00072.jpg
|
468 |
+
2646116932_232573f030.jpg
|
469 |
+
307327914_f98f576adb.jpg
|
470 |
+
3044536048_e615466e7f.jpg
|
471 |
+
3053743109_a2d780c0d2.jpg
|
472 |
+
2265096094_8cc34d669c.jpg
|
473 |
+
2283966256_70317e1759.jpg
|
474 |
+
3609645320_815c294b65.jpg
|
475 |
+
3047264346_e24601bfbf.jpg
|
476 |
+
439037721_cdf1fc7358.jpg
|
477 |
+
2594902417_f65d8866a8.jpg
|
478 |
+
533483374_86c5d4c13e.jpg
|
479 |
+
2991575785_bd4868e215.jpg
|
480 |
+
3295391572_cbfde03a10.jpg
|
481 |
+
3217620013_8b17873273.jpg
|
482 |
+
2526041608_a9775ab8d7.jpg
|
483 |
+
3028969146_26929ae0e8.jpg
|
484 |
+
254295381_d98fa049f4.jpg
|
485 |
+
2148916767_644ea6a7fa.jpg
|
486 |
+
3200120942_59cfbb3437.jpg
|
487 |
+
3591458156_f1a9a33918.jpg
|
488 |
+
3354330935_de75be9d2f.jpg
|
489 |
+
3320356356_1497e53f80.jpg
|
490 |
+
353180303_6a24179c50.jpg
|
491 |
+
3064383768_f6838f57da.jpg
|
492 |
+
154871781_ae77696b77.jpg
|
493 |
+
2616643090_4f2d2d1a44.jpg
|
494 |
+
2049051050_20359a434a.jpg
|
495 |
+
1472882567_33dc14c8b6.jpg
|
496 |
+
170100272_d820db2199.jpg
|
497 |
+
2096771662_984441d20d.jpg
|
498 |
+
363617160_6cb0c723be.jpg
|
499 |
+
3523474077_16e14bc54c.jpg
|
500 |
+
3506468593_7e41a6d9f1.jpg
|
501 |
+
1446053356_a924b4893f.jpg
|
502 |
+
3123351642_3794f2f601.jpg
|
503 |
+
523985664_c866af4850.jpg
|
504 |
+
3251976937_20625dc2b8.jpg
|
505 |
+
2078311270_f01c9eaf4c.jpg
|
506 |
+
350443876_c9769f5734.jpg
|
507 |
+
2649406158_ded6be38de.jpg
|
508 |
+
215214751_e913b6ff09.jpg
|
509 |
+
2926595608_69b22be8d4.jpg
|
510 |
+
3310067561_b92017acab.jpg
|
511 |
+
997722733_0cb5439472.jpg
|
512 |
+
1389264266_8170bc1c54.jpg
|
513 |
+
2774430374_fee1d793e7.jpg
|
514 |
+
3384314832_dffc944152.jpg
|
515 |
+
3251648670_9339943ba2.jpg
|
516 |
+
2933912528_52b05f84a1.jpg
|
517 |
+
3694093650_547259731e.jpg
|
518 |
+
2197275664_fabcf3424b.jpg
|
519 |
+
2505988632_9541f15583.jpg
|
520 |
+
3477715432_79d82487bb.jpg
|
521 |
+
241031254_0c6f30e3d1.jpg
|
522 |
+
2575647360_f5de38c751.jpg
|
523 |
+
3539767254_c598b8e6c7.jpg
|
524 |
+
3182121297_38c99b2769.jpg
|
525 |
+
1682079482_9a72fa57fa.jpg
|
526 |
+
3247052319_da8aba1983.jpg
|
527 |
+
249394748_2e4acfbbb5.jpg
|
528 |
+
2461616306_3ee7ac1b4b.jpg
|
529 |
+
929679367_ff8c7df2ee.jpg
|
530 |
+
468102269_135938e209.jpg
|
531 |
+
771048251_602e5e8f45.jpg
|
532 |
+
2384353160_f395e9a54b.jpg
|
533 |
+
3245912109_fdeef6b456.jpg
|
534 |
+
3613955682_3860e116cf.jpg
|
535 |
+
2866254827_9a8f592017.jpg
|
536 |
+
160792599_6a7ec52516.jpg
|
537 |
+
3108732084_565b423162.jpg
|
538 |
+
2991994607_06f24ec7a6.jpg
|
539 |
+
542179694_e170e9e465.jpg
|
540 |
+
136644343_0e2b423829.jpg
|
541 |
+
3605061440_1d08c80a57.jpg
|
542 |
+
2358554995_54ed3baa83.jpg
|
543 |
+
3138399980_d6ab8b2272.jpg
|
544 |
+
2944836001_b38b516286.jpg
|
545 |
+
2949982320_c704b31626.jpg
|
546 |
+
2544426580_317b1f1f73.jpg
|
547 |
+
3006093003_c211737232.jpg
|
548 |
+
2370481277_a3085614c9.jpg
|
549 |
+
2707873672_15e6b5d54b.jpg
|
550 |
+
3427118504_93126c83e0.jpg
|
551 |
+
3203908917_53e53c03d1.jpg
|
552 |
+
1415591512_a84644750c.jpg
|
553 |
+
2757803246_8aa3499d26.jpg
|
554 |
+
2061144717_5b3a1864f0.jpg
|
555 |
+
3393343330_b13df4d8ec.jpg
|
556 |
+
3569406219_f37ebf7b92.jpg
|
557 |
+
3353036763_4cbeba03b2.jpg
|
558 |
+
3498327617_d2e3db3ee3.jpg
|
559 |
+
1343426964_cde3fb54e8.jpg
|
560 |
+
3425851292_de92a072ee.jpg
|
561 |
+
3630641436_8f9ac5b9b2.jpg
|
562 |
+
2901880865_3fd7b66a45.jpg
|
563 |
+
2445283938_ff477c7952.jpg
|
564 |
+
3315616181_15dd137e27.jpg
|
565 |
+
1572532018_64c030c974.jpg
|
566 |
+
2308271254_27fb466eb4.jpg
|
567 |
+
2498897831_0bbb5d5b51.jpg
|
568 |
+
2170222061_e8bce4a32d.jpg
|
569 |
+
2534502836_7a75305655.jpg
|
570 |
+
534875358_6ea30d3091.jpg
|
571 |
+
370614351_98b8a166b9.jpg
|
572 |
+
3429956016_3c7e3096c2.jpg
|
573 |
+
514990193_2d2422af2c.jpg
|
574 |
+
1287475186_2dee85f1a5.jpg
|
575 |
+
2966552760_e65b22cd26.jpg
|
576 |
+
486712504_36be449055.jpg
|
577 |
+
3015863181_92ff43f4d8.jpg
|
578 |
+
348380010_33bb0599ef.jpg
|
579 |
+
3670907052_c827593564.jpg
|
580 |
+
1626754053_81126b67b6.jpg
|
581 |
+
3716244806_97d5a1fb61.jpg
|
582 |
+
3641022607_e7a5455d6c.jpg
|
583 |
+
2950905787_f2017d3e49.jpg
|
584 |
+
3482974845_db4f16befa.jpg
|
585 |
+
2883099128_0b056eed9e.jpg
|
586 |
+
2310126952_7dc86d88f6.jpg
|
587 |
+
2479162876_a5ce3306af.jpg
|
588 |
+
3498997518_c2b16f0a0e.jpg
|
589 |
+
3232470286_903a61ea16.jpg
|
590 |
+
2183227136_8bb657846b.jpg
|
591 |
+
2120383553_5825333a3f.jpg
|
592 |
+
3544793763_b38546a5e8.jpg
|
593 |
+
1404832008_68e432665b.jpg
|
594 |
+
3541474181_489f19fae7.jpg
|
595 |
+
3042380610_c5ea61eef8.jpg
|
596 |
+
486917990_72bd4069af.jpg
|
597 |
+
2599444370_9e40103027.jpg
|
598 |
+
3468694409_a51571d621.jpg
|
599 |
+
494921598_af73bda568.jpg
|
600 |
+
197107117_4b438b1872.jpg
|
601 |
+
3019842612_8501c1791e.jpg
|
602 |
+
909191414_1cf5d85821.jpg
|
603 |
+
2945036454_280fa5b29f.jpg
|
604 |
+
2666179615_f05a9d8331.jpg
|
605 |
+
3030294889_78b2ccbe51.jpg
|
606 |
+
509778093_21236bb64d.jpg
|
607 |
+
3245070961_8977fdd548.jpg
|
608 |
+
533713007_bf9f3e25b4.jpg
|
609 |
+
2922222717_12195af92d.jpg
|
610 |
+
3191135894_2b4bdabb6d.jpg
|
611 |
+
700884207_d3ec546494.jpg
|
612 |
+
2196846255_2c1635359a.jpg
|
613 |
+
3474406285_01f3d24b71.jpg
|
614 |
+
448252603_7d928c900e.jpg
|
615 |
+
2860872588_f2c7b30e1a.jpg
|
616 |
+
880220939_0ef1c37f1f.jpg
|
617 |
+
820169182_f5e78d7d19.jpg
|
618 |
+
3436063693_15c8d377a2.jpg
|
619 |
+
1262583859_653f1469a9.jpg
|
620 |
+
3185371756_ff4e9fa8a6.jpg
|
621 |
+
3591462960_86045906bd.jpg
|
622 |
+
3619416477_9d18580a14.jpg
|
623 |
+
3459156091_c1879ebe28.jpg
|
624 |
+
537559285_29be110134.jpg
|
625 |
+
3052196390_c59dd24ca8.jpg
|
626 |
+
2490768374_45d94fc658.jpg
|
627 |
+
150387174_24825cf871.jpg
|
628 |
+
1962729184_6996e128e7.jpg
|
629 |
+
2306674172_dc07c7f847.jpg
|
630 |
+
2086513494_dbbcb583e7.jpg
|
631 |
+
2652522323_9218afd8c2.jpg
|
632 |
+
3399284917_721aefe2a7.jpg
|
633 |
+
370713359_7560808550.jpg
|
634 |
+
2843695880_eeea6c67db.jpg
|
635 |
+
2676764246_c58205a365.jpg
|
636 |
+
3107513635_fe8a21f148.jpg
|
637 |
+
2885387575_9127ea10f1.jpg
|
638 |
+
3223224391_be50bf4f43.jpg
|
639 |
+
1461667284_041c8a2475.jpg
|
640 |
+
2196316998_3b2d63f01f.jpg
|
641 |
+
1998457059_c9ac9a1e1a.jpg
|
642 |
+
3294209955_a1f1e2cc19.jpg
|
643 |
+
488408004_a1e26d4886.jpg
|
644 |
+
3135504530_0f4130d8f8.jpg
|
645 |
+
3217910740_d1d61c08ab.jpg
|
646 |
+
3602838407_bf13e49243.jpg
|
647 |
+
2984174290_a915748d77.jpg
|
648 |
+
424779662_568f9606d0.jpg
|
649 |
+
2431832075_00aa1a4457.jpg
|
650 |
+
624742559_ff467d8ebc.jpg
|
651 |
+
3157847991_463e006a28.jpg
|
652 |
+
2893374123_087f98d58a.jpg
|
653 |
+
3359551687_68f2f0212a.jpg
|
654 |
+
3070031806_3d587c2a66.jpg
|
655 |
+
2480850054_de3433b54a.jpg
|
656 |
+
3216926094_bc975e84b9.jpg
|
657 |
+
3449114979_6cdc3e8da8.jpg
|
658 |
+
2543589122_ec3e55f434.jpg
|
659 |
+
3530843182_35af2c821c.jpg
|
660 |
+
3472364264_dbde5a8d0a.jpg
|
661 |
+
3715469645_6d1dc019b3.jpg
|
662 |
+
2196107384_361d73a170.jpg
|
663 |
+
1561658940_a947f2446a.jpg
|
664 |
+
3655074079_7df3812bc5.jpg
|
665 |
+
3004823335_9b82cbd8a7.jpg
|
666 |
+
2495931537_9b8d4474b6.jpg
|
667 |
+
293881927_ac62900fd4.jpg
|
668 |
+
3162045919_c2decbb69b.jpg
|
669 |
+
505929313_7668f021ab.jpg
|
670 |
+
3244470342_c08f6bb17e.jpg
|
671 |
+
3655964639_21e76383d0.jpg
|
672 |
+
3718964174_cb2dc1615e.jpg
|
673 |
+
3388330419_85d72f7cda.jpg
|
674 |
+
2128119486_4407061c40.jpg
|
675 |
+
917574521_74fab68514.jpg
|
676 |
+
400851260_5911898657.jpg
|
677 |
+
270816949_ffad112278.jpg
|
678 |
+
421730441_6b2267fd31.jpg
|
679 |
+
429851331_b248ca01cd.jpg
|
680 |
+
241345905_5826a72da1.jpg
|
681 |
+
2102360862_264452db8e.jpg
|
682 |
+
3051384385_c5c850c1f8.jpg
|
683 |
+
3500136982_bf7a85531e.jpg
|
684 |
+
416788726_5b4eb1466e.jpg
|
685 |
+
245895500_a4eb97af02.jpg
|
686 |
+
3259002340_707ce96858.jpg
|
687 |
+
2796801478_8ebd7e550b.jpg
|
688 |
+
57422853_b5f6366081.jpg
|
689 |
+
1311388430_4ab0cd1a1f.jpg
|
690 |
+
522063319_33827f1627.jpg
|
691 |
+
384577800_fc325af410.jpg
|
692 |
+
3159995270_17334ccb5b.jpg
|
693 |
+
2229179070_dc8ea8582e.jpg
|
694 |
+
1764955991_5e53a28c87.jpg
|
695 |
+
670609997_5c7fdb3f0b.jpg
|
696 |
+
86412576_c53392ef80.jpg
|
697 |
+
260828892_7925d27865.jpg
|
698 |
+
3737539561_d1dc161040.jpg
|
699 |
+
3262075846_5695021d84.jpg
|
700 |
+
3227148358_f152303584.jpg
|
701 |
+
2373234213_4ebe9c4ee5.jpg
|
702 |
+
2914206497_5e36ac6324.jpg
|
703 |
+
488356951_b3b77ad832.jpg
|
704 |
+
2105756457_a100d8434e.jpg
|
705 |
+
3506560025_8d0f4f9ac4.jpg
|
706 |
+
3456362961_d8f7e347a8.jpg
|
707 |
+
3044500219_778f9f2b71.jpg
|
708 |
+
2301525531_edde12d673.jpg
|
709 |
+
3280052365_c4644bf0a5.jpg
|
710 |
+
3640422448_a0f42e4559.jpg
|
711 |
+
2396025708_e4a72e2558.jpg
|
712 |
+
1433142189_cda8652603.jpg
|
713 |
+
3214573346_d3a57f0328.jpg
|
714 |
+
3218480482_66af7587c8.jpg
|
715 |
+
2021613437_d99731f986.jpg
|
716 |
+
2525270674_4ab536e7ec.jpg
|
717 |
+
3470951932_27ed74eb0b.jpg
|
718 |
+
2870875612_2cbb9e4a3c.jpg
|
719 |
+
2541104331_a2d65cfa54.jpg
|
720 |
+
444057017_f1e0fcaef7.jpg
|
721 |
+
3597326009_3678a98a43.jpg
|
722 |
+
3360930596_1e75164ce6.jpg
|
723 |
+
247637795_fdf26a03cf.jpg
|
724 |
+
3696698390_989f1488e7.jpg
|
725 |
+
3421789737_f625dd17ed.jpg
|
726 |
+
53043785_c468d6f931.jpg
|
727 |
+
3058439373_9276a4702a.jpg
|
728 |
+
2100816230_ff866fb352.jpg
|
729 |
+
2729655904_1dd01922fb.jpg
|
730 |
+
3270691950_88583c3524.jpg
|
731 |
+
3729525173_7f984ed776.jpg
|
732 |
+
540721368_12ac732c6c.jpg
|
733 |
+
3686924335_3c51e8834a.jpg
|
734 |
+
2295216243_0712928988.jpg
|
735 |
+
3450874870_c4dcf58fb3.jpg
|
736 |
+
3061481868_d1e00b1f2e.jpg
|
737 |
+
308487515_7852928f90.jpg
|
738 |
+
263854883_0f320c1562.jpg
|
739 |
+
3549583146_3e8bb2f7e9.jpg
|
740 |
+
3542484764_77d8920ec9.jpg
|
741 |
+
3208074567_ac44aeb3f3.jpg
|
742 |
+
3167365436_c379bda282.jpg
|
743 |
+
2693425189_47740c22ed.jpg
|
744 |
+
434792818_56375e203f.jpg
|
745 |
+
3635577874_48ebaac734.jpg
|
746 |
+
3413571342_b9855795e2.jpg
|
747 |
+
2475162978_2c51048dca.jpg
|
748 |
+
2160266952_a2ab39191b.jpg
|
749 |
+
463978865_c87c6ca84c.jpg
|
750 |
+
3585487286_ef9a8d4c56.jpg
|
751 |
+
3239021459_a6b71bb400.jpg
|
752 |
+
2662845514_8620aaee96.jpg
|
753 |
+
3044746136_8b89da5f40.jpg
|
754 |
+
343218198_1ca90e0734.jpg
|
755 |
+
2924259848_effb4dcb82.jpg
|
756 |
+
3720366614_dfa8fe1088.jpg
|
757 |
+
1356796100_b265479721.jpg
|
758 |
+
2905942129_2b4bf59bc0.jpg
|
759 |
+
2660008870_b672a4c76a.jpg
|
760 |
+
2274992140_bb9e868bb8.jpg
|
761 |
+
3538213870_9856a76b2a.jpg
|
762 |
+
2206960564_325ed0c7ae.jpg
|
763 |
+
2839038702_e168128665.jpg
|
764 |
+
424416723_19c56cb365.jpg
|
765 |
+
2876993733_cb26107d18.jpg
|
766 |
+
223299142_521aedf9e7.jpg
|
767 |
+
3347798761_5c5260b000.jpg
|
768 |
+
1220401002_3f44b1f3f7.jpg
|
769 |
+
3564543247_05cdbc31cf.jpg
|
770 |
+
3385246141_a263d1053e.jpg
|
771 |
+
3334537556_a2cf4e9b9a.jpg
|
772 |
+
2909955251_4b326a46a7.jpg
|
773 |
+
2247889670_413db8094b.jpg
|
774 |
+
3186073578_6e115f45f5.jpg
|
775 |
+
3192069971_83c5a90b4c.jpg
|
776 |
+
3422458549_f3f3878dbf.jpg
|
777 |
+
2891617125_f939f604c7.jpg
|
778 |
+
279728508_6bd7281f3c.jpg
|
779 |
+
2913965136_2d00136697.jpg
|
780 |
+
3692892751_f6574e2700.jpg
|
781 |
+
2288099178_41091aa00c.jpg
|
782 |
+
476233374_e1396998ef.jpg
|
783 |
+
2559921948_06af25d566.jpg
|
784 |
+
2189995738_352607a63b.jpg
|
785 |
+
3359530430_249f51972c.jpg
|
786 |
+
317488612_70ac35493b.jpg
|
787 |
+
2842865689_e37256d9ce.jpg
|
788 |
+
2225231022_1632d0a5aa.jpg
|
789 |
+
327415627_6313d32a64.jpg
|
790 |
+
2292406847_f366350600.jpg
|
791 |
+
3571147934_d1c8af1d6e.jpg
|
792 |
+
2607462776_78e639d891.jpg
|
793 |
+
801607443_f15956d1ce.jpg
|
794 |
+
2176980976_7054c99621.jpg
|
795 |
+
3523559027_a65619a34b.jpg
|
796 |
+
1329832826_432538d331.jpg
|
797 |
+
260520547_944f9f4c91.jpg
|
798 |
+
2473738924_eca928d12f.jpg
|
799 |
+
1765164972_92dac06fa9.jpg
|
800 |
+
2806710650_e201acd913.jpg
|
801 |
+
2501595799_6316001e89.jpg
|
802 |
+
3697359692_8a5cdbe4fe.jpg
|
803 |
+
3688858505_e8afd1475d.jpg
|
804 |
+
3396157719_6807d52a81.jpg
|
805 |
+
473220329_819a913bbb.jpg
|
806 |
+
3228069008_edb2961fc4.jpg
|
807 |
+
2861932486_52befd8592.jpg
|
808 |
+
758921886_55a351dd67.jpg
|
809 |
+
791338571_7f38510bf7.jpg
|
810 |
+
3435035138_af32890a4c.jpg
|
811 |
+
1339596997_8ac29c1841.jpg
|
812 |
+
3245460937_2710a82709.jpg
|
813 |
+
3256275785_9c3af57576.jpg
|
814 |
+
2856080862_95d793fa9d.jpg
|
815 |
+
3179336562_c3d0c0a3bd.jpg
|
816 |
+
430173345_86388d8822.jpg
|
817 |
+
1096395242_fc69f0ae5a.jpg
|
818 |
+
2378149488_648e5deeac.jpg
|
819 |
+
2358561039_e215a8d6cd.jpg
|
820 |
+
2667015110_1670324a33.jpg
|
821 |
+
500446858_125702b296.jpg
|
822 |
+
226607225_44d696db6b.jpg
|
823 |
+
2496370758_a3fbc49837.jpg
|
824 |
+
3259991972_fce3ab18b2.jpg
|
825 |
+
229862312_1a0ba19dab.jpg
|
826 |
+
3333921867_6cc7d7c73d.jpg
|
827 |
+
2248487950_c62d0c81a9.jpg
|
828 |
+
3074842262_62b1b2168c.jpg
|
829 |
+
561417861_8e25d0c0e8.jpg
|
830 |
+
2646046871_c3a5dbb971.jpg
|
831 |
+
2944952557_8484f0da8f.jpg
|
832 |
+
3244747165_17028936e0.jpg
|
833 |
+
2285570521_05015cbf4b.jpg
|
834 |
+
315880837_90db309bab.jpg
|
835 |
+
3375070563_3c290a7991.jpg
|
836 |
+
1298295313_db1f4c6522.jpg
|
837 |
+
3585598356_8ce815bbb9.jpg
|
838 |
+
2473689180_e9d8fd656a.jpg
|
839 |
+
3258874419_23fec1bdc1.jpg
|
840 |
+
1237985362_dbafc59280.jpg
|
841 |
+
3290105461_7590f23371.jpg
|
842 |
+
2644430445_47c985a2ee.jpg
|
843 |
+
732468337_a37075225e.jpg
|
844 |
+
113678030_87a6a6e42e.jpg
|
845 |
+
2120411340_104eb610b1.jpg
|
846 |
+
2450453051_f1d4a78ab4.jpg
|
847 |
+
2831217847_555b2f95ca.jpg
|
848 |
+
3192266178_f9bf5d3dba.jpg
|
849 |
+
326456451_effadbbe49.jpg
|
850 |
+
2663794355_e726ec7e05.jpg
|
851 |
+
3364151356_eecd07a23e.jpg
|
852 |
+
2251747182_6b67a3ab8b.jpg
|
853 |
+
3139160252_75109e9e05.jpg
|
854 |
+
219070971_ae43410b9e.jpg
|
855 |
+
1674612291_7154c5ab61.jpg
|
856 |
+
136886677_6026c622eb.jpg
|
857 |
+
3398746625_5199beea71.jpg
|
858 |
+
3220650628_4ed964e5b4.jpg
|
859 |
+
1082379191_ec1e53f996.jpg
|
860 |
+
3741462565_cc35966b7a.jpg
|
861 |
+
1174525839_7c1e6cfa86.jpg
|
862 |
+
3572267708_9d8a81d4a4.jpg
|
863 |
+
1509786421_f03158adfc.jpg
|
864 |
+
3155987659_b9ea318dd3.jpg
|
865 |
+
925491651_57df3a5b36.jpg
|
866 |
+
2735558076_0d7bbc18fc.jpg
|
867 |
+
300922408_05a4f9938c.jpg
|
868 |
+
1490670858_e122df2560.jpg
|
869 |
+
2953015871_cae796b6e7.jpg
|
870 |
+
524282699_71e678a6bd.jpg
|
871 |
+
2890113532_ab2003d74e.jpg
|
872 |
+
1456393634_74022d9056.jpg
|
873 |
+
2813033949_e19fa08805.jpg
|
874 |
+
745880539_cd3f948837.jpg
|
875 |
+
2480327661_fb69829f57.jpg
|
876 |
+
3125309108_1011486589.jpg
|
877 |
+
3287549827_04dec6fb6e.jpg
|
878 |
+
391579205_c8373b5411.jpg
|
879 |
+
2610447973_89227ff978.jpg
|
880 |
+
2698666984_13e17236ae.jpg
|
881 |
+
339350939_6643bfb270.jpg
|
882 |
+
127490019_7c5c08cb11.jpg
|
883 |
+
1714316707_8bbaa2a2ba.jpg
|
884 |
+
3556598205_86c180769d.jpg
|
885 |
+
757046028_ff5999f91b.jpg
|
886 |
+
132489044_3be606baf7.jpg
|
887 |
+
3613800013_5a54968ab0.jpg
|
888 |
+
2577972703_a22c5f2a87.jpg
|
889 |
+
2073964624_52da3a0fc4.jpg
|
890 |
+
2194494220_bb2178832c.jpg
|
891 |
+
2215136723_960edfea49.jpg
|
892 |
+
2759860913_f75b39d783.jpg
|
893 |
+
3225310099_d8e419ba56.jpg
|
894 |
+
2938120171_970564e3d8.jpg
|
895 |
+
754852108_72f80d421f.jpg
|
896 |
+
3187395715_f2940c2b72.jpg
|
897 |
+
3281078518_630a7a7f4f.jpg
|
898 |
+
3071676551_a65741e372.jpg
|
899 |
+
3106026005_473a7b1c8c.jpg
|
900 |
+
3523874798_9ba2fa46e3.jpg
|
901 |
+
245252561_4f20f1c89e.jpg
|
902 |
+
3685328542_ab999b83bb.jpg
|
903 |
+
3613424631_3ae537624f.jpg
|
904 |
+
3584930205_a3f58a4b7c.jpg
|
905 |
+
127488876_f2d2a89588.jpg
|
906 |
+
3578841731_f775cab089.jpg
|
907 |
+
2934359101_cdf57442dc.jpg
|
908 |
+
339658315_fbb178c252.jpg
|
909 |
+
2991994415_504d1c0a03.jpg
|
910 |
+
3349451628_4249a21c8f.jpg
|
911 |
+
3197917064_e679a44b8e.jpg
|
912 |
+
2657484284_daa07a3a1b.jpg
|
913 |
+
2894217628_f1a4153dca.jpg
|
914 |
+
3424424006_98f9d1921c.jpg
|
915 |
+
2526585002_10987a63f3.jpg
|
916 |
+
1836335410_de8313a64e.jpg
|
917 |
+
2443380641_7b38d18f5b.jpg
|
918 |
+
2208067635_39a03834ca.jpg
|
919 |
+
3427233064_6af01bfc5c.jpg
|
920 |
+
799486353_f665d7b0f0.jpg
|
921 |
+
3741827382_71e93298d0.jpg
|
922 |
+
3578914491_36019ba703.jpg
|
923 |
+
3197981073_3156963446.jpg
|
924 |
+
416960865_048fd3f294.jpg
|
925 |
+
197504190_fd1fc3d4b7.jpg
|
926 |
+
2484190118_e89363c465.jpg
|
927 |
+
2602258549_7401a3cdae.jpg
|
928 |
+
493621130_152bdd4e91.jpg
|
929 |
+
3332467180_d72f9b067d.jpg
|
930 |
+
2981702521_2459f2c1c4.jpg
|
931 |
+
461505235_590102a5bf.jpg
|
932 |
+
1490213660_9ea45550cf.jpg
|
933 |
+
300577375_26cc2773a1.jpg
|
934 |
+
2549968784_39bfbe44f9.jpg
|
935 |
+
2075321027_c8fcbaf581.jpg
|
936 |
+
1547883892_e29b3db42e.jpg
|
937 |
+
2886411666_72d8b12ce4.jpg
|
938 |
+
2239938351_43c73c887c.jpg
|
939 |
+
2918769188_565dd48060.jpg
|
940 |
+
3610683688_bbe6d725ed.jpg
|
941 |
+
3025549604_38b86198f5.jpg
|
942 |
+
2073105823_6dacade004.jpg
|
943 |
+
2447284966_d6bbdb4b6e.jpg
|
944 |
+
2600867924_cd502fc911.jpg
|
945 |
+
2333288869_8c01e4c859.jpg
|
946 |
+
3589367895_5d3729e3ea.jpg
|
947 |
+
96420612_feb18fc6c6.jpg
|
948 |
+
3375991133_87d7c40925.jpg
|
949 |
+
3320032226_63390d74a6.jpg
|
950 |
+
2971431335_e192613db4.jpg
|
951 |
+
219301555_17883a51bd.jpg
|
952 |
+
3222041930_f642f49d28.jpg
|
953 |
+
3187492926_8aa85f80c6.jpg
|
954 |
+
3673165148_67f217064f.jpg
|
955 |
+
270724499_107481c88f.jpg
|
956 |
+
2182488373_df73c7cc09.jpg
|
957 |
+
2421446839_fe7d46c177.jpg
|
958 |
+
2603792708_18a97bac97.jpg
|
959 |
+
2822290399_97c809d43b.jpg
|
960 |
+
1332722096_1e3de8ae70.jpg
|
961 |
+
3694064560_467683205b.jpg
|
962 |
+
3263395801_5e4cee2b9e.jpg
|
963 |
+
3701291852_373ea46bb6.jpg
|
964 |
+
2343525685_3eba3b6686.jpg
|
965 |
+
416106657_cab2a107a5.jpg
|
966 |
+
387830531_e89c192b92.jpg
|
967 |
+
2892995070_39f3c9a56e.jpg
|
968 |
+
3432550415_e7b77232de.jpg
|
969 |
+
3564312955_716e86c48b.jpg
|
970 |
+
3238951136_2a99f1a1a8.jpg
|
971 |
+
3595643050_d312e4b652.jpg
|
972 |
+
3139876823_859c7d7c23.jpg
|
973 |
+
3473264983_67917a931f.jpg
|
974 |
+
2994179598_a45c2732b5.jpg
|
975 |
+
491405109_798222cfd0.jpg
|
976 |
+
3115174046_9e96b9ce47.jpg
|
977 |
+
3631986552_944ea208fc.jpg
|
978 |
+
3350786891_6d39b234e9.jpg
|
979 |
+
3062173277_bfb5ef4c45.jpg
|
980 |
+
3108197858_441ff38565.jpg
|
981 |
+
1224851143_33bcdd299c.jpg
|
982 |
+
3458559770_12cf9f134e.jpg
|
983 |
+
3425835357_204e620a66.jpg
|
984 |
+
3214885227_2be09e7cfb.jpg
|
985 |
+
2854207034_1f00555703.jpg
|
986 |
+
2167644298_100ca79f54.jpg
|
987 |
+
241346971_c100650320.jpg
|
988 |
+
1386964743_9e80d96b05.jpg
|
989 |
+
3397220683_4aca010f86.jpg
|
990 |
+
2473791980_805c819bd4.jpg
|
991 |
+
241345844_69e1c22464.jpg
|
992 |
+
3256043809_47258e0b3e.jpg
|
993 |
+
2351479551_e8820a1ff3.jpg
|
994 |
+
3514179514_cbc3371b92.jpg
|
995 |
+
1119015538_e8e796281e.jpg
|
996 |
+
3727752439_907795603b.jpg
|
997 |
+
3430607596_7e4f74e3ff.jpg
|
998 |
+
3259666643_ae49524c81.jpg
|
999 |
+
2623930900_b9df917b82.jpg
|
1000 |
+
3490736665_38710f4b91.jpg
|
Flickr_8k.trainImages.txt
ADDED
The diff for this file is too large to render.
See raw diff
|
|
Img-captioning-project.ipynb
ADDED
@@ -0,0 +1,869 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "code",
|
5 |
+
"execution_count": 64,
|
6 |
+
"id": "029e3b0a",
|
7 |
+
"metadata": {},
|
8 |
+
"outputs": [],
|
9 |
+
"source": [
|
10 |
+
"from os import listdir\n",
|
11 |
+
"from pickle import dump\n",
|
12 |
+
"from keras.applications.vgg16 import VGG16, preprocess_input\n",
|
13 |
+
"from tensorflow.keras.preprocessing.image import img_to_array, load_img\n",
|
14 |
+
"from keras.models import Model"
|
15 |
+
]
|
16 |
+
},
|
17 |
+
{
|
18 |
+
"cell_type": "code",
|
19 |
+
"execution_count": 299,
|
20 |
+
"id": "bec9f820",
|
21 |
+
"metadata": {},
|
22 |
+
"outputs": [],
|
23 |
+
"source": [
|
24 |
+
"# extract feature from each photo in directory\n",
|
25 |
+
"def extract_feature(directory):\n",
|
26 |
+
" model = VGG16()\n",
|
27 |
+
" #restructure model, here we remove last softmax layer from this model\n",
|
28 |
+
" model.layers.pop\n",
|
29 |
+
" model = Model(inputs=model.inputs, outputs=model.layers[-1].output)\n",
|
30 |
+
" print(model.summary)\n",
|
31 |
+
" \n",
|
32 |
+
" #extract feature from each photo\n",
|
33 |
+
" feature = dict()\n",
|
34 |
+
" for name in listdir(directory):\n",
|
35 |
+
" filename = directory + '/' + name\n",
|
36 |
+
" image = load_img(filename, target_size=(224,224))\n",
|
37 |
+
" #convert img pixels to numpy array\n",
|
38 |
+
" image = img_to_array(image)\n",
|
39 |
+
" #reshape data for the model\n",
|
40 |
+
" image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))\n",
|
41 |
+
" #preprocess img for preprocess model\n",
|
42 |
+
" image = preprocess_input(image)\n",
|
43 |
+
" #get features\n",
|
44 |
+
" features = model.predict(image, verbose=0)\n",
|
45 |
+
" #get img id\n",
|
46 |
+
" img_id = name.split('.')[0]\n",
|
47 |
+
" #storing features\n",
|
48 |
+
" feature[img_id] = features\n",
|
49 |
+
" print(\">%s\" % name)\n",
|
50 |
+
" return feature"
|
51 |
+
]
|
52 |
+
},
|
53 |
+
{
|
54 |
+
"cell_type": "code",
|
55 |
+
"execution_count": null,
|
56 |
+
"id": "035ed4b2",
|
57 |
+
"metadata": {},
|
58 |
+
"outputs": [],
|
59 |
+
"source": [
|
60 |
+
"directory = \"img_captioning_dataset/Images\"\n",
|
61 |
+
"features = extract_feature(directory)\n",
|
62 |
+
"# print(\"Extracted Features: %d\" %len(features))\n",
|
63 |
+
"# dump(features, open('img_captioning_features/features.pkl', 'wb'))"
|
64 |
+
]
|
65 |
+
},
|
66 |
+
{
|
67 |
+
"cell_type": "code",
|
68 |
+
"execution_count": 385,
|
69 |
+
"id": "89135fbf",
|
70 |
+
"metadata": {},
|
71 |
+
"outputs": [],
|
72 |
+
"source": [
|
73 |
+
"import string\n",
|
74 |
+
"from nltk.tokenize import word_tokenize\n",
|
75 |
+
"\n",
|
76 |
+
"def load_doc(filename):\n",
|
77 |
+
" # open the file as read only\n",
|
78 |
+
" file = open(filename, 'r')\n",
|
79 |
+
" # read all text\n",
|
80 |
+
" text = file.read()\n",
|
81 |
+
" # close the file\n",
|
82 |
+
" file.close()\n",
|
83 |
+
" return text\n",
|
84 |
+
"\n",
|
85 |
+
"#extract description of image\n",
|
86 |
+
"def load_description(doc):\n",
|
87 |
+
" mapping = dict()\n",
|
88 |
+
" for line in doc.split('\\n'):\n",
|
89 |
+
" token = word_tokenize(line)\n",
|
90 |
+
" if len(line) < 2:\n",
|
91 |
+
" continue\n",
|
92 |
+
" image_id, image_desc = token[0], token[1:]\n",
|
93 |
+
" image_id = image_id.split('.')[0]\n",
|
94 |
+
" image_desc = ' '.join(image_desc)\n",
|
95 |
+
" if image_id not in mapping:\n",
|
96 |
+
" mapping[image_id] = list()\n",
|
97 |
+
" mapping[image_id].append(image_desc)\n",
|
98 |
+
" return mapping"
|
99 |
+
]
|
100 |
+
},
|
101 |
+
{
|
102 |
+
"cell_type": "code",
|
103 |
+
"execution_count": 386,
|
104 |
+
"id": "74ffda4f",
|
105 |
+
"metadata": {},
|
106 |
+
"outputs": [],
|
107 |
+
"source": [
|
108 |
+
"def clean_descriptions(descriptions):\n",
|
109 |
+
" # prepare translation table for removing punctuation\n",
|
110 |
+
" table = str.maketrans('', '', string.punctuation)\n",
|
111 |
+
" for key, desc_list in descriptions.items():\n",
|
112 |
+
" for i in range(len(desc_list)):\n",
|
113 |
+
" desc = desc_list[i]\n",
|
114 |
+
" # tokenize\n",
|
115 |
+
" desc = desc.split()\n",
|
116 |
+
" # convert to lower case\n",
|
117 |
+
" desc = [word.lower() for word in desc]\n",
|
118 |
+
" # remove punctuation from each token\n",
|
119 |
+
" desc = [w.translate(table) for w in desc]\n",
|
120 |
+
" # remove hanging 's' and 'a'\n",
|
121 |
+
" desc = [word for word in desc if len(word)>1]\n",
|
122 |
+
" # remove tokens with numbers in them\n",
|
123 |
+
" desc = [word for word in desc if word.isalpha()]\n",
|
124 |
+
" # store as string\n",
|
125 |
+
" desc_list[i] = ' '.join(desc)\n",
|
126 |
+
"def to_vocabulary(descriptions):\n",
|
127 |
+
" # build a list of all description strings\n",
|
128 |
+
" all_desc = set()\n",
|
129 |
+
" for key in descriptions.keys():\n",
|
130 |
+
" [all_desc.update(d.split()) for d in descriptions[key]]\n",
|
131 |
+
" return all_desc"
|
132 |
+
]
|
133 |
+
},
|
134 |
+
{
|
135 |
+
"cell_type": "code",
|
136 |
+
"execution_count": 387,
|
137 |
+
"id": "6ae0e204",
|
138 |
+
"metadata": {},
|
139 |
+
"outputs": [],
|
140 |
+
"source": [
|
141 |
+
"def save_descriptions(descriptions, filename):\n",
|
142 |
+
" lines = list()\n",
|
143 |
+
" for key, desc_list in descriptions.items():\n",
|
144 |
+
" for desc in desc_list:\n",
|
145 |
+
" lines.append(key + \" \" + desc)\n",
|
146 |
+
" data = '\\n'.join(lines)\n",
|
147 |
+
" file = open(filename, 'w')\n",
|
148 |
+
" file.write(data)\n",
|
149 |
+
" file.close()"
|
150 |
+
]
|
151 |
+
},
|
152 |
+
{
|
153 |
+
"cell_type": "code",
|
154 |
+
"execution_count": 388,
|
155 |
+
"id": "ad625117",
|
156 |
+
"metadata": {},
|
157 |
+
"outputs": [
|
158 |
+
{
|
159 |
+
"name": "stdout",
|
160 |
+
"output_type": "stream",
|
161 |
+
"text": [
|
162 |
+
"Loaded: 8092\n"
|
163 |
+
]
|
164 |
+
}
|
165 |
+
],
|
166 |
+
"source": [
|
167 |
+
"filename = \"Flickr8k.token.txt\"\n",
|
168 |
+
"doc = load_doc(filename)\n",
|
169 |
+
"descriptions = load_description(doc)\n",
|
170 |
+
"print(\"Loaded: %d\" %len(descriptions))"
|
171 |
+
]
|
172 |
+
},
|
173 |
+
{
|
174 |
+
"cell_type": "code",
|
175 |
+
"execution_count": 389,
|
176 |
+
"id": "7b06b1b5",
|
177 |
+
"metadata": {},
|
178 |
+
"outputs": [
|
179 |
+
{
|
180 |
+
"name": "stdout",
|
181 |
+
"output_type": "stream",
|
182 |
+
"text": [
|
183 |
+
"Vocab size: 8761\n"
|
184 |
+
]
|
185 |
+
}
|
186 |
+
],
|
187 |
+
"source": [
|
188 |
+
"#clean desc\n",
|
189 |
+
"clean_descriptions(descriptions)\n",
|
190 |
+
"vocab = to_vocabulary(descriptions)\n",
|
191 |
+
"print(\"Vocab size: %d\" %len(vocab))"
|
192 |
+
]
|
193 |
+
},
|
194 |
+
{
|
195 |
+
"cell_type": "code",
|
196 |
+
"execution_count": 390,
|
197 |
+
"id": "c4c867ea",
|
198 |
+
"metadata": {},
|
199 |
+
"outputs": [],
|
200 |
+
"source": [
|
201 |
+
"save_descriptions(descriptions, \"another-way/descriptions1.txt\")"
|
202 |
+
]
|
203 |
+
},
|
204 |
+
{
|
205 |
+
"cell_type": "markdown",
|
206 |
+
"id": "d4079267",
|
207 |
+
"metadata": {},
|
208 |
+
"source": [
|
209 |
+
"### Extract Identifier"
|
210 |
+
]
|
211 |
+
},
|
212 |
+
{
|
213 |
+
"cell_type": "code",
|
214 |
+
"execution_count": 281,
|
215 |
+
"id": "898c84a0",
|
216 |
+
"metadata": {},
|
217 |
+
"outputs": [],
|
218 |
+
"source": [
|
219 |
+
"from pickle import dump"
|
220 |
+
]
|
221 |
+
},
|
222 |
+
{
|
223 |
+
"cell_type": "code",
|
224 |
+
"execution_count": 391,
|
225 |
+
"id": "dd687334",
|
226 |
+
"metadata": {},
|
227 |
+
"outputs": [],
|
228 |
+
"source": [
|
229 |
+
"#load into memory\n",
|
230 |
+
"def load_doc(filename):\n",
|
231 |
+
" with open(filename, 'r') as f:\n",
|
232 |
+
" content = f.read()\n",
|
233 |
+
" return content\n",
|
234 |
+
"#pre-defined list of photo identifier\n",
|
235 |
+
"def load_set(filename):\n",
|
236 |
+
" doc = load_doc(filename)\n",
|
237 |
+
" dataset = list()\n",
|
238 |
+
" for line in doc.split(\"\\n\"):\n",
|
239 |
+
" if len(line) < 1:\n",
|
240 |
+
" continue\n",
|
241 |
+
" identifier = line.split('.')[0]\n",
|
242 |
+
" dataset.append(identifier)\n",
|
243 |
+
" return set(dataset)"
|
244 |
+
]
|
245 |
+
},
|
246 |
+
{
|
247 |
+
"cell_type": "code",
|
248 |
+
"execution_count": 392,
|
249 |
+
"id": "2c612418",
|
250 |
+
"metadata": {},
|
251 |
+
"outputs": [],
|
252 |
+
"source": [
|
253 |
+
"def load_clean_descripitions(filename, dataset):\n",
|
254 |
+
" doc = load_doc(filename)\n",
|
255 |
+
" descriptions = dict()\n",
|
256 |
+
" for line in doc.split('\\n'):\n",
|
257 |
+
" tokens = word_tokenize(line)\n",
|
258 |
+
" image_id, image_desc = tokens[0], tokens[1:]\n",
|
259 |
+
" if image_id in dataset:\n",
|
260 |
+
" if image_id not in descriptions:\n",
|
261 |
+
" descriptions[image_id] = list()\n",
|
262 |
+
" #wrap description in token\n",
|
263 |
+
" desc = 'startseq ' + ' '.join(image_desc) + ' endseq'\n",
|
264 |
+
" descriptions[image_id].append(desc)\n",
|
265 |
+
" return descriptions"
|
266 |
+
]
|
267 |
+
},
|
268 |
+
{
|
269 |
+
"cell_type": "code",
|
270 |
+
"execution_count": 393,
|
271 |
+
"id": "4d22db3e",
|
272 |
+
"metadata": {},
|
273 |
+
"outputs": [],
|
274 |
+
"source": [
|
275 |
+
"def load_photo_features(features, dataset):\n",
|
276 |
+
" all_features = load(open(features, 'rb'))\n",
|
277 |
+
" features = {k: all_features[k] for k in dataset if k in all_features}\n",
|
278 |
+
" return features"
|
279 |
+
]
|
280 |
+
},
|
281 |
+
{
|
282 |
+
"cell_type": "code",
|
283 |
+
"execution_count": 394,
|
284 |
+
"id": "0c3a8e25",
|
285 |
+
"metadata": {},
|
286 |
+
"outputs": [
|
287 |
+
{
|
288 |
+
"name": "stdout",
|
289 |
+
"output_type": "stream",
|
290 |
+
"text": [
|
291 |
+
"dataset: 6000\n",
|
292 |
+
"Descriptions: train=6000\n",
|
293 |
+
"Photos: train=6000\n"
|
294 |
+
]
|
295 |
+
}
|
296 |
+
],
|
297 |
+
"source": [
|
298 |
+
"from pickle import load\n",
|
299 |
+
"\n",
|
300 |
+
"features = \"Flickr_8k.trainImages.txt\"\n",
|
301 |
+
"train = load_set(features)\n",
|
302 |
+
"print(\"dataset: %d\" %len(train))\n",
|
303 |
+
"train_descriptions = load_clean_descripitions(\"descriptions1.txt\", train)\n",
|
304 |
+
"print(\"Descriptions: train=%d\" %len(train_descriptions))\n",
|
305 |
+
"train_features = load_photo_features(\"features.pkl\", train)\n",
|
306 |
+
"print('Photos: train=%d' % len(train_features))"
|
307 |
+
]
|
308 |
+
},
|
309 |
+
{
|
310 |
+
"cell_type": "code",
|
311 |
+
"execution_count": 444,
|
312 |
+
"id": "437278aa",
|
313 |
+
"metadata": {},
|
314 |
+
"outputs": [
|
315 |
+
{
|
316 |
+
"data": {
|
317 |
+
"text/plain": [
|
318 |
+
"{'1191338263_a4fa073154': ['startseq little old lady sitting next to an advertisement endseq',\n",
|
319 |
+
" 'startseq an asian woman waiting at an underground train stop endseq',\n",
|
320 |
+
" 'startseq an old woman sits in transit station next to backlit advertisement endseq',\n",
|
321 |
+
" 'startseq woman sits in subway station endseq',\n",
|
322 |
+
" 'startseq woman with an umbrella is sitting at station with an aquos commercial on the wall endseq'],\n",
|
323 |
+
" '218342358_1755a9cce1': ['startseq cyclist wearing red helmet is riding on the pavement endseq',\n",
|
324 |
+
" 'startseq girl is riding bike on the street while wearing red helmet endseq',\n",
|
325 |
+
" 'startseq person on bike wearing red helmet riding down street endseq',\n",
|
326 |
+
" 'startseq woman wears red helmet and blue shirt as she goes for bike ride in the shade endseq',\n",
|
327 |
+
" 'startseq person in blue shirt and red helmet riding bike down the road endseq'],\n",
|
328 |
+
" '2187222896_c206d63396': ['startseq boy in red shirt in front of long blue wall raises his eyebrow at the camera endseq',\n",
|
329 |
+
" 'startseq boy in red shirt with stripes standing near blue brick wall with handicap signs endseq',\n",
|
330 |
+
" 'startseq an african american boy stands in front of blue building in the handicapped space endseq',\n",
|
331 |
+
" 'startseq the boy in the orange shirt looks backwards endseq',\n",
|
332 |
+
" 'startseq the boy in the red shirt is next to blue wall endseq'],\n",
|
333 |
+
" '2276499757_b44dc6f8ce': ['startseq dog looks warily at the brown dog investigating his area endseq',\n",
|
334 |
+
" 'startseq large brown dog is looking at medium sized black dog endseq',\n",
|
335 |
+
" 'startseq small black dog looks at larger brown dog in grassy field endseq',\n",
|
336 |
+
" 'startseq the big brown dog looks at the small black dog in tall grass endseq',\n",
|
337 |
+
" 'startseq there is big dog looking at little dog endseq'],\n",
|
338 |
+
" '2294598473_40637b5c04': ['startseq dog catches frisbee in midair endseq',\n",
|
339 |
+
" 'startseq dog catching frisbee endseq',\n",
|
340 |
+
" 'startseq terrier mix catches frisbee in the air endseq',\n",
|
341 |
+
" 'startseq white and black dog catching frisbee endseq',\n",
|
342 |
+
" 'startseq white dog is leaping in the air with green object in its mouth endseq'],\n",
|
343 |
+
" '2380765956_6313d8cae3': ['startseq blond girl wearing green jacket walks on trail along side metal fence endseq',\n",
|
344 |
+
" 'startseq girl in green coat walks down rural road playing flute endseq',\n",
|
345 |
+
" 'startseq young girl in parka playing flute while walking by fenced in field endseq',\n",
|
346 |
+
" 'startseq girl in green and blue jacket walking past an enclosed field endseq',\n",
|
347 |
+
" 'startseq girl playing flute as she walks by fence in rural area endseq'],\n",
|
348 |
+
" '2501968935_02f2cd8079': ['startseq man dressed in purple shirt and red bandanna smiles at the people watching him endseq',\n",
|
349 |
+
" 'startseq man on the street wearing leather chaps and chainmail codpiece endseq',\n",
|
350 |
+
" 'startseq man wearing purple shirt and black leather chaps poses for the camera endseq',\n",
|
351 |
+
" 'startseq man dressed in leather chaps and purple shirt stands in front of onlookers endseq',\n",
|
352 |
+
" 'startseq there is man in purple shirt leather chaps and red bandanna standing near other men endseq'],\n",
|
353 |
+
" '2506892928_7e79bec613': ['startseq three children in field with white flowers endseq',\n",
|
354 |
+
" 'startseq three children one with stuffed kitten in field of flowers endseq',\n",
|
355 |
+
" 'startseq three children play in the garden endseq',\n",
|
356 |
+
" 'startseq three children pose among wildflowers endseq',\n",
|
357 |
+
" 'startseq three kids palying with toy cat in garden endseq'],\n",
|
358 |
+
" '2513260012_03d33305cf': ['startseq black dog is running after white dog in the snow endseq',\n",
|
359 |
+
" 'startseq black dog chasing brown dog through snow endseq',\n",
|
360 |
+
" 'startseq two dogs chase each other across the snowy ground endseq',\n",
|
361 |
+
" 'startseq two dogs play together in the snow endseq',\n",
|
362 |
+
" 'startseq two dogs running through low lying body of water endseq'],\n",
|
363 |
+
" '2638369467_8fc251595b': ['startseq girl in white dress endseq',\n",
|
364 |
+
" 'startseq little girl in white is looking back at the camera while carrying water grenade endseq',\n",
|
365 |
+
" 'startseq smiling young girl in braids is playing ball endseq',\n",
|
366 |
+
" 'startseq young girl wearing white looks at the camera as she plays endseq',\n",
|
367 |
+
" 'startseq the girl is holding green ball endseq'],\n",
|
368 |
+
" '2644326817_8f45080b87': ['startseq black and white dog with red frisbee standing on sandy beach endseq',\n",
|
369 |
+
" 'startseq dog drops red disc on beach endseq',\n",
|
370 |
+
" 'startseq dog with red frisbee flying in the air endseq',\n",
|
371 |
+
" 'startseq dog catching red frisbee endseq',\n",
|
372 |
+
" 'startseq the black dog is dropping red disc on beach endseq'],\n",
|
373 |
+
" '2699342860_5288e203ea': ['startseq boy wearing red tshirt is running through woodland endseq',\n",
|
374 |
+
" 'startseq child runs near some trees endseq',\n",
|
375 |
+
" 'startseq young boy is dancing around endseq',\n",
|
376 |
+
" 'startseq young boy with red short sleeved shirt and jeans runs by some trees endseq',\n",
|
377 |
+
" 'startseq the little boy in the red shirt stops to smile for the camera endseq'],\n",
|
378 |
+
" '2851304910_b5721199bc': ['startseq photographer looks over the hills endseq',\n",
|
379 |
+
" 'startseq woman in red jacket is videotaping natural landscape endseq',\n",
|
380 |
+
" 'startseq woman with camera looks out over rolling hills endseq',\n",
|
381 |
+
" 'startseq woman with camera on tripod is looking at the view endseq',\n",
|
382 |
+
" 'startseq lady in red shirt has her camera set up in the field to record something endseq'],\n",
|
383 |
+
" '2903617548_d3e38d7f88': ['startseq little baby plays croquet endseq',\n",
|
384 |
+
" 'startseq little girl plays croquet next to truck endseq',\n",
|
385 |
+
" 'startseq the child is playing croquette by the truck endseq',\n",
|
386 |
+
" 'startseq the kid is in front of car with put and ball endseq',\n",
|
387 |
+
" 'startseq the little boy is playing with croquet hammer and ball beside the car endseq'],\n",
|
388 |
+
" '2926786902_815a99a154': ['startseq skier in yellow jacket is airborne above the mountains endseq',\n",
|
389 |
+
" 'startseq skier jumps high in the air with view of the mountains endseq',\n",
|
390 |
+
" 'startseq skiing man in fluorescent jacket jumps very high and it looks as though he is flying endseq',\n",
|
391 |
+
" 'startseq somone is high in the air doing ski jump endseq',\n",
|
392 |
+
" 'startseq the skier in the green jacket and white pants appears to almost fly into the sky endseq'],\n",
|
393 |
+
" '3119887967_271a097464': ['startseq man in sweater pointing at the camera endseq',\n",
|
394 |
+
" 'startseq one man is posing with arms outstretched and finger pointed while another stares from behind him endseq',\n",
|
395 |
+
" 'startseq the man in the black hat stands behind the man who is pointing his finger endseq',\n",
|
396 |
+
" 'startseq two men look toward the camera while the one in front points his index finger endseq',\n",
|
397 |
+
" 'startseq two men one wearing black hat while the one in front points standing in hallway endseq'],\n",
|
398 |
+
" '3197891333_b1b0fd1702': ['startseq family of nine people including four children pose in front of brick fireplace with white mantle endseq',\n",
|
399 |
+
" 'startseq family poses in front of the fireplace and christmas tree endseq',\n",
|
400 |
+
" 'startseq family posing by the mantle and christmas tree endseq',\n",
|
401 |
+
" 'startseq happy family poses by the fireplace endseq',\n",
|
402 |
+
" 'startseq two couples and four kids pose for family picture endseq'],\n",
|
403 |
+
" '3338291921_fe7ae0c8f8': ['startseq brown dog in the snow has something hot pink in its mouth endseq',\n",
|
404 |
+
" 'startseq brown dog in the snow holding pink hat endseq',\n",
|
405 |
+
" 'startseq brown dog is holding pink shirt in the snow endseq',\n",
|
406 |
+
" 'startseq dog is carrying something pink in its mouth while walking through the snow endseq',\n",
|
407 |
+
" 'startseq dog with something pink in its mouth is looking forward endseq'],\n",
|
408 |
+
" '3356369156_074750c6cc': ['startseq blue boat with yellow canopy is floating on calm waters endseq',\n",
|
409 |
+
" 'startseq boat in the water endseq',\n",
|
410 |
+
" 'startseq boat with roof on green water endseq',\n",
|
411 |
+
" 'startseq the boat is in the middle of the water endseq',\n",
|
412 |
+
" 'startseq the solitude boat floats on the lake endseq'],\n",
|
413 |
+
" '3423802527_94bd2b23b0': ['startseq bunch of girls in cheerleader outfits endseq',\n",
|
414 |
+
" 'startseq large group of cheerleaders walking in parade endseq',\n",
|
415 |
+
" 'startseq cheerleaders perform endseq',\n",
|
416 |
+
" 'startseq many cheerleaders wearing black walk down the street endseq',\n",
|
417 |
+
" 'startseq parade of cheerleaders wearing black pink and white uniforms endseq'],\n",
|
418 |
+
" '488416045_1c6d903fe0': ['startseq brown dog is running along beach endseq',\n",
|
419 |
+
" 'startseq brown dog wearing black collar running across the beach endseq',\n",
|
420 |
+
" 'startseq dog walks on the sand near the water endseq',\n",
|
421 |
+
" 'startseq brown dog running on the beach endseq',\n",
|
422 |
+
" 'startseq the large brown dog is running on the beach by the ocean endseq']}"
|
423 |
+
]
|
424 |
+
},
|
425 |
+
"execution_count": 444,
|
426 |
+
"metadata": {},
|
427 |
+
"output_type": "execute_result"
|
428 |
+
}
|
429 |
+
],
|
430 |
+
"source": [
|
431 |
+
"train_descriptions"
|
432 |
+
]
|
433 |
+
},
|
434 |
+
{
|
435 |
+
"cell_type": "markdown",
|
436 |
+
"id": "b80bb437",
|
437 |
+
"metadata": {},
|
438 |
+
"source": [
|
439 |
+
"### Now going to use keras tokenizer to change text to numeric form"
|
440 |
+
]
|
441 |
+
},
|
442 |
+
{
|
443 |
+
"cell_type": "code",
|
444 |
+
"execution_count": 396,
|
445 |
+
"id": "c7e2130c",
|
446 |
+
"metadata": {},
|
447 |
+
"outputs": [],
|
448 |
+
"source": [
|
449 |
+
"# dict to clean list\n",
|
450 |
+
"def to_lines(descriptions):\n",
|
451 |
+
" all_desc = list()\n",
|
452 |
+
" for key in descriptions.keys():\n",
|
453 |
+
" [all_desc.append(d) for d in descriptions[key]]\n",
|
454 |
+
" return all_desc"
|
455 |
+
]
|
456 |
+
},
|
457 |
+
{
|
458 |
+
"cell_type": "code",
|
459 |
+
"execution_count": 397,
|
460 |
+
"id": "a91092cf",
|
461 |
+
"metadata": {},
|
462 |
+
"outputs": [],
|
463 |
+
"source": [
|
464 |
+
"def create_tokenizer(descriptions):\n",
|
465 |
+
" lines = to_lines(descriptions)\n",
|
466 |
+
" tokenizer = Tokenizer()\n",
|
467 |
+
" tokenizer.fit_on_texts(lines)\n",
|
468 |
+
" return tokenizer"
|
469 |
+
]
|
470 |
+
},
|
471 |
+
{
|
472 |
+
"cell_type": "code",
|
473 |
+
"execution_count": 398,
|
474 |
+
"id": "69996870",
|
475 |
+
"metadata": {},
|
476 |
+
"outputs": [
|
477 |
+
{
|
478 |
+
"name": "stdout",
|
479 |
+
"output_type": "stream",
|
480 |
+
"text": [
|
481 |
+
"Vocabulary Size: 7577\n"
|
482 |
+
]
|
483 |
+
}
|
484 |
+
],
|
485 |
+
"source": [
|
486 |
+
"tokenizer = create_tokenizer(train_descriptions)\n",
|
487 |
+
"vocab_size = len(tokenizer.word_index) + 1\n",
|
488 |
+
"print('Vocabulary Size: %d' % vocab_size)"
|
489 |
+
]
|
490 |
+
},
|
491 |
+
{
|
492 |
+
"cell_type": "code",
|
493 |
+
"execution_count": 399,
|
494 |
+
"id": "9f0b5246",
|
495 |
+
"metadata": {},
|
496 |
+
"outputs": [],
|
497 |
+
"source": [
|
498 |
+
"#len of description\n",
|
499 |
+
"def max_length(description):\n",
|
500 |
+
" lines = to_lines(description)\n",
|
501 |
+
" return max(len(d.split()) for d in lines)"
|
502 |
+
]
|
503 |
+
},
|
504 |
+
{
|
505 |
+
"cell_type": "code",
|
506 |
+
"execution_count": 462,
|
507 |
+
"id": "191d71d6",
|
508 |
+
"metadata": {},
|
509 |
+
"outputs": [],
|
510 |
+
"source": [
|
511 |
+
"# create input and output sequence\n",
|
512 |
+
"def create_sequences(tokenizer, max_length, desc_list, photo):\n",
|
513 |
+
" X1, X2, y = list(), list(), list()\n",
|
514 |
+
" # walk through each description for the image\n",
|
515 |
+
" for desc in desc_list:\n",
|
516 |
+
" # encode the sequence\n",
|
517 |
+
" seq = tokenizer.texts_to_sequences([desc])[0]\n",
|
518 |
+
" # split one sequence into multiple X,y pairs\n",
|
519 |
+
" for i in range(1, len(seq)):\n",
|
520 |
+
" # split into input and output pair\n",
|
521 |
+
" in_seq, out_seq = seq[:i], seq[i]\n",
|
522 |
+
" # pad input sequence\n",
|
523 |
+
" in_seq = pad_sequences([in_seq], maxlen=max_length)[0]\n",
|
524 |
+
" # encode output sequence\n",
|
525 |
+
" out_seq = to_categorical([out_seq], num_classes=vocab_size)[0]\n",
|
526 |
+
" # store\n",
|
527 |
+
" X1.append(photo)\n",
|
528 |
+
" X2.append(in_seq)\n",
|
529 |
+
" y.append(out_seq)\n",
|
530 |
+
" return array(X1), array(X2), array(y)"
|
531 |
+
]
|
532 |
+
},
|
533 |
+
{
|
534 |
+
"cell_type": "code",
|
535 |
+
"execution_count": 401,
|
536 |
+
"id": "4e3e04fa",
|
537 |
+
"metadata": {},
|
538 |
+
"outputs": [],
|
539 |
+
"source": [
|
540 |
+
"from numpy import array\n",
|
541 |
+
"from tensorflow.keras.preprocessing.text import Tokenizer\n",
|
542 |
+
"from tensorflow.keras.preprocessing.sequence import pad_sequences\n",
|
543 |
+
"from tensorflow.keras.utils import to_categorical, plot_model\n",
|
544 |
+
"from keras.models import Model\n",
|
545 |
+
"from keras.layers import Input, Dense, Activation, Dropout, Embedding,LSTM, Bidirectional, BatchNormalization\n",
|
546 |
+
"from keras.layers.merging import add\n",
|
547 |
+
"from keras.callbacks import ModelCheckpoint"
|
548 |
+
]
|
549 |
+
},
|
550 |
+
{
|
551 |
+
"cell_type": "markdown",
|
552 |
+
"id": "45c2cfe9",
|
553 |
+
"metadata": {},
|
554 |
+
"source": [
|
555 |
+
"### Model creation"
|
556 |
+
]
|
557 |
+
},
|
558 |
+
{
|
559 |
+
"cell_type": "code",
|
560 |
+
"execution_count": null,
|
561 |
+
"id": "93f8f578",
|
562 |
+
"metadata": {},
|
563 |
+
"outputs": [],
|
564 |
+
"source": []
|
565 |
+
},
|
566 |
+
{
|
567 |
+
"cell_type": "code",
|
568 |
+
"execution_count": 467,
|
569 |
+
"id": "22c7799b",
|
570 |
+
"metadata": {},
|
571 |
+
"outputs": [],
|
572 |
+
"source": [
|
573 |
+
"def define_model(vocab_size, max_length):\n",
|
574 |
+
" # feature extractor model\n",
|
575 |
+
" inputs1 = Input(shape=(1000,))\n",
|
576 |
+
" fe1 = Dropout(0.5)(inputs1)\n",
|
577 |
+
" fe2 = Dense(256, activation='relu')(fe1)\n",
|
578 |
+
" # sequence model\n",
|
579 |
+
" inputs2 = Input(shape=(max_length,))\n",
|
580 |
+
" se1 = Embedding(vocab_size,output_dim=256, mask_zero=True)(inputs2)\n",
|
581 |
+
" se2 = Dropout(0.5)(se1)\n",
|
582 |
+
" se3 = LSTM(256)(se2)\n",
|
583 |
+
" # decoder model\n",
|
584 |
+
" decoder1 = concatenate([fe2, se3])\n",
|
585 |
+
" decoder2 = Dense(256, activation='relu')(decoder1)\n",
|
586 |
+
" outputs = Dense(vocab_size, activation='softmax')(decoder2)\n",
|
587 |
+
" # tie it together [image, seq] [word]\n",
|
588 |
+
" model = Model(inputs=[inputs1, inputs2], outputs=outputs)\n",
|
589 |
+
" model.compile(loss='categorical_crossentropy', optimizer='adam')\n",
|
590 |
+
" # summarize model\n",
|
591 |
+
" print(model.summary())\n",
|
592 |
+
" return model"
|
593 |
+
]
|
594 |
+
},
|
595 |
+
{
|
596 |
+
"cell_type": "code",
|
597 |
+
"execution_count": 463,
|
598 |
+
"id": "6ad11b1d",
|
599 |
+
"metadata": {},
|
600 |
+
"outputs": [],
|
601 |
+
"source": [
|
602 |
+
"# load batch of data\n",
|
603 |
+
"def data_generator(descriptions, photos, tokenizer, max_length):\n",
|
604 |
+
" # loop for ever over images\n",
|
605 |
+
" while 1:\n",
|
606 |
+
" for key, desc_list in descriptions.items():\n",
|
607 |
+
" # retrieve the photo feature\n",
|
608 |
+
" photo = photos[key][0]\n",
|
609 |
+
" in_img, in_seq, out_word = create_sequences(tokenizer, max_length, desc_list, photo)\n",
|
610 |
+
" yield [[in_img, in_seq], out_word]"
|
611 |
+
]
|
612 |
+
},
|
613 |
+
{
|
614 |
+
"cell_type": "code",
|
615 |
+
"execution_count": 464,
|
616 |
+
"id": "a999a0db",
|
617 |
+
"metadata": {},
|
618 |
+
"outputs": [
|
619 |
+
{
|
620 |
+
"name": "stdout",
|
621 |
+
"output_type": "stream",
|
622 |
+
"text": [
|
623 |
+
"Dataset: 6000\n",
|
624 |
+
"train_descriptions= 6000\n",
|
625 |
+
"photos: train= 6000\n",
|
626 |
+
"Vocab size: 7577\n",
|
627 |
+
"Description Length: 34\n"
|
628 |
+
]
|
629 |
+
}
|
630 |
+
],
|
631 |
+
"source": [
|
632 |
+
"#load train dataset\n",
|
633 |
+
"import tensorflow as tf\n",
|
634 |
+
"filename = \"Flickr_8k.trainImages.txt\"\n",
|
635 |
+
"train = load_set(filename)\n",
|
636 |
+
"print(\"Dataset: %d\" %len(train))\n",
|
637 |
+
"\n",
|
638 |
+
"train_descriptions = load_clean_descripitions(\"descriptions1.txt\", train)\n",
|
639 |
+
"print(\"train_descriptions= %d\" %len(train_descriptions))\n",
|
640 |
+
"\n",
|
641 |
+
"train_feature = load_photo_features(\"features.pkl\", train)\n",
|
642 |
+
"print(\"photos: train= %d\" %len(train_feature))\n",
|
643 |
+
"\n",
|
644 |
+
"tokenizer = create_tokenizer(train_descriptions)\n",
|
645 |
+
"vocab_size = len(tokenizer.word_index)+1\n",
|
646 |
+
"print(\"Vocab size: %d\" %vocab_size)\n",
|
647 |
+
"\n",
|
648 |
+
"max_len = max_length(train_descriptions)\n",
|
649 |
+
"print('Description Length: %d' % max_len)"
|
650 |
+
]
|
651 |
+
},
|
652 |
+
{
|
653 |
+
"cell_type": "code",
|
654 |
+
"execution_count": 468,
|
655 |
+
"id": "9936fc7f",
|
656 |
+
"metadata": {
|
657 |
+
"scrolled": false
|
658 |
+
},
|
659 |
+
"outputs": [
|
660 |
+
{
|
661 |
+
"name": "stdout",
|
662 |
+
"output_type": "stream",
|
663 |
+
"text": [
|
664 |
+
"Model: \"model_47\"\n",
|
665 |
+
"__________________________________________________________________________________________________\n",
|
666 |
+
" Layer (type) Output Shape Param # Connected to \n",
|
667 |
+
"==================================================================================================\n",
|
668 |
+
" input_121 (InputLayer) [(None, 34)] 0 [] \n",
|
669 |
+
" \n",
|
670 |
+
" input_120 (InputLayer) [(None, 1000)] 0 [] \n",
|
671 |
+
" \n",
|
672 |
+
" embedding_52 (Embedding) (None, 34, 256) 1939712 ['input_121[0][0]'] \n",
|
673 |
+
" \n",
|
674 |
+
" dropout_109 (Dropout) (None, 1000) 0 ['input_120[0][0]'] \n",
|
675 |
+
" \n",
|
676 |
+
" dropout_110 (Dropout) (None, 34, 256) 0 ['embedding_52[0][0]'] \n",
|
677 |
+
" \n",
|
678 |
+
" dense_151 (Dense) (None, 256) 256256 ['dropout_109[0][0]'] \n",
|
679 |
+
" \n",
|
680 |
+
" lstm_52 (LSTM) (None, 256) 525312 ['dropout_110[0][0]'] \n",
|
681 |
+
" \n",
|
682 |
+
" concatenate_8 (Concatenate) (None, 512) 0 ['dense_151[0][0]', \n",
|
683 |
+
" 'lstm_52[0][0]'] \n",
|
684 |
+
" \n",
|
685 |
+
" dense_152 (Dense) (None, 256) 131328 ['concatenate_8[0][0]'] \n",
|
686 |
+
" \n",
|
687 |
+
" dense_153 (Dense) (None, 7577) 1947289 ['dense_152[0][0]'] \n",
|
688 |
+
" \n",
|
689 |
+
"==================================================================================================\n",
|
690 |
+
"Total params: 4,799,897\n",
|
691 |
+
"Trainable params: 4,799,897\n",
|
692 |
+
"Non-trainable params: 0\n",
|
693 |
+
"__________________________________________________________________________________________________\n",
|
694 |
+
"None\n"
|
695 |
+
]
|
696 |
+
}
|
697 |
+
],
|
698 |
+
"source": [
|
699 |
+
"#train model\n",
|
700 |
+
"model = define_model(vocab_size, max_len)\n",
|
701 |
+
"epochs = 10\n",
|
702 |
+
"steps = len(train_descriptions)"
|
703 |
+
]
|
704 |
+
},
|
705 |
+
{
|
706 |
+
"cell_type": "code",
|
707 |
+
"execution_count": 469,
|
708 |
+
"id": "6d10533f",
|
709 |
+
"metadata": {},
|
710 |
+
"outputs": [
|
711 |
+
{
|
712 |
+
"name": "stdout",
|
713 |
+
"output_type": "stream",
|
714 |
+
"text": [
|
715 |
+
" 514/6000 [=>............................] - ETA: 25:52 - loss: 5.8238"
|
716 |
+
]
|
717 |
+
},
|
718 |
+
{
|
719 |
+
"ename": "KeyboardInterrupt",
|
720 |
+
"evalue": "",
|
721 |
+
"output_type": "error",
|
722 |
+
"traceback": [
|
723 |
+
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
724 |
+
"\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
|
725 |
+
"Cell \u001b[1;32mIn[469], line 4\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(epochs):\n\u001b[0;32m 2\u001b[0m \u001b[38;5;66;03m#create data generator\u001b[39;00m\n\u001b[0;32m 3\u001b[0m generator \u001b[38;5;241m=\u001b[39m data_generator(train_descriptions, train_feature, tokenizer, max_len)\n\u001b[1;32m----> 4\u001b[0m \u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mgenerator\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mepochs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msteps_per_epoch\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[43msteps\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mverbose\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[0;32m 5\u001b[0m model\u001b[38;5;241m.\u001b[39msave(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmodel_\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mstr\u001b[39m(i) \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mh5\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n",
|
726 |
+
"File \u001b[1;32m~\\miniconda3\\lib\\site-packages\\keras\\utils\\traceback_utils.py:65\u001b[0m, in \u001b[0;36mfilter_traceback.<locals>.error_handler\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 63\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 64\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m---> 65\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m fn(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m 66\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m 67\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n",
|
727 |
+
"File \u001b[1;32m~\\miniconda3\\lib\\site-packages\\keras\\engine\\training.py:1685\u001b[0m, in \u001b[0;36mModel.fit\u001b[1;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq, max_queue_size, workers, use_multiprocessing)\u001b[0m\n\u001b[0;32m 1677\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m tf\u001b[38;5;241m.\u001b[39mprofiler\u001b[38;5;241m.\u001b[39mexperimental\u001b[38;5;241m.\u001b[39mTrace(\n\u001b[0;32m 1678\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtrain\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m 1679\u001b[0m epoch_num\u001b[38;5;241m=\u001b[39mepoch,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 1682\u001b[0m _r\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m,\n\u001b[0;32m 1683\u001b[0m ):\n\u001b[0;32m 1684\u001b[0m callbacks\u001b[38;5;241m.\u001b[39mon_train_batch_begin(step)\n\u001b[1;32m-> 1685\u001b[0m tmp_logs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtrain_function\u001b[49m\u001b[43m(\u001b[49m\u001b[43miterator\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1686\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m data_handler\u001b[38;5;241m.\u001b[39mshould_sync:\n\u001b[0;32m 1687\u001b[0m context\u001b[38;5;241m.\u001b[39masync_wait()\n",
|
728 |
+
"File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\tensorflow\\python\\util\\traceback_utils.py:150\u001b[0m, in \u001b[0;36mfilter_traceback.<locals>.error_handler\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 148\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 149\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 150\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m fn(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m 151\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m 152\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n",
|
729 |
+
"File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\polymorphic_function.py:894\u001b[0m, in \u001b[0;36mFunction.__call__\u001b[1;34m(self, *args, **kwds)\u001b[0m\n\u001b[0;32m 891\u001b[0m compiler \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mxla\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_jit_compile \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnonXla\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 893\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m OptionalXlaContext(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_jit_compile):\n\u001b[1;32m--> 894\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwds)\n\u001b[0;32m 896\u001b[0m new_tracing_count \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexperimental_get_tracing_count()\n\u001b[0;32m 897\u001b[0m without_tracing \u001b[38;5;241m=\u001b[39m (tracing_count \u001b[38;5;241m==\u001b[39m new_tracing_count)\n",
|
730 |
+
"File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\polymorphic_function.py:926\u001b[0m, in \u001b[0;36mFunction._call\u001b[1;34m(self, *args, **kwds)\u001b[0m\n\u001b[0;32m 923\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_lock\u001b[38;5;241m.\u001b[39mrelease()\n\u001b[0;32m 924\u001b[0m \u001b[38;5;66;03m# In this case we have created variables on the first call, so we run the\u001b[39;00m\n\u001b[0;32m 925\u001b[0m \u001b[38;5;66;03m# defunned version which is guaranteed to never create variables.\u001b[39;00m\n\u001b[1;32m--> 926\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_no_variable_creation_fn(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwds) \u001b[38;5;66;03m# pylint: disable=not-callable\u001b[39;00m\n\u001b[0;32m 927\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_variable_creation_fn \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m 928\u001b[0m \u001b[38;5;66;03m# Release the lock early so that multiple threads can perform the call\u001b[39;00m\n\u001b[0;32m 929\u001b[0m \u001b[38;5;66;03m# in parallel.\u001b[39;00m\n\u001b[0;32m 930\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_lock\u001b[38;5;241m.\u001b[39mrelease()\n",
|
731 |
+
"File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\tracing_compiler.py:143\u001b[0m, in \u001b[0;36mTracingCompiler.__call__\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 140\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_lock:\n\u001b[0;32m 141\u001b[0m (concrete_function,\n\u001b[0;32m 142\u001b[0m filtered_flat_args) \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_maybe_define_function(args, kwargs)\n\u001b[1;32m--> 143\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mconcrete_function\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_flat\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 144\u001b[0m \u001b[43m \u001b[49m\u001b[43mfiltered_flat_args\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcaptured_inputs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mconcrete_function\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcaptured_inputs\u001b[49m\u001b[43m)\u001b[49m\n",
|
732 |
+
"File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\monomorphic_function.py:1757\u001b[0m, in \u001b[0;36mConcreteFunction._call_flat\u001b[1;34m(self, args, captured_inputs, cancellation_manager)\u001b[0m\n\u001b[0;32m 1753\u001b[0m possible_gradient_type \u001b[38;5;241m=\u001b[39m gradients_util\u001b[38;5;241m.\u001b[39mPossibleTapeGradientTypes(args)\n\u001b[0;32m 1754\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (possible_gradient_type \u001b[38;5;241m==\u001b[39m gradients_util\u001b[38;5;241m.\u001b[39mPOSSIBLE_GRADIENT_TYPES_NONE\n\u001b[0;32m 1755\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m executing_eagerly):\n\u001b[0;32m 1756\u001b[0m \u001b[38;5;66;03m# No tape is watching; skip to running the function.\u001b[39;00m\n\u001b[1;32m-> 1757\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_build_call_outputs(\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_inference_function\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcall\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 1758\u001b[0m \u001b[43m \u001b[49m\u001b[43mctx\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcancellation_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcancellation_manager\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[0;32m 1759\u001b[0m forward_backward \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_select_forward_and_backward_functions(\n\u001b[0;32m 1760\u001b[0m args,\n\u001b[0;32m 1761\u001b[0m possible_gradient_type,\n\u001b[0;32m 1762\u001b[0m executing_eagerly)\n\u001b[0;32m 1763\u001b[0m forward_function, args_with_tangents \u001b[38;5;241m=\u001b[39m forward_backward\u001b[38;5;241m.\u001b[39mforward()\n",
|
733 |
+
"File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\tensorflow\\python\\eager\\polymorphic_function\\monomorphic_function.py:381\u001b[0m, in \u001b[0;36m_EagerDefinedFunction.call\u001b[1;34m(self, ctx, args, cancellation_manager)\u001b[0m\n\u001b[0;32m 379\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m _InterpolateFunctionError(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m 380\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m cancellation_manager \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m--> 381\u001b[0m outputs \u001b[38;5;241m=\u001b[39m \u001b[43mexecute\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mexecute\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 382\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msignature\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mname\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 383\u001b[0m \u001b[43m \u001b[49m\u001b[43mnum_outputs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_num_outputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 384\u001b[0m \u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 385\u001b[0m \u001b[43m \u001b[49m\u001b[43mattrs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mattrs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 386\u001b[0m \u001b[43m \u001b[49m\u001b[43mctx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mctx\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 387\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 388\u001b[0m outputs \u001b[38;5;241m=\u001b[39m execute\u001b[38;5;241m.\u001b[39mexecute_with_cancellation(\n\u001b[0;32m 389\u001b[0m \u001b[38;5;28mstr\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msignature\u001b[38;5;241m.\u001b[39mname),\n\u001b[0;32m 390\u001b[0m num_outputs\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_outputs,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 393\u001b[0m ctx\u001b[38;5;241m=\u001b[39mctx,\n\u001b[0;32m 394\u001b[0m cancellation_manager\u001b[38;5;241m=\u001b[39mcancellation_manager)\n",
|
734 |
+
"File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\tensorflow\\python\\eager\\execute.py:52\u001b[0m, in \u001b[0;36mquick_execute\u001b[1;34m(op_name, num_outputs, inputs, attrs, ctx, name)\u001b[0m\n\u001b[0;32m 50\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m 51\u001b[0m ctx\u001b[38;5;241m.\u001b[39mensure_initialized()\n\u001b[1;32m---> 52\u001b[0m tensors \u001b[38;5;241m=\u001b[39m \u001b[43mpywrap_tfe\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mTFE_Py_Execute\u001b[49m\u001b[43m(\u001b[49m\u001b[43mctx\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_handle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdevice_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mop_name\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 53\u001b[0m \u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mattrs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnum_outputs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 54\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m core\u001b[38;5;241m.\u001b[39m_NotOkStatusException \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m 55\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m name \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
|
735 |
+
"\u001b[1;31mKeyboardInterrupt\u001b[0m: "
|
736 |
+
]
|
737 |
+
}
|
738 |
+
],
|
739 |
+
"source": [
|
740 |
+
"for i in range(epochs):\n",
|
741 |
+
" #create data generator\n",
|
742 |
+
" generator = data_generator(train_descriptions, train_feature, tokenizer, max_len)\n",
|
743 |
+
" model.fit(generator, epochs=1, steps_per_epoch = steps, verbose=1)\n",
|
744 |
+
" model.save(\"model_\" + str(i) + \"h5\")"
|
745 |
+
]
|
746 |
+
},
|
747 |
+
{
|
748 |
+
"cell_type": "code",
|
749 |
+
"execution_count": null,
|
750 |
+
"id": "f4867e1b",
|
751 |
+
"metadata": {},
|
752 |
+
"outputs": [],
|
753 |
+
"source": [
|
754 |
+
"# from tensorflow.keras.callbacks import ModelCheckpoint\n",
|
755 |
+
"\n",
|
756 |
+
"# # Define the number of epochs and steps\n",
|
757 |
+
"# epochs = 10\n",
|
758 |
+
"# steps_per_epoch = len(train_descriptions)\n",
|
759 |
+
"\n",
|
760 |
+
"# # Create a data generator\n",
|
761 |
+
"# generator = data_generator(train_descriptions, train_feature, tokenizer, max_len)\n",
|
762 |
+
"\n",
|
763 |
+
"# # Define a checkpoint callback to save the model after each epoch\n",
|
764 |
+
"# checkpoint = ModelCheckpoint(filepath=\"model_{epoch}.h5\", save_weights_only=False, save_format=\"h5\")\n",
|
765 |
+
"\n",
|
766 |
+
"# # Train the model for the specified number of epochs\n",
|
767 |
+
"# model.fit(generator, epochs=epochs, steps_per_epoch=steps_per_epoch, verbose=1, callbacks=[checkpoint])"
|
768 |
+
]
|
769 |
+
},
|
770 |
+
{
|
771 |
+
"cell_type": "code",
|
772 |
+
"execution_count": 2,
|
773 |
+
"id": "3a998776",
|
774 |
+
"metadata": {},
|
775 |
+
"outputs": [],
|
776 |
+
"source": [
|
777 |
+
"def word_for_id(interger, tokenizer):\n",
|
778 |
+
" for word, index in tokenizer.word_index.items():\n",
|
779 |
+
" if index==interger:\n",
|
780 |
+
" return word\n",
|
781 |
+
" return None\n",
|
782 |
+
"def generate_desc(model, tokenizer, photo, max_len):\n",
|
783 |
+
" in_text = \"start_seq\"\n",
|
784 |
+
" for i in range(max_len):\n",
|
785 |
+
" sequence = tokenizer.texts_to_sequences([in_text])[0]\n",
|
786 |
+
" sequence = pad_sequence([sequence], maxlen = max_len)\n",
|
787 |
+
" yhat = model.predict([photo, sequence], verbose=1)\n",
|
788 |
+
" yhat = argmax(yhat)\n",
|
789 |
+
" word = word_for_id(yhat, tokenizer)\n",
|
790 |
+
" if word is None:\n",
|
791 |
+
" break\n",
|
792 |
+
" in_text += ' '+word\n",
|
793 |
+
" if word=='endseq':\n",
|
794 |
+
" break\n",
|
795 |
+
" return in_text"
|
796 |
+
]
|
797 |
+
},
|
798 |
+
{
|
799 |
+
"cell_type": "code",
|
800 |
+
"execution_count": 3,
|
801 |
+
"id": "9f7dfb85",
|
802 |
+
"metadata": {},
|
803 |
+
"outputs": [
|
804 |
+
{
|
805 |
+
"ename": "NameError",
|
806 |
+
"evalue": "name 'corpus_bleu' is not defined",
|
807 |
+
"output_type": "error",
|
808 |
+
"traceback": [
|
809 |
+
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
810 |
+
"\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",
|
811 |
+
"Cell \u001b[1;32mIn[3], line 8\u001b[0m\n\u001b[0;32m 6\u001b[0m references \u001b[38;5;241m=\u001b[39m [d\u001b[38;5;241m.\u001b[39msplit() \u001b[38;5;28;01mfor\u001b[39;00m d \u001b[38;5;129;01min\u001b[39;00m desc_list]\n\u001b[0;32m 7\u001b[0m actual\u001b[38;5;241m.\u001b[39mappend(yhat\u001b[38;5;241m.\u001b[39msplit())\n\u001b[1;32m----> 8\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mBLUE-1: \u001b[39m\u001b[38;5;132;01m%f\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m\u001b[43mcorpus_bleu\u001b[49m(actual, predicted, weights\u001b[38;5;241m=\u001b[39m(\u001b[38;5;241m1.0\u001b[39m,\u001b[38;5;241m0\u001b[39m,\u001b[38;5;241m0\u001b[39m,\u001b[38;5;241m0\u001b[39m)))\n\u001b[0;32m 9\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mBLUE-2: \u001b[39m\u001b[38;5;132;01m%f\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39mcorpus_bleu(actual, predicted, weights\u001b[38;5;241m=\u001b[39m(\u001b[38;5;241m0.5\u001b[39m,\u001b[38;5;241m0.5\u001b[39m,\u001b[38;5;241m0\u001b[39m,\u001b[38;5;241m0\u001b[39m)))\n\u001b[0;32m 10\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mBLUE-3: \u001b[39m\u001b[38;5;132;01m%f\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39mcorpus_bleu(actual, predicted, weights\u001b[38;5;241m=\u001b[39m(\u001b[38;5;241m0.3\u001b[39m,\u001b[38;5;241m0.3\u001b[39m,\u001b[38;5;241m0.3\u001b[39m,\u001b[38;5;241m0\u001b[39m)))\n",
|
812 |
+
"\u001b[1;31mNameError\u001b[0m: name 'corpus_bleu' is not defined"
|
813 |
+
]
|
814 |
+
}
|
815 |
+
],
|
816 |
+
"source": [
|
817 |
+
"# evaluated the skill of model\n",
|
818 |
+
"def evaluate_model(model, description, photos, tokenizer, max_length):\n",
|
819 |
+
" actual, predicted = list(), list()\n",
|
820 |
+
" for key, desc_list in description.items():\n",
|
821 |
+
" yhat = generate_desc(model, tokenizer, photos[key], max_length)\n",
|
822 |
+
" references = [d.split() for d in desc_list]\n",
|
823 |
+
" actual.append(yhat.split())\n",
|
824 |
+
" predicted.append(yhat.split())\n",
|
825 |
+
"print(\"BLUE-1: %f\" %corpus_bleu(actual, predicted, weights=(1.0,0,0,0)))\n",
|
826 |
+
"print(\"BLUE-2: %f\" %corpus_bleu(actual, predicted, weights=(0.5,0.5,0,0)))\n",
|
827 |
+
"print(\"BLUE-3: %f\" %corpus_bleu(actual, predicted, weights=(0.3,0.3,0.3,0)))\n",
|
828 |
+
"print(\"BLUE-4: %f\" %corpus_bleu(actual, predicted, weights=(0.25,0.25,0.25,0.25)))"
|
829 |
+
]
|
830 |
+
},
|
831 |
+
{
|
832 |
+
"cell_type": "code",
|
833 |
+
"execution_count": null,
|
834 |
+
"id": "d5a1cd9c",
|
835 |
+
"metadata": {},
|
836 |
+
"outputs": [],
|
837 |
+
"source": []
|
838 |
+
},
|
839 |
+
{
|
840 |
+
"cell_type": "code",
|
841 |
+
"execution_count": null,
|
842 |
+
"id": "c1509cb1",
|
843 |
+
"metadata": {},
|
844 |
+
"outputs": [],
|
845 |
+
"source": []
|
846 |
+
}
|
847 |
+
],
|
848 |
+
"metadata": {
|
849 |
+
"kernelspec": {
|
850 |
+
"display_name": "Python 3 (ipykernel)",
|
851 |
+
"language": "python",
|
852 |
+
"name": "python3"
|
853 |
+
},
|
854 |
+
"language_info": {
|
855 |
+
"codemirror_mode": {
|
856 |
+
"name": "ipython",
|
857 |
+
"version": 3
|
858 |
+
},
|
859 |
+
"file_extension": ".py",
|
860 |
+
"mimetype": "text/x-python",
|
861 |
+
"name": "python",
|
862 |
+
"nbconvert_exporter": "python",
|
863 |
+
"pygments_lexer": "ipython3",
|
864 |
+
"version": "3.10.9"
|
865 |
+
}
|
866 |
+
},
|
867 |
+
"nbformat": 4,
|
868 |
+
"nbformat_minor": 5
|
869 |
+
}
|
README.md
CHANGED
@@ -1,12 +1,33 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Image Captioning Project
|
2 |
+
|
3 |
+
This project implements an end-to-end Image Captioning system using VGG16, CNN, and LSTM. It generates descriptive captions for input images by combining the power of convolutional neural networks (CNN) for image feature extraction and long short-term memory (LSTM) networks for language modeling.
|
4 |
+
|
5 |
+
## Overview
|
6 |
+
|
7 |
+
The Image Captioning system follows the following steps:
|
8 |
+
|
9 |
+
1. Preprocessing: The input images are preprocessed to extract features using the VGG16 model. These features serve as the visual representation of the images.
|
10 |
+
|
11 |
+
2. Text Preprocessing: The captions associated with the images are preprocessed by tokenizing them into words and creating a vocabulary of unique words.
|
12 |
+
|
13 |
+
3. Model Architecture: The architecture consists of a CNN for image feature extraction and an LSTM network for generating captions. The CNN encodes the image features, while the LSTM decodes the features to generate descriptive captions.
|
14 |
+
|
15 |
+
4. Training: The model is trained using a dataset of images and corresponding captions. The image features are extracted using the pre-trained VGG16 model, and the captions are processed and fed into the LSTM network.
|
16 |
+
|
17 |
+
5. Caption Generation: Given a new input image, the trained model generates captions by first extracting the image features using the CNN and then using the LSTM to generate a sequence of words based on the image features.
|
18 |
+
|
19 |
+
## Dependencies
|
20 |
+
|
21 |
+
- Python 3.x
|
22 |
+
- TensorFlow
|
23 |
+
- Keras
|
24 |
+
- NumPy
|
25 |
+
- NLTK
|
26 |
+
|
27 |
+
## Installation
|
28 |
+
|
29 |
+
1. Clone the repository:
|
30 |
+
|
31 |
+
### app link(not fitted perfectly due to limited resources so that there would be chances of wrong predictions
|
32 |
+
https://sunilgiri7-end-to-end-image-screening-project-streamlit-z7uirv.streamlit.app/
|
33 |
+
|
captions.txt
ADDED
The diff for this file is too large to render.
See raw diff
|
|
descriptions.txt
ADDED
The diff for this file is too large to render.
See raw diff
|
|
descriptions1.txt
ADDED
The diff for this file is too large to render.
See raw diff
|
|
features.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:542f8e7bcb742c8eda9eb4df8c0d26a4a82feed966ad045a7ebec1bc5505826a
|
3 |
+
size 32852115
|
img_captioning_project.ipynb
ADDED
@@ -0,0 +1,1224 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "code",
|
5 |
+
"execution_count": 81,
|
6 |
+
"metadata": {
|
7 |
+
"id": "4xDkP0IKzLgW"
|
8 |
+
},
|
9 |
+
"outputs": [],
|
10 |
+
"source": [
|
11 |
+
"from os import listdir\n",
|
12 |
+
"from numpy import array\n",
|
13 |
+
"from keras.models import Model\n",
|
14 |
+
"from pickle import dump\n",
|
15 |
+
"from keras.applications.vgg16 import VGG16\n",
|
16 |
+
"from tensorflow.keras.preprocessing.image import load_img\n",
|
17 |
+
"from tensorflow.keras.preprocessing.image import img_to_array\n",
|
18 |
+
"from tensorflow.keras.preprocessing.sequence import pad_sequences\n",
|
19 |
+
"from keras.preprocessing.text import Tokenizer\n",
|
20 |
+
"from keras.utils import to_categorical\n",
|
21 |
+
"from keras.utils import plot_model\n",
|
22 |
+
"from keras.models import Model\n",
|
23 |
+
"from keras.layers import Input\n",
|
24 |
+
"from keras.layers import Dense\n",
|
25 |
+
"from keras.layers import LSTM\n",
|
26 |
+
"from keras.layers import Embedding\n",
|
27 |
+
"from keras.layers import Dropout\n",
|
28 |
+
"from tensorflow.keras.layers import Add\n",
|
29 |
+
"from keras.callbacks import ModelCheckpoint"
|
30 |
+
]
|
31 |
+
},
|
32 |
+
{
|
33 |
+
"cell_type": "code",
|
34 |
+
"source": [
|
35 |
+
"from keras.applications.vgg16 import VGG16, preprocess_input\n",
|
36 |
+
"model = VGG16()\n",
|
37 |
+
"# re-structure the model\n",
|
38 |
+
"model.layers.pop()\n",
|
39 |
+
"model = Model(inputs=model.inputs, outputs=model.layers[-2].output)\n",
|
40 |
+
"# summarize\n",
|
41 |
+
"print(model.summary())"
|
42 |
+
],
|
43 |
+
"metadata": {
|
44 |
+
"colab": {
|
45 |
+
"base_uri": "https://localhost:8080/"
|
46 |
+
},
|
47 |
+
"id": "UuRJY0-d9yux",
|
48 |
+
"outputId": "22a58ba4-0f1f-473f-ca65-b7422a453f22"
|
49 |
+
},
|
50 |
+
"execution_count": 82,
|
51 |
+
"outputs": [
|
52 |
+
{
|
53 |
+
"output_type": "stream",
|
54 |
+
"name": "stdout",
|
55 |
+
"text": [
|
56 |
+
"Model: \"model_7\"\n",
|
57 |
+
"_________________________________________________________________\n",
|
58 |
+
" Layer (type) Output Shape Param # \n",
|
59 |
+
"=================================================================\n",
|
60 |
+
" input_8 (InputLayer) [(None, 224, 224, 3)] 0 \n",
|
61 |
+
" \n",
|
62 |
+
" block1_conv1 (Conv2D) (None, 224, 224, 64) 1792 \n",
|
63 |
+
" \n",
|
64 |
+
" block1_conv2 (Conv2D) (None, 224, 224, 64) 36928 \n",
|
65 |
+
" \n",
|
66 |
+
" block1_pool (MaxPooling2D) (None, 112, 112, 64) 0 \n",
|
67 |
+
" \n",
|
68 |
+
" block2_conv1 (Conv2D) (None, 112, 112, 128) 73856 \n",
|
69 |
+
" \n",
|
70 |
+
" block2_conv2 (Conv2D) (None, 112, 112, 128) 147584 \n",
|
71 |
+
" \n",
|
72 |
+
" block2_pool (MaxPooling2D) (None, 56, 56, 128) 0 \n",
|
73 |
+
" \n",
|
74 |
+
" block3_conv1 (Conv2D) (None, 56, 56, 256) 295168 \n",
|
75 |
+
" \n",
|
76 |
+
" block3_conv2 (Conv2D) (None, 56, 56, 256) 590080 \n",
|
77 |
+
" \n",
|
78 |
+
" block3_conv3 (Conv2D) (None, 56, 56, 256) 590080 \n",
|
79 |
+
" \n",
|
80 |
+
" block3_pool (MaxPooling2D) (None, 28, 28, 256) 0 \n",
|
81 |
+
" \n",
|
82 |
+
" block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160 \n",
|
83 |
+
" \n",
|
84 |
+
" block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808 \n",
|
85 |
+
" \n",
|
86 |
+
" block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808 \n",
|
87 |
+
" \n",
|
88 |
+
" block4_pool (MaxPooling2D) (None, 14, 14, 512) 0 \n",
|
89 |
+
" \n",
|
90 |
+
" block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808 \n",
|
91 |
+
" \n",
|
92 |
+
" block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808 \n",
|
93 |
+
" \n",
|
94 |
+
" block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808 \n",
|
95 |
+
" \n",
|
96 |
+
" block5_pool (MaxPooling2D) (None, 7, 7, 512) 0 \n",
|
97 |
+
" \n",
|
98 |
+
" flatten (Flatten) (None, 25088) 0 \n",
|
99 |
+
" \n",
|
100 |
+
" fc1 (Dense) (None, 4096) 102764544 \n",
|
101 |
+
" \n",
|
102 |
+
" fc2 (Dense) (None, 4096) 16781312 \n",
|
103 |
+
" \n",
|
104 |
+
"=================================================================\n",
|
105 |
+
"Total params: 134,260,544\n",
|
106 |
+
"Trainable params: 134,260,544\n",
|
107 |
+
"Non-trainable params: 0\n",
|
108 |
+
"_________________________________________________________________\n",
|
109 |
+
"None\n"
|
110 |
+
]
|
111 |
+
}
|
112 |
+
]
|
113 |
+
},
|
114 |
+
{
|
115 |
+
"cell_type": "code",
|
116 |
+
"execution_count": 83,
|
117 |
+
"metadata": {
|
118 |
+
"id": "tR-lfP51bmp5"
|
119 |
+
},
|
120 |
+
"outputs": [],
|
121 |
+
"source": [
|
122 |
+
"from os import listdir\n",
|
123 |
+
"from pickle import dump\n",
|
124 |
+
"from tensorflow.keras.preprocessing.image import img_to_array, load_img\n",
|
125 |
+
"from keras.models import Model\n",
|
126 |
+
"\n",
|
127 |
+
"# extract feature from each photo in directory\n",
|
128 |
+
"def extract_features(directory):\n",
|
129 |
+
"\t# extract features from each photo\n",
|
130 |
+
"\tfeatures = dict()\n",
|
131 |
+
"\tfor name in listdir(directory):\n",
|
132 |
+
"\t\t# load an image from file\n",
|
133 |
+
"\t\tfilename = directory + '/' + name\n",
|
134 |
+
"\t\timage = load_img(filename, target_size=(224, 224))\n",
|
135 |
+
"\t\t# convert the image pixels to a numpy array\n",
|
136 |
+
"\t\timage = img_to_array(image)\n",
|
137 |
+
"\t\t# reshape data for the model\n",
|
138 |
+
"\t\timage = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))\n",
|
139 |
+
"\t\t# prepare the image for the VGG model\n",
|
140 |
+
"\t\timage = preprocess_input(image)\n",
|
141 |
+
"\t\t# get features\n",
|
142 |
+
"\t\tfeature = model.predict(image, verbose=0)\n",
|
143 |
+
"\t\t# get image id\n",
|
144 |
+
"\t\timage_id = name.split('.')[0]\n",
|
145 |
+
"\t\t# store feature\n",
|
146 |
+
"\t\tfeatures[image_id] = feature\n",
|
147 |
+
"\t\tprint('>%s' % name)\n",
|
148 |
+
"\treturn features"
|
149 |
+
]
|
150 |
+
},
|
151 |
+
{
|
152 |
+
"cell_type": "code",
|
153 |
+
"execution_count": 84,
|
154 |
+
"metadata": {
|
155 |
+
"id": "nc7ks02Gjwgh"
|
156 |
+
},
|
157 |
+
"outputs": [],
|
158 |
+
"source": [
|
159 |
+
"# directory = \"/content/drive/MyDrive/Image_Captioning_Project/Images\"\n",
|
160 |
+
"# features = extract_features(directory)\n",
|
161 |
+
"# dump(features, open('features1.pkl', 'wb'))\n",
|
162 |
+
"# print(\"Extracted Features: %d\" %len(features))"
|
163 |
+
]
|
164 |
+
},
|
165 |
+
{
|
166 |
+
"cell_type": "code",
|
167 |
+
"source": [
|
168 |
+
"!ls"
|
169 |
+
],
|
170 |
+
"metadata": {
|
171 |
+
"colab": {
|
172 |
+
"base_uri": "https://localhost:8080/"
|
173 |
+
},
|
174 |
+
"id": "9fp0SwYv0VK6",
|
175 |
+
"outputId": "4387bde5-1136-41b9-f03b-52404d2ee015"
|
176 |
+
},
|
177 |
+
"execution_count": 85,
|
178 |
+
"outputs": [
|
179 |
+
{
|
180 |
+
"output_type": "stream",
|
181 |
+
"name": "stdout",
|
182 |
+
"text": [
|
183 |
+
"drive sample_data\n"
|
184 |
+
]
|
185 |
+
}
|
186 |
+
]
|
187 |
+
},
|
188 |
+
{
|
189 |
+
"cell_type": "code",
|
190 |
+
"execution_count": 86,
|
191 |
+
"metadata": {
|
192 |
+
"id": "-nIfYC9Yj7-b"
|
193 |
+
},
|
194 |
+
"outputs": [],
|
195 |
+
"source": [
|
196 |
+
"import string\n",
|
197 |
+
"from nltk.tokenize import word_tokenize\n",
|
198 |
+
"\n",
|
199 |
+
"def load_doc(filename):\n",
|
200 |
+
" # open the file as read only\n",
|
201 |
+
" file = open(filename, 'r')\n",
|
202 |
+
" # read all text\n",
|
203 |
+
" text = file.read()\n",
|
204 |
+
" # close the file\n",
|
205 |
+
" file.close()\n",
|
206 |
+
" return text"
|
207 |
+
]
|
208 |
+
},
|
209 |
+
{
|
210 |
+
"cell_type": "code",
|
211 |
+
"execution_count": 87,
|
212 |
+
"metadata": {
|
213 |
+
"id": "n9FUCV49RnnS"
|
214 |
+
},
|
215 |
+
"outputs": [],
|
216 |
+
"source": [
|
217 |
+
"def load_descriptions(doc):\n",
|
218 |
+
"\tmapping = dict()\n",
|
219 |
+
"\t# process lines\n",
|
220 |
+
"\tfor line in doc.split('\\n'):\n",
|
221 |
+
"\t\t# split line by white space\n",
|
222 |
+
"\t\ttokens = line.split()\n",
|
223 |
+
"\t\tif len(line) < 2:\n",
|
224 |
+
"\t\t\tcontinue\n",
|
225 |
+
"\t\t# take the first token as the image id, the rest as the description\n",
|
226 |
+
"\t\timage_id, image_desc = tokens[0], tokens[1:]\n",
|
227 |
+
"\t\t# remove filename from image id\n",
|
228 |
+
"\t\timage_id = image_id.split('.')[0]\n",
|
229 |
+
"\t\t# convert description tokens back to string\n",
|
230 |
+
"\t\timage_desc = ' '.join(image_desc)\n",
|
231 |
+
"\t\t# create the list if needed\n",
|
232 |
+
"\t\tif image_id not in mapping:\n",
|
233 |
+
"\t\t\tmapping[image_id] = list()\n",
|
234 |
+
"\t\t# store description\n",
|
235 |
+
"\t\tmapping[image_id].append(image_desc)\n",
|
236 |
+
"\treturn mapping"
|
237 |
+
]
|
238 |
+
},
|
239 |
+
{
|
240 |
+
"cell_type": "markdown",
|
241 |
+
"source": [
|
242 |
+
"## Preprocessing of Text\n",
|
243 |
+
"\n",
|
244 |
+
"1. Convert all words to lowercase.\n",
|
245 |
+
"2. Remove all punctuation.\n",
|
246 |
+
"3. Remove all words that are one character or less in length (e.g. ‘a’).\n",
|
247 |
+
"4. Remove all words with numbers in them."
|
248 |
+
],
|
249 |
+
"metadata": {
|
250 |
+
"id": "l31beBIf2E3h"
|
251 |
+
}
|
252 |
+
},
|
253 |
+
{
|
254 |
+
"cell_type": "code",
|
255 |
+
"execution_count": 88,
|
256 |
+
"metadata": {
|
257 |
+
"id": "e6Dd0Ugej8sf"
|
258 |
+
},
|
259 |
+
"outputs": [],
|
260 |
+
"source": [
|
261 |
+
"def clean_descriptions(descriptions):\n",
|
262 |
+
" # prepare translation table for removing punctuation\n",
|
263 |
+
" table = str.maketrans('', '', string.punctuation)\n",
|
264 |
+
" for key, desc_list in descriptions.items():\n",
|
265 |
+
" for i in range(len(desc_list)):\n",
|
266 |
+
" desc = desc_list[i]\n",
|
267 |
+
" # tokenize\n",
|
268 |
+
" desc = desc.split()\n",
|
269 |
+
" # convert to lower case\n",
|
270 |
+
" desc = [word.lower() for word in desc]\n",
|
271 |
+
" # remove punctuation from each token\n",
|
272 |
+
" desc = [w.translate(table) for w in desc]\n",
|
273 |
+
" # remove hanging 's' and 'a'\n",
|
274 |
+
" desc = [word for word in desc if len(word)>1]\n",
|
275 |
+
" # remove tokens with numbers in them\n",
|
276 |
+
" desc = [word for word in desc if word.isalpha()]\n",
|
277 |
+
" # store as string\n",
|
278 |
+
" desc_list[i] = ' '.join(desc)\n",
|
279 |
+
"def to_vocabulary(descriptions):\n",
|
280 |
+
" # build a list of all description strings\n",
|
281 |
+
" all_desc = set()\n",
|
282 |
+
" for key in descriptions.keys():\n",
|
283 |
+
" [all_desc.update(d.split()) for d in descriptions[key]]\n",
|
284 |
+
" return all_desc"
|
285 |
+
]
|
286 |
+
},
|
287 |
+
{
|
288 |
+
"cell_type": "code",
|
289 |
+
"execution_count": 89,
|
290 |
+
"metadata": {
|
291 |
+
"id": "o7lzD3qgkCDs"
|
292 |
+
},
|
293 |
+
"outputs": [],
|
294 |
+
"source": [
|
295 |
+
"def save_descriptions(descriptions, filename):\n",
|
296 |
+
" lines = list()\n",
|
297 |
+
" for key, desc_list in descriptions.items():\n",
|
298 |
+
" for desc in desc_list:\n",
|
299 |
+
" lines.append(key + \" \" + desc)\n",
|
300 |
+
" data = '\\n'.join(lines)\n",
|
301 |
+
" file = open(filename, 'w')\n",
|
302 |
+
" file.write(data)\n",
|
303 |
+
" file.close()"
|
304 |
+
]
|
305 |
+
},
|
306 |
+
{
|
307 |
+
"cell_type": "code",
|
308 |
+
"execution_count": 90,
|
309 |
+
"metadata": {
|
310 |
+
"colab": {
|
311 |
+
"base_uri": "https://localhost:8080/"
|
312 |
+
},
|
313 |
+
"id": "_kjcu6Ug3Lqc",
|
314 |
+
"outputId": "4139ef68-a4a0-43f4-f86f-01f52cf73138"
|
315 |
+
},
|
316 |
+
"outputs": [
|
317 |
+
{
|
318 |
+
"output_type": "stream",
|
319 |
+
"name": "stderr",
|
320 |
+
"text": [
|
321 |
+
"[nltk_data] Downloading package punkt to /root/nltk_data...\n",
|
322 |
+
"[nltk_data] Package punkt is already up-to-date!\n"
|
323 |
+
]
|
324 |
+
},
|
325 |
+
{
|
326 |
+
"output_type": "execute_result",
|
327 |
+
"data": {
|
328 |
+
"text/plain": [
|
329 |
+
"True"
|
330 |
+
]
|
331 |
+
},
|
332 |
+
"metadata": {},
|
333 |
+
"execution_count": 90
|
334 |
+
}
|
335 |
+
],
|
336 |
+
"source": [
|
337 |
+
"import nltk\n",
|
338 |
+
"nltk.download('punkt')"
|
339 |
+
]
|
340 |
+
},
|
341 |
+
{
|
342 |
+
"cell_type": "code",
|
343 |
+
"execution_count": 91,
|
344 |
+
"metadata": {
|
345 |
+
"colab": {
|
346 |
+
"base_uri": "https://localhost:8080/"
|
347 |
+
},
|
348 |
+
"id": "RancEv97kENF",
|
349 |
+
"outputId": "8d8214e4-fe45-4e25-a602-74c143971471"
|
350 |
+
},
|
351 |
+
"outputs": [
|
352 |
+
{
|
353 |
+
"output_type": "stream",
|
354 |
+
"name": "stdout",
|
355 |
+
"text": [
|
356 |
+
"Loaded: 8092\n"
|
357 |
+
]
|
358 |
+
}
|
359 |
+
],
|
360 |
+
"source": [
|
361 |
+
"filename = \"/content/drive/MyDrive/Image_Captioning_Project/Flickr8k.token.txt\"\n",
|
362 |
+
"doc = load_doc(filename)\n",
|
363 |
+
"descriptions = load_descriptions(doc)\n",
|
364 |
+
"print(\"Loaded: %d\" %len(descriptions))"
|
365 |
+
]
|
366 |
+
},
|
367 |
+
{
|
368 |
+
"cell_type": "code",
|
369 |
+
"execution_count": 92,
|
370 |
+
"metadata": {
|
371 |
+
"colab": {
|
372 |
+
"base_uri": "https://localhost:8080/"
|
373 |
+
},
|
374 |
+
"id": "BD4eqsEukFqE",
|
375 |
+
"outputId": "e9e98894-99c3-4ca4-d9bd-94fc4ba22e0e"
|
376 |
+
},
|
377 |
+
"outputs": [
|
378 |
+
{
|
379 |
+
"output_type": "stream",
|
380 |
+
"name": "stdout",
|
381 |
+
"text": [
|
382 |
+
"Vocab size: 8763\n"
|
383 |
+
]
|
384 |
+
}
|
385 |
+
],
|
386 |
+
"source": [
|
387 |
+
"#clean desc\n",
|
388 |
+
"clean_descriptions(descriptions)\n",
|
389 |
+
"vocab = to_vocabulary(descriptions)\n",
|
390 |
+
"print(\"Vocab size: %d\" %len(vocab))"
|
391 |
+
]
|
392 |
+
},
|
393 |
+
{
|
394 |
+
"cell_type": "code",
|
395 |
+
"execution_count": 93,
|
396 |
+
"metadata": {
|
397 |
+
"id": "rVZ9RHhbkGIo"
|
398 |
+
},
|
399 |
+
"outputs": [],
|
400 |
+
"source": [
|
401 |
+
"# save_descriptions(descriptions, \"descriptions2.txt\")"
|
402 |
+
]
|
403 |
+
},
|
404 |
+
{
|
405 |
+
"cell_type": "markdown",
|
406 |
+
"source": [
|
407 |
+
"### Developing Deep Learning Model\n",
|
408 |
+
"\n",
|
409 |
+
"#### This section is divided into the following parts:\n",
|
410 |
+
"\n",
|
411 |
+
"Loading Data.\n",
|
412 |
+
"Defining the Model.\n",
|
413 |
+
"Fitting the Model."
|
414 |
+
],
|
415 |
+
"metadata": {
|
416 |
+
"id": "PnV7xrpPCPrs"
|
417 |
+
}
|
418 |
+
},
|
419 |
+
{
|
420 |
+
"cell_type": "code",
|
421 |
+
"execution_count": 94,
|
422 |
+
"metadata": {
|
423 |
+
"id": "dZ8tvUjckG1F"
|
424 |
+
},
|
425 |
+
"outputs": [],
|
426 |
+
"source": [
|
427 |
+
"from pickle import dump\n",
|
428 |
+
"\n",
|
429 |
+
"#load into memory\n",
|
430 |
+
"def load_doc(filename):\n",
|
431 |
+
"\t# open the file as read only\n",
|
432 |
+
"\tfile = open(filename, 'r')\n",
|
433 |
+
"\t# read all text\n",
|
434 |
+
"\ttext = file.read()\n",
|
435 |
+
"\t# close the file\n",
|
436 |
+
"\tfile.close()\n",
|
437 |
+
"\treturn text\n",
|
438 |
+
"\n",
|
439 |
+
"#pre-defined list of photo identifier\n",
|
440 |
+
"def load_set(filename):\n",
|
441 |
+
" doc = load_doc(filename)\n",
|
442 |
+
" dataset = list()\n",
|
443 |
+
" for line in doc.split(\"\\n\"):\n",
|
444 |
+
" if len(line) < 1:\n",
|
445 |
+
" continue\n",
|
446 |
+
" identifier = line.split('.')[0]\n",
|
447 |
+
" dataset.append(identifier)\n",
|
448 |
+
" return set(dataset)"
|
449 |
+
]
|
450 |
+
},
|
451 |
+
{
|
452 |
+
"cell_type": "markdown",
|
453 |
+
"source": [
|
454 |
+
"load_clean_descriptions() that loads the cleaned text descriptions from ‘descriptions.txt‘ for a given set of identifiers and returns a dictionary of identifiers to lists of text descriptions.\n",
|
455 |
+
"\n",
|
456 |
+
"The model we will develop will generate a caption given a photo, and the caption will be generated one word at a time. The sequence of previously generated words will be provided as input. Therefore, we will need a ‘first word’ to kick-off the generation process and a ‘last word‘ to signal the end of the caption.\n",
|
457 |
+
"\n",
|
458 |
+
"We will use the strings ‘startseq‘ and ‘endseq‘ for this purpose."
|
459 |
+
],
|
460 |
+
"metadata": {
|
461 |
+
"id": "NxRnPZr4CZh4"
|
462 |
+
}
|
463 |
+
},
|
464 |
+
{
|
465 |
+
"cell_type": "code",
|
466 |
+
"execution_count": 95,
|
467 |
+
"metadata": {
|
468 |
+
"id": "9hF4PUCskHF_"
|
469 |
+
},
|
470 |
+
"outputs": [],
|
471 |
+
"source": [
|
472 |
+
"def load_photo_features(features, dataset):\n",
|
473 |
+
" all_features = load(open(features, 'rb'))\n",
|
474 |
+
" features = {k: all_features[k] for k in dataset}\n",
|
475 |
+
" return features"
|
476 |
+
]
|
477 |
+
},
|
478 |
+
{
|
479 |
+
"cell_type": "code",
|
480 |
+
"execution_count": 96,
|
481 |
+
"metadata": {
|
482 |
+
"id": "kPQVXbKqSp6m"
|
483 |
+
},
|
484 |
+
"outputs": [],
|
485 |
+
"source": [
|
486 |
+
"def load_clean_descriptions(filename, dataset):\n",
|
487 |
+
"\t# load document\n",
|
488 |
+
"\tdoc = load_doc(filename)\n",
|
489 |
+
"\tdescriptions = dict()\n",
|
490 |
+
"\tfor line in doc.split('\\n'):\n",
|
491 |
+
"\t\t# split line by white space\n",
|
492 |
+
"\t\ttokens = line.split()\n",
|
493 |
+
"\t\t# split id from description\n",
|
494 |
+
"\t\timage_id, image_desc = tokens[0], tokens[1:]\n",
|
495 |
+
"\t\t# skip images not in the set\n",
|
496 |
+
"\t\tif image_id in dataset:\n",
|
497 |
+
"\t\t\t# create list\n",
|
498 |
+
"\t\t\tif image_id not in descriptions:\n",
|
499 |
+
"\t\t\t\tdescriptions[image_id] = list()\n",
|
500 |
+
"\t\t\t# wrap description in tokens\n",
|
501 |
+
"\t\t\tdesc = 'startseq ' + ' '.join(image_desc) + ' endseq'\n",
|
502 |
+
"\t\t\t# store\n",
|
503 |
+
"\t\t\tdescriptions[image_id].append(desc)\n",
|
504 |
+
"\treturn descriptions"
|
505 |
+
]
|
506 |
+
},
|
507 |
+
{
|
508 |
+
"cell_type": "code",
|
509 |
+
"source": [
|
510 |
+
"from pickle import load\n",
|
511 |
+
"\n",
|
512 |
+
"# load training dataset (6K)\n",
|
513 |
+
"filename = '/content/drive/MyDrive/Image_Captioning_Project/Flickr_8k.trainImages.txt'\n",
|
514 |
+
"train = load_set(filename)\n",
|
515 |
+
"print('Dataset: %d' % len(train))\n",
|
516 |
+
"# descriptions\n",
|
517 |
+
"train_descriptions = load_clean_descriptions('/content/drive/MyDrive/Image_Captioning_Project/descriptions1.txt', train)\n",
|
518 |
+
"print('Descriptions: train=%d' % len(train_descriptions))\n",
|
519 |
+
"# photo features\n",
|
520 |
+
"train_features = load_photo_features('/content/drive/MyDrive/Image_Captioning_Project/features.pkl', train)\n",
|
521 |
+
"print('Photos: train=%d' % len(train_features))"
|
522 |
+
],
|
523 |
+
"metadata": {
|
524 |
+
"colab": {
|
525 |
+
"base_uri": "https://localhost:8080/"
|
526 |
+
},
|
527 |
+
"id": "M8Y0VIWrxRdr",
|
528 |
+
"outputId": "baef9b0d-885f-4ba6-b792-4d9b0ffcb52b"
|
529 |
+
},
|
530 |
+
"execution_count": 97,
|
531 |
+
"outputs": [
|
532 |
+
{
|
533 |
+
"output_type": "stream",
|
534 |
+
"name": "stdout",
|
535 |
+
"text": [
|
536 |
+
"Dataset: 6000\n",
|
537 |
+
"Descriptions: train=6000\n",
|
538 |
+
"Photos: train=6000\n"
|
539 |
+
]
|
540 |
+
}
|
541 |
+
]
|
542 |
+
},
|
543 |
+
{
|
544 |
+
"cell_type": "code",
|
545 |
+
"execution_count": 98,
|
546 |
+
"metadata": {
|
547 |
+
"id": "CxCpUVLlZ1M6"
|
548 |
+
},
|
549 |
+
"outputs": [],
|
550 |
+
"source": [
|
551 |
+
"def load_doc(filename):\n",
|
552 |
+
"\t# open the file as read only\n",
|
553 |
+
"\tfile = open(filename, 'r')\n",
|
554 |
+
"\t# read all text\n",
|
555 |
+
"\ttext = file.read()\n",
|
556 |
+
"\t# close the file\n",
|
557 |
+
"\tfile.close\n",
|
558 |
+
"\treturn text"
|
559 |
+
]
|
560 |
+
},
|
561 |
+
{
|
562 |
+
"cell_type": "code",
|
563 |
+
"execution_count": 99,
|
564 |
+
"metadata": {
|
565 |
+
"id": "pqOcDdqUTHDW"
|
566 |
+
},
|
567 |
+
"outputs": [],
|
568 |
+
"source": [
|
569 |
+
"def load_set(filename):\n",
|
570 |
+
" doc = load_doc(filename)\n",
|
571 |
+
" dataset = list()\n",
|
572 |
+
" for line in doc.split(\"\\n\"):\n",
|
573 |
+
" if len(line) < 1:\n",
|
574 |
+
" continue\n",
|
575 |
+
" identifier = line.split('.')[0]\n",
|
576 |
+
" dataset.append(identifier)\n",
|
577 |
+
" return set(dataset)"
|
578 |
+
]
|
579 |
+
},
|
580 |
+
{
|
581 |
+
"cell_type": "code",
|
582 |
+
"execution_count": 100,
|
583 |
+
"metadata": {
|
584 |
+
"id": "_l3IMXzPZ7mN"
|
585 |
+
},
|
586 |
+
"outputs": [],
|
587 |
+
"source": [
|
588 |
+
"def load_clean_descriptions(filename, dataset):\n",
|
589 |
+
"\t# load document\n",
|
590 |
+
"\tdoc = load_doc(filename)\n",
|
591 |
+
"\tdescriptions = dict()\n",
|
592 |
+
"\tfor line in doc.split('\\n'):\n",
|
593 |
+
"\t\t# split line by white space\n",
|
594 |
+
"\t\ttokens = line.split()\n",
|
595 |
+
"\t\t# split id from description\n",
|
596 |
+
"\t\timage_id, image_desc = tokens[0], tokens[1:]\n",
|
597 |
+
"\t\t# skip images not in the set\n",
|
598 |
+
"\t\tif image_id in dataset:\n",
|
599 |
+
"\t\t\t# create list\n",
|
600 |
+
"\t\t\tif image_id not in descriptions:\n",
|
601 |
+
"\t\t\t\tdescriptions[image_id] = list()\n",
|
602 |
+
"\t\t\t# wrap description in tokens\n",
|
603 |
+
"\t\t\tdesc = 'startseq ' + ' '.join(image_desc) + ' endseq'\n",
|
604 |
+
"\t\t\t# store\n",
|
605 |
+
"\t\t\tdescriptions[image_id].append(desc)\n",
|
606 |
+
"\treturn descriptions "
|
607 |
+
]
|
608 |
+
},
|
609 |
+
{
|
610 |
+
"cell_type": "code",
|
611 |
+
"execution_count": 101,
|
612 |
+
"metadata": {
|
613 |
+
"id": "Cf_rfRQpTtu_"
|
614 |
+
},
|
615 |
+
"outputs": [],
|
616 |
+
"source": [
|
617 |
+
"def load_photo_features(filename, dataset):\n",
|
618 |
+
"\t# load all features\n",
|
619 |
+
"\tall_features = load(open(filename, 'rb'))\n",
|
620 |
+
"\t# filter features\n",
|
621 |
+
"\tfeatures = {k: all_features[k] for k in dataset}\n",
|
622 |
+
"\treturn features"
|
623 |
+
]
|
624 |
+
},
|
625 |
+
{
|
626 |
+
"cell_type": "code",
|
627 |
+
"execution_count": 102,
|
628 |
+
"metadata": {
|
629 |
+
"id": "0HHS8lQFkHR-"
|
630 |
+
},
|
631 |
+
"outputs": [],
|
632 |
+
"source": [
|
633 |
+
"# dict to clean list\n",
|
634 |
+
"def to_lines(descriptions):\n",
|
635 |
+
" all_desc = list()\n",
|
636 |
+
" for key in descriptions.keys():\n",
|
637 |
+
" [all_desc.append(d) for d in descriptions[key]]\n",
|
638 |
+
" return all_desc\n",
|
639 |
+
"\n",
|
640 |
+
"def create_tokenizer(descriptions):\n",
|
641 |
+
" lines = to_lines(descriptions)\n",
|
642 |
+
" tokenizer = Tokenizer()\n",
|
643 |
+
" tokenizer.fit_on_texts(lines)\n",
|
644 |
+
" return tokenizer"
|
645 |
+
]
|
646 |
+
},
|
647 |
+
{
|
648 |
+
"cell_type": "code",
|
649 |
+
"execution_count": 103,
|
650 |
+
"metadata": {
|
651 |
+
"id": "FjSt5rpvkXk3"
|
652 |
+
},
|
653 |
+
"outputs": [],
|
654 |
+
"source": [
|
655 |
+
"#len of description\n",
|
656 |
+
"def max_length(description):\n",
|
657 |
+
" lines = to_lines(description)\n",
|
658 |
+
" return max(len(d.split()) for d in lines)"
|
659 |
+
]
|
660 |
+
},
|
661 |
+
{
|
662 |
+
"cell_type": "code",
|
663 |
+
"execution_count": 104,
|
664 |
+
"metadata": {
|
665 |
+
"id": "cNko1BPwkX21"
|
666 |
+
},
|
667 |
+
"outputs": [],
|
668 |
+
"source": [
|
669 |
+
"# create input and output sequence\n",
|
670 |
+
"def create_sequences(tokenizer, max_length, desc_list, photo):\n",
|
671 |
+
" X1, X2, y = list(), list(), list()\n",
|
672 |
+
" # walk through each description for the image\n",
|
673 |
+
" for desc in desc_list:\n",
|
674 |
+
" # encode the sequence\n",
|
675 |
+
" seq = tokenizer.texts_to_sequences([desc])[0]\n",
|
676 |
+
" # split one sequence into multiple X,y pairs\n",
|
677 |
+
" for i in range(1, len(seq)):\n",
|
678 |
+
" # split into input and output pair\n",
|
679 |
+
" in_seq, out_seq = seq[:i], seq[i]\n",
|
680 |
+
" # pad input sequence\n",
|
681 |
+
" in_seq = pad_sequences([in_seq], maxlen=max_length)[0]\n",
|
682 |
+
" # encode output sequence\n",
|
683 |
+
" out_seq = to_categorical([out_seq], num_classes=vocab_size)[0]\n",
|
684 |
+
" # store\n",
|
685 |
+
" X1.append(photo)\n",
|
686 |
+
" X2.append(in_seq)\n",
|
687 |
+
" y.append(out_seq)\n",
|
688 |
+
" return array(X1), array(X2), array(y)"
|
689 |
+
]
|
690 |
+
},
|
691 |
+
{
|
692 |
+
"cell_type": "markdown",
|
693 |
+
"metadata": {
|
694 |
+
"id": "q5LhU8zQkdqu"
|
695 |
+
},
|
696 |
+
"source": [
|
697 |
+
"## Model building"
|
698 |
+
]
|
699 |
+
},
|
700 |
+
{
|
701 |
+
"cell_type": "code",
|
702 |
+
"execution_count": 105,
|
703 |
+
"metadata": {
|
704 |
+
"id": "zT7KqC6bkYEj"
|
705 |
+
},
|
706 |
+
"outputs": [],
|
707 |
+
"source": [
|
708 |
+
"from tensorflow.keras.layers import add\n",
|
709 |
+
"def define_model(vocab_size, max_length):\n",
|
710 |
+
" # feature extractor model\n",
|
711 |
+
" inputs1 = Input(shape=(1000,))\n",
|
712 |
+
" fe1 = Dropout(0.5)(inputs1)\n",
|
713 |
+
" fe2 = Dense(256, activation='relu')(fe1)\n",
|
714 |
+
" # sequence model\n",
|
715 |
+
" inputs2 = Input(shape=(max_length,))\n",
|
716 |
+
" se1 = Embedding(vocab_size,output_dim=256, mask_zero=True)(inputs2)\n",
|
717 |
+
" se2 = Dropout(0.5)(se1)\n",
|
718 |
+
" se3 = LSTM(256)(se2)\n",
|
719 |
+
" # decoder model\n",
|
720 |
+
" decoder1 = add([fe2, se3])\n",
|
721 |
+
" decoder2 = Dense(256, activation='relu')(decoder1)\n",
|
722 |
+
" outputs = Dense(vocab_size, activation='softmax')(decoder2)\n",
|
723 |
+
" # tie it together [image, seq] [word]\n",
|
724 |
+
" model = Model(inputs=[inputs1, inputs2], outputs=outputs)\n",
|
725 |
+
" model.compile(loss='categorical_crossentropy', optimizer='adam')\n",
|
726 |
+
" # summarize model\n",
|
727 |
+
" print(model.summary())\n",
|
728 |
+
" return model"
|
729 |
+
]
|
730 |
+
},
|
731 |
+
{
|
732 |
+
"cell_type": "code",
|
733 |
+
"execution_count": 106,
|
734 |
+
"metadata": {
|
735 |
+
"id": "fR-dFhrYkYJv"
|
736 |
+
},
|
737 |
+
"outputs": [],
|
738 |
+
"source": [
|
739 |
+
"# load batch of data\n",
|
740 |
+
"def data_generator(descriptions, photos, tokenizer, max_length):\n",
|
741 |
+
" # loop for ever over images\n",
|
742 |
+
" while 1:\n",
|
743 |
+
" for key, desc_list in descriptions.items():\n",
|
744 |
+
" # retrieve the photo feature\n",
|
745 |
+
" photo = photos[key][0]\n",
|
746 |
+
" in_img, in_seq, out_word = create_sequences(tokenizer, max_length, desc_list, photo)\n",
|
747 |
+
" yield [[in_img, in_seq], out_word]"
|
748 |
+
]
|
749 |
+
},
|
750 |
+
{
|
751 |
+
"cell_type": "code",
|
752 |
+
"execution_count": 107,
|
753 |
+
"metadata": {
|
754 |
+
"colab": {
|
755 |
+
"base_uri": "https://localhost:8080/"
|
756 |
+
},
|
757 |
+
"id": "eJ6n7_dEkkis",
|
758 |
+
"outputId": "4f0e3daa-18c7-4797-a7a6-5d193b02cf04"
|
759 |
+
},
|
760 |
+
"outputs": [
|
761 |
+
{
|
762 |
+
"output_type": "stream",
|
763 |
+
"name": "stdout",
|
764 |
+
"text": [
|
765 |
+
"Dataset: 6000\n",
|
766 |
+
"train_descriptions= 6000\n",
|
767 |
+
"photos: train= 6000\n",
|
768 |
+
"Vocab size: 7579\n",
|
769 |
+
"Description Length: 34\n"
|
770 |
+
]
|
771 |
+
}
|
772 |
+
],
|
773 |
+
"source": [
|
774 |
+
"#load train dataset\n",
|
775 |
+
"import tensorflow as tf\n",
|
776 |
+
"filename = \"/content/drive/MyDrive/Image_Captioning_Project/Flickr_8k.trainImages.txt\"\n",
|
777 |
+
"train = load_set(filename)\n",
|
778 |
+
"print(\"Dataset: %d\" %len(train))\n",
|
779 |
+
"\n",
|
780 |
+
"train_descriptions = load_clean_descriptions(\"/content/drive/MyDrive/Image_Captioning_Project/descriptions1.txt\", train)\n",
|
781 |
+
"print(\"train_descriptions= %d\" %len(train_descriptions))\n",
|
782 |
+
"\n",
|
783 |
+
"train_feature = load_photo_features(\"/content/drive/MyDrive/Image_Captioning_Project/features.pkl\", train)\n",
|
784 |
+
"print(\"photos: train= %d\" %len(train_feature))\n",
|
785 |
+
"\n",
|
786 |
+
"tokenizer = create_tokenizer(train_descriptions)\n",
|
787 |
+
"vocab_size = len(tokenizer.word_index)+1\n",
|
788 |
+
"print(\"Vocab size: %d\" %vocab_size)\n",
|
789 |
+
"\n",
|
790 |
+
"max_length = max_length(train_descriptions)\n",
|
791 |
+
"print('Description Length: %d' % max_length)"
|
792 |
+
]
|
793 |
+
},
|
794 |
+
{
|
795 |
+
"cell_type": "code",
|
796 |
+
"execution_count": 108,
|
797 |
+
"metadata": {
|
798 |
+
"id": "yUnKHod1BIup"
|
799 |
+
},
|
800 |
+
"outputs": [],
|
801 |
+
"source": [
|
802 |
+
"import pickle\n",
|
803 |
+
"\n",
|
804 |
+
"# Dump the tokenizer using pickle\n",
|
805 |
+
"with open('tokenizer1.pkl', 'wb') as f:\n",
|
806 |
+
" pickle.dump(tokenizer, f)"
|
807 |
+
]
|
808 |
+
},
|
809 |
+
{
|
810 |
+
"cell_type": "code",
|
811 |
+
"execution_count": 109,
|
812 |
+
"metadata": {
|
813 |
+
"id": "-x7HX3aLkk2x"
|
814 |
+
},
|
815 |
+
"outputs": [],
|
816 |
+
"source": [
|
817 |
+
"#train model\n",
|
818 |
+
"# model = define_model(vocab_size, max_length)\n",
|
819 |
+
"# filename = \"/content/drive/MyDrive/Image_Captioning_Project/model_18.h5\"\n",
|
820 |
+
"# model = load_model(filename)\n",
|
821 |
+
"# epochs = 4\n",
|
822 |
+
"# steps = len(train_descriptions)\n",
|
823 |
+
"# model.summary()"
|
824 |
+
]
|
825 |
+
},
|
826 |
+
{
|
827 |
+
"cell_type": "code",
|
828 |
+
"execution_count": 110,
|
829 |
+
"metadata": {
|
830 |
+
"id": "JyBqM_6ikk8Y"
|
831 |
+
},
|
832 |
+
"outputs": [],
|
833 |
+
"source": [
|
834 |
+
"# for i in range(epochs):\n",
|
835 |
+
"# #create data generator\n",
|
836 |
+
"# generator = data_generator(train_descriptions, train_feature, tokenizer, max_len)\n",
|
837 |
+
"# model.fit(generator, epochs=1, steps_per_epoch = steps, verbose=1)\n",
|
838 |
+
"# model.save(\"model_\" + str(i) + \".h5\")"
|
839 |
+
]
|
840 |
+
},
|
841 |
+
{
|
842 |
+
"cell_type": "code",
|
843 |
+
"execution_count": 111,
|
844 |
+
"metadata": {
|
845 |
+
"id": "U4-B7smiaqCH"
|
846 |
+
},
|
847 |
+
"outputs": [],
|
848 |
+
"source": [
|
849 |
+
"def load_doc(filename):\n",
|
850 |
+
"\t# open the file as read only\n",
|
851 |
+
"\tfile = open(filename, 'r')\n",
|
852 |
+
"\t# read all text\n",
|
853 |
+
"\ttext = file.read()\n",
|
854 |
+
"\t# close the file\n",
|
855 |
+
"\tfile.close()\n",
|
856 |
+
"\treturn text\n",
|
857 |
+
"\n",
|
858 |
+
"# load a pre-defined list of photo identifiers\n",
|
859 |
+
"def load_set(filename):\n",
|
860 |
+
"\tdoc = load_doc(filename)\n",
|
861 |
+
"\tdataset = list()\n",
|
862 |
+
"\t# process line by line\n",
|
863 |
+
"\tfor line in doc.split('\\n'):\n",
|
864 |
+
"\t\t# skip empty lines\n",
|
865 |
+
"\t\tif len(line) < 1:\n",
|
866 |
+
"\t\t\tcontinue\n",
|
867 |
+
"\t\t# get the image identifier\n",
|
868 |
+
"\t\tidentifier = line.split('.')[0]\n",
|
869 |
+
"\t\tdataset.append(identifier)\n",
|
870 |
+
"\treturn set(dataset)"
|
871 |
+
]
|
872 |
+
},
|
873 |
+
{
|
874 |
+
"cell_type": "code",
|
875 |
+
"execution_count": 112,
|
876 |
+
"metadata": {
|
877 |
+
"id": "y42JWG04a1e2"
|
878 |
+
},
|
879 |
+
"outputs": [],
|
880 |
+
"source": [
|
881 |
+
"def load_photo_features(filename, dataset):\n",
|
882 |
+
"\t# load all features\n",
|
883 |
+
"\tall_features = load(open(filename, 'rb'))\n",
|
884 |
+
"\t# filter features\n",
|
885 |
+
"\tfeatures = {k: all_features[k] for k in dataset}\n",
|
886 |
+
"\treturn features\n",
|
887 |
+
"\n",
|
888 |
+
"# covert a dictionary of clean descriptions to a list of descriptions\n",
|
889 |
+
"def to_lines(descriptions):\n",
|
890 |
+
"\tall_desc = list()\n",
|
891 |
+
"\tfor key in descriptions.keys():\n",
|
892 |
+
"\t\t[all_desc.append(d) for d in descriptions[key]]\n",
|
893 |
+
"\treturn all_desc\n",
|
894 |
+
"\n",
|
895 |
+
"# fit a tokenizer given caption descriptions\n",
|
896 |
+
"def create_tokenizer(descriptions):\n",
|
897 |
+
"\tlines = to_lines(descriptions)\n",
|
898 |
+
"\ttokenizer = Tokenizer()\n",
|
899 |
+
"\ttokenizer.fit_on_texts(lines)\n",
|
900 |
+
"\treturn tokenizer\n",
|
901 |
+
"\n",
|
902 |
+
"# calculate the length of the description with the most words\n",
|
903 |
+
"def max_length(descriptions):\n",
|
904 |
+
"\tlines = to_lines(descriptions)\n",
|
905 |
+
"\treturn max(len(d.split()) for d in lines)\n",
|
906 |
+
"\n",
|
907 |
+
"# map an integer to a word\n",
|
908 |
+
"def word_for_id(integer, tokenizer):\n",
|
909 |
+
"\tfor word, index in tokenizer.word_index.items():\n",
|
910 |
+
"\t\tif index == integer:\n",
|
911 |
+
"\t\t\treturn word\n",
|
912 |
+
"\treturn None "
|
913 |
+
]
|
914 |
+
},
|
915 |
+
{
|
916 |
+
"cell_type": "code",
|
917 |
+
"source": [
|
918 |
+
"from tensorflow.keras.preprocessing.sequence import pad_sequences\n",
|
919 |
+
"import numpy as np\n",
|
920 |
+
"def generate_desc(model, tokenizer, photo, max_length):\n",
|
921 |
+
"\t# seed the generation process\n",
|
922 |
+
"\tin_text = 'startseq'\n",
|
923 |
+
"\t# iterate over the whole length of the sequence\n",
|
924 |
+
"\tfor i in range(max_length):\n",
|
925 |
+
"\t\t# integer encode input sequence\n",
|
926 |
+
"\t\tsequence = tokenizer.texts_to_sequences([in_text])[0]\n",
|
927 |
+
"\t\t# pad input\n",
|
928 |
+
"\t\tsequence = pad_sequences([sequence], maxlen=max_length)\n",
|
929 |
+
"\t\t# predict next word\n",
|
930 |
+
"\t\tyhat = model.predict([photo,sequence], verbose=0)\n",
|
931 |
+
"\t\t# convert probability to integer\n",
|
932 |
+
"\t\tyhat = np.argmax(yhat)\n",
|
933 |
+
"\t\t# map integer to word\n",
|
934 |
+
"\t\tword = word_for_id(yhat, tokenizer)\n",
|
935 |
+
"\t\t# stop if we cannot map the word\n",
|
936 |
+
"\t\tif word is None:\n",
|
937 |
+
"\t\t\tbreak\n",
|
938 |
+
"\t\t# append as input for generating the next word\n",
|
939 |
+
"\t\tin_text += ' ' + word\n",
|
940 |
+
"\t\t# stop if we predict the end of the sequence\n",
|
941 |
+
"\t\tif word == 'endseq':\n",
|
942 |
+
"\t\t\tbreak\n",
|
943 |
+
"\treturn in_text"
|
944 |
+
],
|
945 |
+
"metadata": {
|
946 |
+
"id": "Needd4uQm2gZ"
|
947 |
+
},
|
948 |
+
"execution_count": 113,
|
949 |
+
"outputs": []
|
950 |
+
},
|
951 |
+
{
|
952 |
+
"cell_type": "code",
|
953 |
+
"execution_count": 114,
|
954 |
+
"metadata": {
|
955 |
+
"id": "PrCXWKP8E1pt"
|
956 |
+
},
|
957 |
+
"outputs": [],
|
958 |
+
"source": [
|
959 |
+
"# evaluated the skill of model\n",
|
960 |
+
"from nltk.translate.bleu_score import corpus_bleu\n",
|
961 |
+
"def evaluate_model(model, descriptions, photos, tokenizer, max_length):\n",
|
962 |
+
"\tactual, predicted = list(), list()\n",
|
963 |
+
"\t# step over the whole set\n",
|
964 |
+
"\tfor key, desc_list in descriptions.items():\n",
|
965 |
+
"\t\t# generate description\n",
|
966 |
+
"\t\tyhat = generate_desc(model, tokenizer, photos[key], max_length)\n",
|
967 |
+
"\t\t# store actual and predicted\n",
|
968 |
+
"\t\treferences = [d.split() for d in desc_list]\n",
|
969 |
+
"\t\tactual.append(references)\n",
|
970 |
+
"\t\tpredicted.append(yhat.split())\n",
|
971 |
+
"\t# calculate BLEU score\n",
|
972 |
+
"\tprint('BLEU-1: %f' % corpus_bleu(actual, predicted, weights=(1.0, 0, 0, 0)))\n",
|
973 |
+
"\tprint('BLEU-2: %f' % corpus_bleu(actual, predicted, weights=(0.5, 0.5, 0, 0)))\n",
|
974 |
+
"\tprint('BLEU-3: %f' % corpus_bleu(actual, predicted, weights=(0.3, 0.3, 0.3, 0)))\n",
|
975 |
+
"\tprint('BLEU-4: %f' % corpus_bleu(actual, predicted, weights=(0.25, 0.25, 0.25, 0.25)))"
|
976 |
+
]
|
977 |
+
},
|
978 |
+
{
|
979 |
+
"cell_type": "code",
|
980 |
+
"execution_count": 115,
|
981 |
+
"metadata": {
|
982 |
+
"colab": {
|
983 |
+
"base_uri": "https://localhost:8080/"
|
984 |
+
},
|
985 |
+
"id": "PwYhBAiYbOFN",
|
986 |
+
"outputId": "a253af6f-79d6-408b-ade8-ebbe4f8d2426"
|
987 |
+
},
|
988 |
+
"outputs": [
|
989 |
+
{
|
990 |
+
"output_type": "stream",
|
991 |
+
"name": "stdout",
|
992 |
+
"text": [
|
993 |
+
"Dataset: 6000\n",
|
994 |
+
"train_descriptions= 6000\n",
|
995 |
+
"photos: train= 6000\n",
|
996 |
+
"Vocab size: 7268\n",
|
997 |
+
"Description Length: 33\n"
|
998 |
+
]
|
999 |
+
}
|
1000 |
+
],
|
1001 |
+
"source": [
|
1002 |
+
"#load train dataset\n",
|
1003 |
+
"import tensorflow as tf\n",
|
1004 |
+
"filename = \"/content/drive/MyDrive/Image_Captioning_Project/Flickr_8k.trainImages.txt\"\n",
|
1005 |
+
"train = load_set(filename)\n",
|
1006 |
+
"print(\"Dataset: %d\" %len(train))\n",
|
1007 |
+
"\n",
|
1008 |
+
"train_descriptions = load_clean_descriptions(\"/content/drive/MyDrive/Image_Captioning_Project/descriptions.txt\", train)\n",
|
1009 |
+
"print(\"train_descriptions= %d\" %len(train_descriptions))\n",
|
1010 |
+
"\n",
|
1011 |
+
"train_feature = load_photo_features(\"/content/drive/MyDrive/Image_Captioning_Project/features.pkl\", train)\n",
|
1012 |
+
"print(\"photos: train= %d\" %len(train_feature))\n",
|
1013 |
+
"\n",
|
1014 |
+
"tokenizer = create_tokenizer(train_descriptions)\n",
|
1015 |
+
"vocab_size = len(tokenizer.word_index)+1\n",
|
1016 |
+
"print(\"Vocab size: %d\" %vocab_size)\n",
|
1017 |
+
"\n",
|
1018 |
+
"max_length = max_length(train_descriptions)\n",
|
1019 |
+
"print('Description Length: %d' % max_length)"
|
1020 |
+
]
|
1021 |
+
},
|
1022 |
+
{
|
1023 |
+
"cell_type": "code",
|
1024 |
+
"execution_count": 116,
|
1025 |
+
"metadata": {
|
1026 |
+
"colab": {
|
1027 |
+
"base_uri": "https://localhost:8080/"
|
1028 |
+
},
|
1029 |
+
"id": "S9p7vYFZ7Y_J",
|
1030 |
+
"outputId": "48124f24-c348-4cd7-a8bb-6e30e7c26060"
|
1031 |
+
},
|
1032 |
+
"outputs": [
|
1033 |
+
{
|
1034 |
+
"output_type": "stream",
|
1035 |
+
"name": "stdout",
|
1036 |
+
"text": [
|
1037 |
+
"Dataset: 1000\n",
|
1038 |
+
"Description= 1000\n",
|
1039 |
+
"photos: test=1000"
|
1040 |
+
]
|
1041 |
+
},
|
1042 |
+
{
|
1043 |
+
"output_type": "stream",
|
1044 |
+
"name": "stderr",
|
1045 |
+
"text": [
|
1046 |
+
"WARNING:tensorflow:Layer lstm_1 will not use cuDNN kernels since it doesn't meet the criteria. It will use a generic GPU kernel as fallback when running on GPU.\n"
|
1047 |
+
]
|
1048 |
+
},
|
1049 |
+
{
|
1050 |
+
"output_type": "stream",
|
1051 |
+
"name": "stdout",
|
1052 |
+
"text": [
|
1053 |
+
"\n"
|
1054 |
+
]
|
1055 |
+
}
|
1056 |
+
],
|
1057 |
+
"source": [
|
1058 |
+
"filename = \"/content/drive/MyDrive/Image_Captioning_Project/Flickr_8k.testImages.txt\"\n",
|
1059 |
+
"test = load_set(filename)\n",
|
1060 |
+
"print(\"Dataset: %d\" %len(test))\n",
|
1061 |
+
"test_description = load_clean_descriptions(\"/content/drive/MyDrive/Image_Captioning_Project/descriptions.txt\", test)\n",
|
1062 |
+
"print(\"Description= %d\" %len(test_description))\n",
|
1063 |
+
"test_features = load_photo_features(\"/content/drive/MyDrive/Image_Captioning_Project/features.pkl\", test)\n",
|
1064 |
+
"print(\"photos: test=%d\" % len(test_features))\n",
|
1065 |
+
"\n",
|
1066 |
+
"from keras.models import load_model\n",
|
1067 |
+
"filename = \"/content/drive/MyDrive/Image_Captioning_Project/model_18.h5\"\n",
|
1068 |
+
"model = load_model(filename)"
|
1069 |
+
]
|
1070 |
+
},
|
1071 |
+
{
|
1072 |
+
"cell_type": "code",
|
1073 |
+
"source": [
|
1074 |
+
"# evaluate_model(model, test_description, test_features, tokenizer, max_length)"
|
1075 |
+
],
|
1076 |
+
"metadata": {
|
1077 |
+
"id": "URns1LFyOaPZ"
|
1078 |
+
},
|
1079 |
+
"execution_count": 117,
|
1080 |
+
"outputs": []
|
1081 |
+
},
|
1082 |
+
{
|
1083 |
+
"cell_type": "code",
|
1084 |
+
"execution_count": 118,
|
1085 |
+
"metadata": {
|
1086 |
+
"id": "9dVz3rRrKvAi"
|
1087 |
+
},
|
1088 |
+
"outputs": [],
|
1089 |
+
"source": [
|
1090 |
+
"from pickle import load\n",
|
1091 |
+
"from numpy import argmax\n",
|
1092 |
+
"from tensorflow.keras.preprocessing.sequence import pad_sequences\n",
|
1093 |
+
"from keras.applications.vgg16 import VGG16\n",
|
1094 |
+
"from tensorflow.keras.preprocessing.image import load_img\n",
|
1095 |
+
"from tensorflow.keras.preprocessing.image import img_to_array\n",
|
1096 |
+
"from keras.applications.vgg16 import preprocess_input\n",
|
1097 |
+
"from keras.models import Model\n",
|
1098 |
+
"from keras.models import load_model\n",
|
1099 |
+
"# from keras.preprocessing.text import Tokenizer"
|
1100 |
+
]
|
1101 |
+
},
|
1102 |
+
{
|
1103 |
+
"cell_type": "code",
|
1104 |
+
"execution_count": 119,
|
1105 |
+
"metadata": {
|
1106 |
+
"id": "qvlspE-eitvS"
|
1107 |
+
},
|
1108 |
+
"outputs": [],
|
1109 |
+
"source": [
|
1110 |
+
"def extract_features(filename):\n",
|
1111 |
+
"\t# load the model\n",
|
1112 |
+
"\tmodel = VGG16()\n",
|
1113 |
+
"\t# re-structure the model\n",
|
1114 |
+
"\tmodel.layers.pop()\n",
|
1115 |
+
"\tmodel = Model(inputs=model.inputs, outputs=model.layers[-2].output)\n",
|
1116 |
+
"\t# load the photo\n",
|
1117 |
+
"\timage = load_img(filename, target_size=(224, 224))\n",
|
1118 |
+
"\t# convert the image pixels to a numpy array\n",
|
1119 |
+
"\timage = img_to_array(image)\n",
|
1120 |
+
"\t# reshape data for the model\n",
|
1121 |
+
"\timage = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))\n",
|
1122 |
+
"\t# prepare the image for the VGG model\n",
|
1123 |
+
"\timage = preprocess_input(image)\n",
|
1124 |
+
"\t# get features\n",
|
1125 |
+
"\tfeature = model.predict(image, verbose=0)\n",
|
1126 |
+
"\treturn feature"
|
1127 |
+
]
|
1128 |
+
},
|
1129 |
+
{
|
1130 |
+
"cell_type": "code",
|
1131 |
+
"execution_count": 124,
|
1132 |
+
"metadata": {
|
1133 |
+
"colab": {
|
1134 |
+
"base_uri": "https://localhost:8080/"
|
1135 |
+
},
|
1136 |
+
"id": "ao4swPUfj1Ql",
|
1137 |
+
"outputId": "b6c92906-91c1-44c2-c958-409ca4a30d8b"
|
1138 |
+
},
|
1139 |
+
"outputs": [
|
1140 |
+
{
|
1141 |
+
"output_type": "stream",
|
1142 |
+
"name": "stderr",
|
1143 |
+
"text": [
|
1144 |
+
"WARNING:tensorflow:Layer lstm_1 will not use cuDNN kernels since it doesn't meet the criteria. It will use a generic GPU kernel as fallback when running on GPU.\n"
|
1145 |
+
]
|
1146 |
+
},
|
1147 |
+
{
|
1148 |
+
"output_type": "stream",
|
1149 |
+
"name": "stdout",
|
1150 |
+
"text": [
|
1151 |
+
"startseq dog is running through the snow endseq\n"
|
1152 |
+
]
|
1153 |
+
}
|
1154 |
+
],
|
1155 |
+
"source": [
|
1156 |
+
"from pickle import load\n",
|
1157 |
+
"from tensorflow.keras.preprocessing.text import Tokenizer\n",
|
1158 |
+
"\n",
|
1159 |
+
"tokenizer = load(open('/content/tokenizer1.pkl', 'rb'))\n",
|
1160 |
+
"max_len = 34\n",
|
1161 |
+
"model = load_model('/content/drive/MyDrive/Image_Captioning_Project/model_18.h5')\n",
|
1162 |
+
"photo = extract_features(\"/content/drive/MyDrive/Image_Captioning_Project/Images/101654506_8eb26cfb60.jpg\")\n",
|
1163 |
+
"tokenizer.analyzer = None\n",
|
1164 |
+
"description = generate_desc(model, tokenizer, photo, max_len)\n",
|
1165 |
+
"print(description)"
|
1166 |
+
]
|
1167 |
+
},
|
1168 |
+
{
|
1169 |
+
"cell_type": "code",
|
1170 |
+
"execution_count": 121,
|
1171 |
+
"metadata": {
|
1172 |
+
"colab": {
|
1173 |
+
"base_uri": "https://localhost:8080/"
|
1174 |
+
},
|
1175 |
+
"id": "T1IsisClmnJI",
|
1176 |
+
"outputId": "cb6f632f-9792-4dce-aa58-174f60a94ecf"
|
1177 |
+
},
|
1178 |
+
"outputs": [
|
1179 |
+
{
|
1180 |
+
"output_type": "stream",
|
1181 |
+
"name": "stdout",
|
1182 |
+
"text": [
|
1183 |
+
"man in red shirt is standing on rock\n"
|
1184 |
+
]
|
1185 |
+
}
|
1186 |
+
],
|
1187 |
+
"source": [
|
1188 |
+
"query = description\n",
|
1189 |
+
"stopwords = ['startseq','endseq']\n",
|
1190 |
+
"querywords = query.split()\n",
|
1191 |
+
"\n",
|
1192 |
+
"resultwords = [word for word in querywords if word.lower() not in stopwords]\n",
|
1193 |
+
"result = ' '.join(resultwords)\n",
|
1194 |
+
"\n",
|
1195 |
+
"print(result)"
|
1196 |
+
]
|
1197 |
+
},
|
1198 |
+
{
|
1199 |
+
"cell_type": "code",
|
1200 |
+
"source": [],
|
1201 |
+
"metadata": {
|
1202 |
+
"id": "vO4XsnKBEUeg"
|
1203 |
+
},
|
1204 |
+
"execution_count": 121,
|
1205 |
+
"outputs": []
|
1206 |
+
}
|
1207 |
+
],
|
1208 |
+
"metadata": {
|
1209 |
+
"accelerator": "GPU",
|
1210 |
+
"colab": {
|
1211 |
+
"provenance": [],
|
1212 |
+
"gpuType": "T4"
|
1213 |
+
},
|
1214 |
+
"kernelspec": {
|
1215 |
+
"display_name": "Python 3",
|
1216 |
+
"name": "python3"
|
1217 |
+
},
|
1218 |
+
"language_info": {
|
1219 |
+
"name": "python"
|
1220 |
+
}
|
1221 |
+
},
|
1222 |
+
"nbformat": 4,
|
1223 |
+
"nbformat_minor": 0
|
1224 |
+
}
|
img_captioning_project.py
ADDED
@@ -0,0 +1,581 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
"""img-captioning-project.ipynb
|
3 |
+
|
4 |
+
Automatically generated by Colaboratory.
|
5 |
+
|
6 |
+
Original file is located at
|
7 |
+
https://colab.research.google.com/drive/1wZSpAsjNfRWhMdsclYJT6o2B-YBZc1yH
|
8 |
+
"""
|
9 |
+
|
10 |
+
from os import listdir
|
11 |
+
from numpy import array
|
12 |
+
from keras.models import Model
|
13 |
+
from pickle import dump
|
14 |
+
from keras.applications.vgg16 import VGG16
|
15 |
+
from tensorflow.keras.preprocessing.image import load_img
|
16 |
+
from tensorflow.keras.preprocessing.image import img_to_array
|
17 |
+
from tensorflow.keras.preprocessing.sequence import pad_sequences
|
18 |
+
from keras.preprocessing.text import Tokenizer
|
19 |
+
from keras.utils import to_categorical
|
20 |
+
from keras.utils import plot_model
|
21 |
+
from keras.models import Model
|
22 |
+
from keras.layers import Input
|
23 |
+
from keras.layers import Dense
|
24 |
+
from keras.layers import LSTM
|
25 |
+
from keras.layers import Embedding
|
26 |
+
from keras.layers import Dropout
|
27 |
+
from tensorflow.keras.layers import Add
|
28 |
+
from keras.callbacks import ModelCheckpoint
|
29 |
+
|
30 |
+
from keras.applications.vgg16 import VGG16, preprocess_input
|
31 |
+
model = VGG16()
|
32 |
+
# re-structure the model
|
33 |
+
model.layers.pop()
|
34 |
+
model = Model(inputs=model.inputs, outputs=model.layers[-2].output)
|
35 |
+
# summarize
|
36 |
+
print(model.summary())
|
37 |
+
|
38 |
+
from os import listdir
|
39 |
+
from pickle import dump
|
40 |
+
from tensorflow.keras.preprocessing.image import img_to_array, load_img
|
41 |
+
from keras.models import Model
|
42 |
+
|
43 |
+
# extract feature from each photo in directory
|
44 |
+
def extract_features(directory):
|
45 |
+
# extract features from each photo
|
46 |
+
features = dict()
|
47 |
+
for name in listdir(directory):
|
48 |
+
# load an image from file
|
49 |
+
filename = directory + '/' + name
|
50 |
+
image = load_img(filename, target_size=(224, 224))
|
51 |
+
# convert the image pixels to a numpy array
|
52 |
+
image = img_to_array(image)
|
53 |
+
# reshape data for the model
|
54 |
+
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
|
55 |
+
# prepare the image for the VGG model
|
56 |
+
image = preprocess_input(image)
|
57 |
+
# get features
|
58 |
+
feature = model.predict(image, verbose=0)
|
59 |
+
# get image id
|
60 |
+
image_id = name.split('.')[0]
|
61 |
+
# store feature
|
62 |
+
features[image_id] = feature
|
63 |
+
print('>%s' % name)
|
64 |
+
return features
|
65 |
+
|
66 |
+
# directory = "/content/drive/MyDrive/Image_Captioning_Project/Images"
|
67 |
+
# features = extract_features(directory)
|
68 |
+
# dump(features, open('features1.pkl', 'wb'))
|
69 |
+
# print("Extracted Features: %d" %len(features))
|
70 |
+
|
71 |
+
!ls
|
72 |
+
|
73 |
+
import string
|
74 |
+
from nltk.tokenize import word_tokenize
|
75 |
+
|
76 |
+
def load_doc(filename):
|
77 |
+
# open the file as read only
|
78 |
+
file = open(filename, 'r')
|
79 |
+
# read all text
|
80 |
+
text = file.read()
|
81 |
+
# close the file
|
82 |
+
file.close()
|
83 |
+
return text
|
84 |
+
|
85 |
+
def load_descriptions(doc):
|
86 |
+
mapping = dict()
|
87 |
+
# process lines
|
88 |
+
for line in doc.split('\n'):
|
89 |
+
# split line by white space
|
90 |
+
tokens = line.split()
|
91 |
+
if len(line) < 2:
|
92 |
+
continue
|
93 |
+
# take the first token as the image id, the rest as the description
|
94 |
+
image_id, image_desc = tokens[0], tokens[1:]
|
95 |
+
# remove filename from image id
|
96 |
+
image_id = image_id.split('.')[0]
|
97 |
+
# convert description tokens back to string
|
98 |
+
image_desc = ' '.join(image_desc)
|
99 |
+
# create the list if needed
|
100 |
+
if image_id not in mapping:
|
101 |
+
mapping[image_id] = list()
|
102 |
+
# store description
|
103 |
+
mapping[image_id].append(image_desc)
|
104 |
+
return mapping
|
105 |
+
|
106 |
+
"""## Preprocessing of Text
|
107 |
+
|
108 |
+
1. Convert all words to lowercase.
|
109 |
+
2. Remove all punctuation.
|
110 |
+
3. Remove all words that are one character or less in length (e.g. ‘a’).
|
111 |
+
4. Remove all words with numbers in them.
|
112 |
+
"""
|
113 |
+
|
114 |
+
def clean_descriptions(descriptions):
|
115 |
+
# prepare translation table for removing punctuation
|
116 |
+
table = str.maketrans('', '', string.punctuation)
|
117 |
+
for key, desc_list in descriptions.items():
|
118 |
+
for i in range(len(desc_list)):
|
119 |
+
desc = desc_list[i]
|
120 |
+
# tokenize
|
121 |
+
desc = desc.split()
|
122 |
+
# convert to lower case
|
123 |
+
desc = [word.lower() for word in desc]
|
124 |
+
# remove punctuation from each token
|
125 |
+
desc = [w.translate(table) for w in desc]
|
126 |
+
# remove hanging 's' and 'a'
|
127 |
+
desc = [word for word in desc if len(word)>1]
|
128 |
+
# remove tokens with numbers in them
|
129 |
+
desc = [word for word in desc if word.isalpha()]
|
130 |
+
# store as string
|
131 |
+
desc_list[i] = ' '.join(desc)
|
132 |
+
def to_vocabulary(descriptions):
|
133 |
+
# build a list of all description strings
|
134 |
+
all_desc = set()
|
135 |
+
for key in descriptions.keys():
|
136 |
+
[all_desc.update(d.split()) for d in descriptions[key]]
|
137 |
+
return all_desc
|
138 |
+
|
139 |
+
def save_descriptions(descriptions, filename):
|
140 |
+
lines = list()
|
141 |
+
for key, desc_list in descriptions.items():
|
142 |
+
for desc in desc_list:
|
143 |
+
lines.append(key + " " + desc)
|
144 |
+
data = '\n'.join(lines)
|
145 |
+
file = open(filename, 'w')
|
146 |
+
file.write(data)
|
147 |
+
file.close()
|
148 |
+
|
149 |
+
import nltk
|
150 |
+
nltk.download('punkt')
|
151 |
+
|
152 |
+
filename = "/content/drive/MyDrive/Image_Captioning_Project/Flickr8k.token.txt"
|
153 |
+
doc = load_doc(filename)
|
154 |
+
descriptions = load_descriptions(doc)
|
155 |
+
print("Loaded: %d" %len(descriptions))
|
156 |
+
|
157 |
+
#clean desc
|
158 |
+
clean_descriptions(descriptions)
|
159 |
+
vocab = to_vocabulary(descriptions)
|
160 |
+
print("Vocab size: %d" %len(vocab))
|
161 |
+
|
162 |
+
# save_descriptions(descriptions, "descriptions2.txt")
|
163 |
+
|
164 |
+
"""### Developing Deep Learning Model
|
165 |
+
|
166 |
+
#### This section is divided into the following parts:
|
167 |
+
|
168 |
+
Loading Data.
|
169 |
+
Defining the Model.
|
170 |
+
Fitting the Model.
|
171 |
+
"""
|
172 |
+
|
173 |
+
from pickle import dump
|
174 |
+
|
175 |
+
#load into memory
|
176 |
+
def load_doc(filename):
|
177 |
+
# open the file as read only
|
178 |
+
file = open(filename, 'r')
|
179 |
+
# read all text
|
180 |
+
text = file.read()
|
181 |
+
# close the file
|
182 |
+
file.close()
|
183 |
+
return text
|
184 |
+
|
185 |
+
#pre-defined list of photo identifier
|
186 |
+
def load_set(filename):
|
187 |
+
doc = load_doc(filename)
|
188 |
+
dataset = list()
|
189 |
+
for line in doc.split("\n"):
|
190 |
+
if len(line) < 1:
|
191 |
+
continue
|
192 |
+
identifier = line.split('.')[0]
|
193 |
+
dataset.append(identifier)
|
194 |
+
return set(dataset)
|
195 |
+
|
196 |
+
"""load_clean_descriptions() that loads the cleaned text descriptions from ‘descriptions.txt‘ for a given set of identifiers and returns a dictionary of identifiers to lists of text descriptions.
|
197 |
+
|
198 |
+
The model we will develop will generate a caption given a photo, and the caption will be generated one word at a time. The sequence of previously generated words will be provided as input. Therefore, we will need a ‘first word’ to kick-off the generation process and a ‘last word‘ to signal the end of the caption.
|
199 |
+
|
200 |
+
We will use the strings ‘startseq‘ and ‘endseq‘ for this purpose.
|
201 |
+
"""
|
202 |
+
|
203 |
+
def load_photo_features(features, dataset):
|
204 |
+
all_features = load(open(features, 'rb'))
|
205 |
+
features = {k: all_features[k] for k in dataset}
|
206 |
+
return features
|
207 |
+
|
208 |
+
def load_clean_descriptions(filename, dataset):
|
209 |
+
# load document
|
210 |
+
doc = load_doc(filename)
|
211 |
+
descriptions = dict()
|
212 |
+
for line in doc.split('\n'):
|
213 |
+
# split line by white space
|
214 |
+
tokens = line.split()
|
215 |
+
# split id from description
|
216 |
+
image_id, image_desc = tokens[0], tokens[1:]
|
217 |
+
# skip images not in the set
|
218 |
+
if image_id in dataset:
|
219 |
+
# create list
|
220 |
+
if image_id not in descriptions:
|
221 |
+
descriptions[image_id] = list()
|
222 |
+
# wrap description in tokens
|
223 |
+
desc = 'startseq ' + ' '.join(image_desc) + ' endseq'
|
224 |
+
# store
|
225 |
+
descriptions[image_id].append(desc)
|
226 |
+
return descriptions
|
227 |
+
|
228 |
+
from pickle import load
|
229 |
+
|
230 |
+
# load training dataset (6K)
|
231 |
+
filename = '/content/drive/MyDrive/Image_Captioning_Project/Flickr_8k.trainImages.txt'
|
232 |
+
train = load_set(filename)
|
233 |
+
print('Dataset: %d' % len(train))
|
234 |
+
# descriptions
|
235 |
+
train_descriptions = load_clean_descriptions('/content/drive/MyDrive/Image_Captioning_Project/descriptions1.txt', train)
|
236 |
+
print('Descriptions: train=%d' % len(train_descriptions))
|
237 |
+
# photo features
|
238 |
+
train_features = load_photo_features('/content/drive/MyDrive/Image_Captioning_Project/features.pkl', train)
|
239 |
+
print('Photos: train=%d' % len(train_features))
|
240 |
+
|
241 |
+
def load_doc(filename):
|
242 |
+
# open the file as read only
|
243 |
+
file = open(filename, 'r')
|
244 |
+
# read all text
|
245 |
+
text = file.read()
|
246 |
+
# close the file
|
247 |
+
file.close
|
248 |
+
return text
|
249 |
+
|
250 |
+
def load_set(filename):
|
251 |
+
doc = load_doc(filename)
|
252 |
+
dataset = list()
|
253 |
+
for line in doc.split("\n"):
|
254 |
+
if len(line) < 1:
|
255 |
+
continue
|
256 |
+
identifier = line.split('.')[0]
|
257 |
+
dataset.append(identifier)
|
258 |
+
return set(dataset)
|
259 |
+
|
260 |
+
def load_clean_descriptions(filename, dataset):
|
261 |
+
# load document
|
262 |
+
doc = load_doc(filename)
|
263 |
+
descriptions = dict()
|
264 |
+
for line in doc.split('\n'):
|
265 |
+
# split line by white space
|
266 |
+
tokens = line.split()
|
267 |
+
# split id from description
|
268 |
+
image_id, image_desc = tokens[0], tokens[1:]
|
269 |
+
# skip images not in the set
|
270 |
+
if image_id in dataset:
|
271 |
+
# create list
|
272 |
+
if image_id not in descriptions:
|
273 |
+
descriptions[image_id] = list()
|
274 |
+
# wrap description in tokens
|
275 |
+
desc = 'startseq ' + ' '.join(image_desc) + ' endseq'
|
276 |
+
# store
|
277 |
+
descriptions[image_id].append(desc)
|
278 |
+
return descriptions
|
279 |
+
|
280 |
+
def load_photo_features(filename, dataset):
|
281 |
+
# load all features
|
282 |
+
all_features = load(open(filename, 'rb'))
|
283 |
+
# filter features
|
284 |
+
features = {k: all_features[k] for k in dataset}
|
285 |
+
return features
|
286 |
+
|
287 |
+
# dict to clean list
|
288 |
+
def to_lines(descriptions):
|
289 |
+
all_desc = list()
|
290 |
+
for key in descriptions.keys():
|
291 |
+
[all_desc.append(d) for d in descriptions[key]]
|
292 |
+
return all_desc
|
293 |
+
|
294 |
+
def create_tokenizer(descriptions):
|
295 |
+
lines = to_lines(descriptions)
|
296 |
+
tokenizer = Tokenizer()
|
297 |
+
tokenizer.fit_on_texts(lines)
|
298 |
+
return tokenizer
|
299 |
+
|
300 |
+
#len of description
|
301 |
+
def max_length(description):
|
302 |
+
lines = to_lines(description)
|
303 |
+
return max(len(d.split()) for d in lines)
|
304 |
+
|
305 |
+
# create input and output sequence
|
306 |
+
def create_sequences(tokenizer, max_length, desc_list, photo):
|
307 |
+
X1, X2, y = list(), list(), list()
|
308 |
+
# walk through each description for the image
|
309 |
+
for desc in desc_list:
|
310 |
+
# encode the sequence
|
311 |
+
seq = tokenizer.texts_to_sequences([desc])[0]
|
312 |
+
# split one sequence into multiple X,y pairs
|
313 |
+
for i in range(1, len(seq)):
|
314 |
+
# split into input and output pair
|
315 |
+
in_seq, out_seq = seq[:i], seq[i]
|
316 |
+
# pad input sequence
|
317 |
+
in_seq = pad_sequences([in_seq], maxlen=max_length)[0]
|
318 |
+
# encode output sequence
|
319 |
+
out_seq = to_categorical([out_seq], num_classes=vocab_size)[0]
|
320 |
+
# store
|
321 |
+
X1.append(photo)
|
322 |
+
X2.append(in_seq)
|
323 |
+
y.append(out_seq)
|
324 |
+
return array(X1), array(X2), array(y)
|
325 |
+
|
326 |
+
"""## Model building"""
|
327 |
+
|
328 |
+
from tensorflow.keras.layers import add
|
329 |
+
def define_model(vocab_size, max_length):
|
330 |
+
# feature extractor model
|
331 |
+
inputs1 = Input(shape=(1000,))
|
332 |
+
fe1 = Dropout(0.5)(inputs1)
|
333 |
+
fe2 = Dense(256, activation='relu')(fe1)
|
334 |
+
# sequence model
|
335 |
+
inputs2 = Input(shape=(max_length,))
|
336 |
+
se1 = Embedding(vocab_size,output_dim=256, mask_zero=True)(inputs2)
|
337 |
+
se2 = Dropout(0.5)(se1)
|
338 |
+
se3 = LSTM(256)(se2)
|
339 |
+
# decoder model
|
340 |
+
decoder1 = add([fe2, se3])
|
341 |
+
decoder2 = Dense(256, activation='relu')(decoder1)
|
342 |
+
outputs = Dense(vocab_size, activation='softmax')(decoder2)
|
343 |
+
# tie it together [image, seq] [word]
|
344 |
+
model = Model(inputs=[inputs1, inputs2], outputs=outputs)
|
345 |
+
model.compile(loss='categorical_crossentropy', optimizer='adam')
|
346 |
+
# summarize model
|
347 |
+
print(model.summary())
|
348 |
+
return model
|
349 |
+
|
350 |
+
# load batch of data
|
351 |
+
def data_generator(descriptions, photos, tokenizer, max_length):
|
352 |
+
# loop for ever over images
|
353 |
+
while 1:
|
354 |
+
for key, desc_list in descriptions.items():
|
355 |
+
# retrieve the photo feature
|
356 |
+
photo = photos[key][0]
|
357 |
+
in_img, in_seq, out_word = create_sequences(tokenizer, max_length, desc_list, photo)
|
358 |
+
yield [[in_img, in_seq], out_word]
|
359 |
+
|
360 |
+
#load train dataset
|
361 |
+
import tensorflow as tf
|
362 |
+
filename = "/content/drive/MyDrive/Image_Captioning_Project/Flickr_8k.trainImages.txt"
|
363 |
+
train = load_set(filename)
|
364 |
+
print("Dataset: %d" %len(train))
|
365 |
+
|
366 |
+
train_descriptions = load_clean_descriptions("/content/drive/MyDrive/Image_Captioning_Project/descriptions1.txt", train)
|
367 |
+
print("train_descriptions= %d" %len(train_descriptions))
|
368 |
+
|
369 |
+
train_feature = load_photo_features("/content/drive/MyDrive/Image_Captioning_Project/features.pkl", train)
|
370 |
+
print("photos: train= %d" %len(train_feature))
|
371 |
+
|
372 |
+
tokenizer = create_tokenizer(train_descriptions)
|
373 |
+
vocab_size = len(tokenizer.word_index)+1
|
374 |
+
print("Vocab size: %d" %vocab_size)
|
375 |
+
|
376 |
+
max_length = max_length(train_descriptions)
|
377 |
+
print('Description Length: %d' % max_length)
|
378 |
+
|
379 |
+
import pickle
|
380 |
+
|
381 |
+
# Dump the tokenizer using pickle
|
382 |
+
with open('tokenizer1.pkl', 'wb') as f:
|
383 |
+
pickle.dump(tokenizer, f)
|
384 |
+
|
385 |
+
#train model
|
386 |
+
# model = define_model(vocab_size, max_length)
|
387 |
+
# filename = "/content/drive/MyDrive/Image_Captioning_Project/model_18.h5"
|
388 |
+
# model = load_model(filename)
|
389 |
+
# epochs = 4
|
390 |
+
# steps = len(train_descriptions)
|
391 |
+
# model.summary()
|
392 |
+
|
393 |
+
# for i in range(epochs):
|
394 |
+
# #create data generator
|
395 |
+
# generator = data_generator(train_descriptions, train_feature, tokenizer, max_len)
|
396 |
+
# model.fit(generator, epochs=1, steps_per_epoch = steps, verbose=1)
|
397 |
+
# model.save("model_" + str(i) + ".h5")
|
398 |
+
|
399 |
+
def load_doc(filename):
|
400 |
+
# open the file as read only
|
401 |
+
file = open(filename, 'r')
|
402 |
+
# read all text
|
403 |
+
text = file.read()
|
404 |
+
# close the file
|
405 |
+
file.close()
|
406 |
+
return text
|
407 |
+
|
408 |
+
# load a pre-defined list of photo identifiers
|
409 |
+
def load_set(filename):
|
410 |
+
doc = load_doc(filename)
|
411 |
+
dataset = list()
|
412 |
+
# process line by line
|
413 |
+
for line in doc.split('\n'):
|
414 |
+
# skip empty lines
|
415 |
+
if len(line) < 1:
|
416 |
+
continue
|
417 |
+
# get the image identifier
|
418 |
+
identifier = line.split('.')[0]
|
419 |
+
dataset.append(identifier)
|
420 |
+
return set(dataset)
|
421 |
+
|
422 |
+
def load_photo_features(filename, dataset):
|
423 |
+
# load all features
|
424 |
+
all_features = load(open(filename, 'rb'))
|
425 |
+
# filter features
|
426 |
+
features = {k: all_features[k] for k in dataset}
|
427 |
+
return features
|
428 |
+
|
429 |
+
# covert a dictionary of clean descriptions to a list of descriptions
|
430 |
+
def to_lines(descriptions):
|
431 |
+
all_desc = list()
|
432 |
+
for key in descriptions.keys():
|
433 |
+
[all_desc.append(d) for d in descriptions[key]]
|
434 |
+
return all_desc
|
435 |
+
|
436 |
+
# fit a tokenizer given caption descriptions
|
437 |
+
def create_tokenizer(descriptions):
|
438 |
+
lines = to_lines(descriptions)
|
439 |
+
tokenizer = Tokenizer()
|
440 |
+
tokenizer.fit_on_texts(lines)
|
441 |
+
return tokenizer
|
442 |
+
|
443 |
+
# calculate the length of the description with the most words
|
444 |
+
def max_length(descriptions):
|
445 |
+
lines = to_lines(descriptions)
|
446 |
+
return max(len(d.split()) for d in lines)
|
447 |
+
|
448 |
+
# map an integer to a word
|
449 |
+
def word_for_id(integer, tokenizer):
|
450 |
+
for word, index in tokenizer.word_index.items():
|
451 |
+
if index == integer:
|
452 |
+
return word
|
453 |
+
return None
|
454 |
+
|
455 |
+
from tensorflow.keras.preprocessing.sequence import pad_sequences
|
456 |
+
import numpy as np
|
457 |
+
def generate_desc(model, tokenizer, photo, max_length):
|
458 |
+
# seed the generation process
|
459 |
+
in_text = 'startseq'
|
460 |
+
# iterate over the whole length of the sequence
|
461 |
+
for i in range(max_length):
|
462 |
+
# integer encode input sequence
|
463 |
+
sequence = tokenizer.texts_to_sequences([in_text])[0]
|
464 |
+
# pad input
|
465 |
+
sequence = pad_sequences([sequence], maxlen=max_length)
|
466 |
+
# predict next word
|
467 |
+
yhat = model.predict([photo,sequence], verbose=0)
|
468 |
+
# convert probability to integer
|
469 |
+
yhat = np.argmax(yhat)
|
470 |
+
# map integer to word
|
471 |
+
word = word_for_id(yhat, tokenizer)
|
472 |
+
# stop if we cannot map the word
|
473 |
+
if word is None:
|
474 |
+
break
|
475 |
+
# append as input for generating the next word
|
476 |
+
in_text += ' ' + word
|
477 |
+
# stop if we predict the end of the sequence
|
478 |
+
if word == 'endseq':
|
479 |
+
break
|
480 |
+
return in_text
|
481 |
+
|
482 |
+
# evaluated the skill of model
|
483 |
+
from nltk.translate.bleu_score import corpus_bleu
|
484 |
+
def evaluate_model(model, descriptions, photos, tokenizer, max_length):
|
485 |
+
actual, predicted = list(), list()
|
486 |
+
# step over the whole set
|
487 |
+
for key, desc_list in descriptions.items():
|
488 |
+
# generate description
|
489 |
+
yhat = generate_desc(model, tokenizer, photos[key], max_length)
|
490 |
+
# store actual and predicted
|
491 |
+
references = [d.split() for d in desc_list]
|
492 |
+
actual.append(references)
|
493 |
+
predicted.append(yhat.split())
|
494 |
+
# calculate BLEU score
|
495 |
+
print('BLEU-1: %f' % corpus_bleu(actual, predicted, weights=(1.0, 0, 0, 0)))
|
496 |
+
print('BLEU-2: %f' % corpus_bleu(actual, predicted, weights=(0.5, 0.5, 0, 0)))
|
497 |
+
print('BLEU-3: %f' % corpus_bleu(actual, predicted, weights=(0.3, 0.3, 0.3, 0)))
|
498 |
+
print('BLEU-4: %f' % corpus_bleu(actual, predicted, weights=(0.25, 0.25, 0.25, 0.25)))
|
499 |
+
|
500 |
+
#load train dataset
|
501 |
+
import tensorflow as tf
|
502 |
+
filename = "/content/drive/MyDrive/Image_Captioning_Project/Flickr_8k.trainImages.txt"
|
503 |
+
train = load_set(filename)
|
504 |
+
print("Dataset: %d" %len(train))
|
505 |
+
|
506 |
+
train_descriptions = load_clean_descriptions("/content/drive/MyDrive/Image_Captioning_Project/descriptions.txt", train)
|
507 |
+
print("train_descriptions= %d" %len(train_descriptions))
|
508 |
+
|
509 |
+
train_feature = load_photo_features("/content/drive/MyDrive/Image_Captioning_Project/features.pkl", train)
|
510 |
+
print("photos: train= %d" %len(train_feature))
|
511 |
+
|
512 |
+
tokenizer = create_tokenizer(train_descriptions)
|
513 |
+
vocab_size = len(tokenizer.word_index)+1
|
514 |
+
print("Vocab size: %d" %vocab_size)
|
515 |
+
|
516 |
+
max_length = max_length(train_descriptions)
|
517 |
+
print('Description Length: %d' % max_length)
|
518 |
+
|
519 |
+
filename = "/content/drive/MyDrive/Image_Captioning_Project/Flickr_8k.testImages.txt"
|
520 |
+
test = load_set(filename)
|
521 |
+
print("Dataset: %d" %len(test))
|
522 |
+
test_description = load_clean_descriptions("/content/drive/MyDrive/Image_Captioning_Project/descriptions.txt", test)
|
523 |
+
print("Description= %d" %len(test_description))
|
524 |
+
test_features = load_photo_features("/content/drive/MyDrive/Image_Captioning_Project/features.pkl", test)
|
525 |
+
print("photos: test=%d" % len(test_features))
|
526 |
+
|
527 |
+
from keras.models import load_model
|
528 |
+
filename = "/content/drive/MyDrive/Image_Captioning_Project/model_18.h5"
|
529 |
+
model = load_model(filename)
|
530 |
+
|
531 |
+
# evaluate_model(model, test_description, test_features, tokenizer, max_length)
|
532 |
+
|
533 |
+
from pickle import load
|
534 |
+
from numpy import argmax
|
535 |
+
from tensorflow.keras.preprocessing.sequence import pad_sequences
|
536 |
+
from keras.applications.vgg16 import VGG16
|
537 |
+
from tensorflow.keras.preprocessing.image import load_img
|
538 |
+
from tensorflow.keras.preprocessing.image import img_to_array
|
539 |
+
from keras.applications.vgg16 import preprocess_input
|
540 |
+
from keras.models import Model
|
541 |
+
from keras.models import load_model
|
542 |
+
# from keras.preprocessing.text import Tokenizer
|
543 |
+
|
544 |
+
def extract_features(filename):
|
545 |
+
# load the model
|
546 |
+
model = VGG16()
|
547 |
+
# re-structure the model
|
548 |
+
model.layers.pop()
|
549 |
+
model = Model(inputs=model.inputs, outputs=model.layers[-2].output)
|
550 |
+
# load the photo
|
551 |
+
image = load_img(filename, target_size=(224, 224))
|
552 |
+
# convert the image pixels to a numpy array
|
553 |
+
image = img_to_array(image)
|
554 |
+
# reshape data for the model
|
555 |
+
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
|
556 |
+
# prepare the image for the VGG model
|
557 |
+
image = preprocess_input(image)
|
558 |
+
# get features
|
559 |
+
feature = model.predict(image, verbose=0)
|
560 |
+
return feature
|
561 |
+
|
562 |
+
from pickle import load
|
563 |
+
from tensorflow.keras.preprocessing.text import Tokenizer
|
564 |
+
|
565 |
+
tokenizer = load(open('/content/tokenizer1.pkl', 'rb'))
|
566 |
+
max_len = 34
|
567 |
+
model = load_model('/content/drive/MyDrive/Image_Captioning_Project/model_18.h5')
|
568 |
+
photo = extract_features("/content/drive/MyDrive/Image_Captioning_Project/Images/101654506_8eb26cfb60.jpg")
|
569 |
+
tokenizer.analyzer = None
|
570 |
+
description = generate_desc(model, tokenizer, photo, max_len)
|
571 |
+
print(description)
|
572 |
+
|
573 |
+
query = description
|
574 |
+
stopwords = ['startseq','endseq']
|
575 |
+
querywords = query.split()
|
576 |
+
|
577 |
+
resultwords = [word for word in querywords if word.lower() not in stopwords]
|
578 |
+
result = ' '.join(resultwords)
|
579 |
+
|
580 |
+
print(result)
|
581 |
+
|
model_18.h5
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:65e82872f924314f4e3701ede68a9e77f56076f0e4a4df50cc12889f96df084f
|
3 |
+
size 66382940
|
requirements.txt
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
srsly==2.4.6
|
2 |
+
statsmodels==0.14.0
|
3 |
+
streamlit==1.21.0
|
4 |
+
sympy==1.11.1
|
5 |
+
tempora==5.2.2
|
6 |
+
tenacity==8.2.2
|
7 |
+
tensorboard==2.12.2
|
8 |
+
tensorboard-data-server==0.7.0
|
9 |
+
tensorboard-plugin-wit==1.8.1
|
10 |
+
tensorflow==2.12.0
|
11 |
+
tensorflow-estimator==2.12.0
|
12 |
+
tensorflow-io-gcs-filesystem==0.31.0
|
13 |
+
termcolor==2.2.0
|
streamlit.py
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from tensorflow.keras.models import load_model
|
3 |
+
from tensorflow.keras.preprocessing.text import Tokenizer
|
4 |
+
from tensorflow.keras.preprocessing.sequence import pad_sequences
|
5 |
+
from tensorflow.keras.applications.vgg16 import preprocess_input
|
6 |
+
from tensorflow.keras.applications.vgg16 import VGG16
|
7 |
+
from tensorflow.keras.models import Model
|
8 |
+
from tensorflow.keras.preprocessing.image import load_img, img_to_array
|
9 |
+
import numpy as np
|
10 |
+
from PIL import Image
|
11 |
+
from pickle import load
|
12 |
+
|
13 |
+
# Load tokenizer
|
14 |
+
tokenizer = load(open('tokenizer1.pkl', 'rb'))
|
15 |
+
max_len = 34
|
16 |
+
|
17 |
+
# Load image captioning model
|
18 |
+
model = load_model('model_18.h5')
|
19 |
+
|
20 |
+
# Load VGG16 model for feature extraction
|
21 |
+
vgg_model = VGG16()
|
22 |
+
vgg_model.layers.pop()
|
23 |
+
vgg_model = Model(inputs=vgg_model.inputs, outputs=vgg_model.layers[-2].output)
|
24 |
+
|
25 |
+
# Function to map an integer to a word
|
26 |
+
def word_for_id(integer, tokenizer):
|
27 |
+
for word, index in tokenizer.word_index.items():
|
28 |
+
if index == integer:
|
29 |
+
return word
|
30 |
+
return None
|
31 |
+
|
32 |
+
# Function to generate image caption
|
33 |
+
def generate_caption(model, tokenizer, photo, max_length):
|
34 |
+
# Seed the generation process
|
35 |
+
in_text = 'startseq'
|
36 |
+
# Iterate over the whole length of the sequence
|
37 |
+
for i in range(max_length):
|
38 |
+
# Integer encode input sequence
|
39 |
+
sequence = tokenizer.texts_to_sequences([in_text])[0]
|
40 |
+
# Pad input
|
41 |
+
sequence = pad_sequences([sequence], maxlen=max_length)
|
42 |
+
# Predict next word
|
43 |
+
yhat = model.predict([photo, sequence], verbose=0)
|
44 |
+
# Convert probability to integer
|
45 |
+
yhat = np.argmax(yhat)
|
46 |
+
# Map integer to word
|
47 |
+
word = word_for_id(yhat, tokenizer)
|
48 |
+
# Stop if we cannot map the word
|
49 |
+
if word is None:
|
50 |
+
break
|
51 |
+
# Append as input for generating the next word
|
52 |
+
in_text += ' ' + word
|
53 |
+
# Stop if we predict the end of the sequence
|
54 |
+
if word == 'endseq':
|
55 |
+
break
|
56 |
+
return in_text
|
57 |
+
|
58 |
+
# Function to extract image features
|
59 |
+
def extract_features(filename):
|
60 |
+
# Load the photo
|
61 |
+
image = load_img(filename, target_size=(224, 224))
|
62 |
+
# Convert the image pixels to a numpy array
|
63 |
+
image = img_to_array(image)
|
64 |
+
# Reshape data for the model
|
65 |
+
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
|
66 |
+
# Prepare the image for the VGG model
|
67 |
+
image = preprocess_input(image)
|
68 |
+
# Get features
|
69 |
+
feature = vgg_model.predict(image, verbose=0)
|
70 |
+
return feature
|
71 |
+
|
72 |
+
# Remove start and end sequence tokens from the generated caption
|
73 |
+
def remove_start_end_tokens(caption):
|
74 |
+
stopwords = ['startseq', 'endseq']
|
75 |
+
querywords = caption.split()
|
76 |
+
resultwords = [word for word in querywords if word.lower() not in stopwords]
|
77 |
+
result = ' '.join(resultwords)
|
78 |
+
return result
|
79 |
+
|
80 |
+
def main():
|
81 |
+
st.set_page_config(page_title="Image Captioning", page_icon="📷")
|
82 |
+
st.title("Image Captioning")
|
83 |
+
st.markdown("Upload an image and get a caption for it.")
|
84 |
+
|
85 |
+
# File uploader
|
86 |
+
uploaded_file = st.file_uploader("Choose an image file", type=["jpg", "jpeg", "png"])
|
87 |
+
|
88 |
+
if uploaded_file is not None:
|
89 |
+
# Display uploaded image
|
90 |
+
image = Image.open(uploaded_file)
|
91 |
+
resized_image = image.resize((400, 400))
|
92 |
+
st.image(resized_image, caption='Uploaded Image')
|
93 |
+
|
94 |
+
# Extract image features
|
95 |
+
photo = extract_features(uploaded_file)
|
96 |
+
|
97 |
+
# Generate image caption
|
98 |
+
if st.button("Generate Caption"):
|
99 |
+
with st.spinner("Generating caption..."):
|
100 |
+
description = generate_caption(model, tokenizer, photo, max_len)
|
101 |
+
|
102 |
+
# Remove start and end sequence tokens from the caption
|
103 |
+
caption = remove_start_end_tokens(description)
|
104 |
+
|
105 |
+
# Display caption
|
106 |
+
st.subheader(" Generated Caption")
|
107 |
+
st.markdown("---")
|
108 |
+
st.markdown(f"<p style='font-size: 18px; text-align: center;'>{caption}</p>", unsafe_allow_html=True)
|
109 |
+
st.markdown("---")
|
110 |
+
|
111 |
+
|
112 |
+
if __name__ == '__main__':
|
113 |
+
main()
|
tokenizer1.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:eaf7e2d2acb76ab36344db7ee8f8bd15efff2057d8e5481089e0219e8d6055dd
|
3 |
+
size 299574
|