mirror of
https://github.com/GoogleCloudPlatform/vertex-ai-samples.git
synced 2026-09-26 22:51:56 +00:00
Compare commits
665
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c49bc6fe7 | ||
|
|
098ad42f70 | ||
|
|
1f141d0059 | ||
|
|
e0a1608783 | ||
|
|
1a469a09df | ||
|
|
bc3f6d3819 | ||
|
|
f088a3ce69 | ||
|
|
863660042b | ||
|
|
7162248267 | ||
|
|
2e908a8efa | ||
|
|
588d2c880e | ||
|
|
54f10c7411 | ||
|
|
0c2b9e9f45 | ||
|
|
fe07d416e5 | ||
|
|
9c69cbfd54 | ||
|
|
2a25be6af2 | ||
|
|
9680a7e772 | ||
|
|
30527875ed | ||
|
|
8c11e19d86 | ||
|
|
f44f51c06d | ||
|
|
840b537ea6 | ||
|
|
d2602b944f | ||
|
|
bb39135946 | ||
|
|
cb72a56e55 | ||
|
|
eee97362d0 | ||
|
|
a92c5be0e9 | ||
|
|
80707a3ba7 | ||
|
|
903f69b81c | ||
|
|
40a31daaef | ||
|
|
37ba322412 | ||
|
|
ee43400e89 | ||
|
|
176c3721fd | ||
|
|
1d6f9bc36b | ||
|
|
973ecf95e7 | ||
|
|
1f2adec703 | ||
|
|
9843c1f063 | ||
|
|
5afdc3524a | ||
|
|
770508b4f0 | ||
|
|
987881e887 | ||
|
|
8e53b623e5 | ||
|
|
948537e1d4 | ||
|
|
4338b1d90b | ||
|
|
b7a41637ea | ||
|
|
c8f7b910f2 | ||
|
|
1e226a3419 | ||
|
|
287f70abc2 | ||
|
|
8e9d664d88 | ||
|
|
166a407b8d | ||
|
|
72f9ba7647 | ||
|
|
24549bc506 | ||
|
|
dc4efb0c63 | ||
|
|
b8c6cc29b4 | ||
|
|
3b6d2e02d0 | ||
|
|
f33adcea80 | ||
|
|
5b6063b8a8 | ||
|
|
1857b23556 | ||
|
|
86d85ca555 | ||
|
|
67b50fda2c | ||
|
|
0d5cb22491 | ||
|
|
c030d1d79c | ||
|
|
702e6fc262 | ||
|
|
3b2c58821e | ||
|
|
6b302d6ac8 | ||
|
|
78b2aa87f3 | ||
|
|
0b9582341c | ||
|
|
2869cdb021 | ||
|
|
7b2e54bbfb | ||
|
|
32ada1378b | ||
|
|
2581d90588 | ||
|
|
aa3aa7335f | ||
|
|
7028fa896e | ||
|
|
9e599ac03f | ||
|
|
284fabb30e | ||
|
|
aee8d9fa86 | ||
|
|
91606af0f0 | ||
|
|
81ffae5a44 | ||
|
|
c1c95e5e3c | ||
|
|
7bd3814dd9 | ||
|
|
66f3d8497d | ||
|
|
8d80062253 | ||
|
|
b9fff2e5e8 | ||
|
|
df6ffb7a48 | ||
|
|
84d7b17098 | ||
|
|
7ce3015958 | ||
|
|
0aafebdff3 | ||
|
|
eaddeb62d7 | ||
|
|
3b919c1e7d | ||
|
|
ff6a43cbad | ||
|
|
c03b0343d0 | ||
|
|
bbabed68b8 | ||
|
|
858fed1b07 | ||
|
|
2bbb773eef | ||
|
|
0d8df106ef | ||
|
|
749eb6eb74 | ||
|
|
71d01b8dcd | ||
|
|
56a0605ba1 | ||
|
|
368152fdcb | ||
|
|
86e9323847 | ||
|
|
ce90f9b07d | ||
|
|
a6450646bd | ||
|
|
7117ab3023 | ||
|
|
5486fae2e6 | ||
|
|
83047c3604 | ||
|
|
416ec5081c | ||
|
|
72cd14c7f9 | ||
|
|
23f7217a5e | ||
|
|
81df7b2103 | ||
|
|
db8e4aa3b1 | ||
|
|
5834bdf57b | ||
|
|
25484d8244 | ||
|
|
77b33d1f54 | ||
|
|
71376764a4 | ||
|
|
5252708bff | ||
|
|
58fe261d12 | ||
|
|
3932db4033 | ||
|
|
3d276d9bd4 | ||
|
|
3a09e269a8 | ||
|
|
50efecfaab | ||
|
|
4c68aff8b3 | ||
|
|
1f8f05d6d9 | ||
|
|
bd03ae7831 | ||
|
|
d131ab5874 | ||
|
|
865c2fb868 | ||
|
|
5cca6edccd | ||
|
|
ccdb24c145 | ||
|
|
90480c3be5 | ||
|
|
943df70b47 | ||
|
|
3637c8b3d7 | ||
|
|
80fe1e5e02 | ||
|
|
1a59543d01 | ||
|
|
e99629c42e | ||
|
|
dd774e1f02 | ||
|
|
31dd31e3d4 | ||
|
|
ca61199c03 | ||
|
|
3e0a6634a6 | ||
|
|
e45cfa6d16 | ||
|
|
dfabe38846 | ||
|
|
6b9a54d59e | ||
|
|
2b1f97b1da | ||
|
|
65f5a95ac5 | ||
|
|
0441a3792e | ||
|
|
3828455354 | ||
|
|
d38dfe79d9 | ||
|
|
4ccc40db70 | ||
|
|
330886448b | ||
|
|
1990422749 | ||
|
|
34eda2a7ca | ||
|
|
f5e380a08e | ||
|
|
4b173f1f6f | ||
|
|
752be49136 | ||
|
|
282ecdfd39 | ||
|
|
802357f65b | ||
|
|
e11598ca5a | ||
|
|
bf72ac6312 | ||
|
|
f9019ed15e | ||
|
|
20dcdd3054 | ||
|
|
b566021678 | ||
|
|
5b2f4c2534 | ||
|
|
9a61e3c722 | ||
|
|
a56efdcec7 | ||
|
|
c98d3df75a | ||
|
|
6247fbb96f | ||
|
|
ad339286b0 | ||
|
|
430d789c8f | ||
|
|
94eef657ee | ||
|
|
4b5ada9a44 | ||
|
|
5c22ed4eaa | ||
|
|
36fcc6355c | ||
|
|
4c881849e2 | ||
|
|
7d1f7650b9 | ||
|
|
0183abfdd2 | ||
|
|
b92337699a | ||
|
|
4dcc5413cf | ||
|
|
5f47ba8023 | ||
|
|
698503e73d | ||
|
|
e1a15c4bc9 | ||
|
|
0260d79703 | ||
|
|
16712e53ba | ||
|
|
401064a06c | ||
|
|
28d29b4691 | ||
|
|
20902244de | ||
|
|
ff5939aa8b | ||
|
|
ea23ffd42a | ||
|
|
fb6527f66a | ||
|
|
55f8a6f78a | ||
|
|
397285f4bf | ||
|
|
ea3167b8f7 | ||
|
|
c3526504d8 | ||
|
|
9a409b9011 | ||
|
|
c9cca725c6 | ||
|
|
3ddc77293b | ||
|
|
7fa90ee179 | ||
|
|
b88a775d33 | ||
|
|
d58718ce27 | ||
|
|
f380b42d49 | ||
|
|
98be4d8cb4 | ||
|
|
765d6ee296 | ||
|
|
d08959b1a0 | ||
|
|
aec5fbfd6f | ||
|
|
bcba9b5ea2 | ||
|
|
fe42cb6ebd | ||
|
|
7c90baf6e3 | ||
|
|
f9be4f470d | ||
|
|
309889bf6b | ||
|
|
8eabca5939 | ||
|
|
830a762d2d | ||
|
|
be95016723 | ||
|
|
0a7a2f6eeb | ||
|
|
c0196a16b8 | ||
|
|
8e53879df1 | ||
|
|
8ecc2c25c6 | ||
|
|
d98d427271 | ||
|
|
b35c2a89cb | ||
|
|
bc93be1651 | ||
|
|
baa9c06cf7 | ||
|
|
3f3ef75aba | ||
|
|
1a2a0f1d50 | ||
|
|
93a099f65b | ||
|
|
b6804cdf78 | ||
|
|
b641e0857e | ||
|
|
e12faf03ed | ||
|
|
d24f0d0f21 | ||
|
|
c50d38e82f | ||
|
|
52f458fd7d | ||
|
|
eeaf34aa3b | ||
|
|
705f64dc32 | ||
|
|
3830e14fd6 | ||
|
|
bd55db1efc | ||
|
|
07c0f3710f | ||
|
|
f9de0b6315 | ||
|
|
5052d1f44d | ||
|
|
35fbd744e2 | ||
|
|
6d394e639c | ||
|
|
540410ba89 | ||
|
|
26e6548988 | ||
|
|
16de6f1b99 | ||
|
|
8cb2e868ce | ||
|
|
3153e24e57 | ||
|
|
f40a81dda7 | ||
|
|
1590d1cc6f | ||
|
|
6b065f1c5a | ||
|
|
b88fddd6bb | ||
|
|
22454b5318 | ||
|
|
e26190b5e3 | ||
|
|
e6ecd23556 | ||
|
|
a342923353 | ||
|
|
0adcf3d60c | ||
|
|
49547be529 | ||
|
|
9dbd6303b0 | ||
|
|
ac049f3de1 | ||
|
|
3bca163dea | ||
|
|
8904b43308 | ||
|
|
828926e9ab | ||
|
|
851dfb72c1 | ||
|
|
dea652ceca | ||
|
|
56310240b3 | ||
|
|
d828534f28 | ||
|
|
5b6340a15e | ||
|
|
2d3a490aca | ||
|
|
764ea292e5 | ||
|
|
867410462e | ||
|
|
1874743d19 | ||
|
|
b19fcc9f66 | ||
|
|
12db1f9e05 | ||
|
|
853b5c0a97 | ||
|
|
00aa9a2672 | ||
|
|
7eb4eea074 | ||
|
|
4b8b1e503b | ||
|
|
db0f7fb6d7 | ||
|
|
cd04f66ac0 | ||
|
|
419e01d1d3 | ||
|
|
e7a51b394b | ||
|
|
fdfec862be | ||
|
|
6da196a80b | ||
|
|
280f62a1d3 | ||
|
|
20e524dda5 | ||
|
|
b0c7c70b81 | ||
|
|
dcfc30edab | ||
|
|
03fea0608d | ||
|
|
6c15941242 | ||
|
|
1bd5c364f5 | ||
|
|
1c6e4a36c1 | ||
|
|
080d1819ed | ||
|
|
5679e46a12 | ||
|
|
d54b3845fe | ||
|
|
6a2d06f8f4 | ||
|
|
38a37ae8b9 | ||
|
|
be20a635e4 | ||
|
|
db06465158 | ||
|
|
b42b6c6fb8 | ||
|
|
73fbc762fe | ||
|
|
994a86d07a | ||
|
|
71c1eca210 | ||
|
|
20cdcefea3 | ||
|
|
26db26d100 | ||
|
|
01575ae76d | ||
|
|
1c431bdb85 | ||
|
|
096a5d069e | ||
|
|
d795b6e1f5 | ||
|
|
34eaf50f2c | ||
|
|
08ffe85ddf | ||
|
|
3ade1ab265 | ||
|
|
6e71605669 | ||
|
|
f8af22386c | ||
|
|
9d7a744924 | ||
|
|
4f8a527f5c | ||
|
|
4a987f5dcb | ||
|
|
a2a3de5767 | ||
|
|
3ca5d6cad6 | ||
|
|
9117fbbb71 | ||
|
|
607c2605fa | ||
|
|
3509bbc383 | ||
|
|
8593308244 | ||
|
|
806801b4ea | ||
|
|
a1b1ff9a6b | ||
|
|
3acd72ec81 | ||
|
|
12347f3ce2 | ||
|
|
f9c4e32088 | ||
|
|
78da2206b0 | ||
|
|
46fa993732 | ||
|
|
df0c0d209b | ||
|
|
2e8d6239df | ||
|
|
1841201fee | ||
|
|
f10857f299 | ||
|
|
1e4b3aefdb | ||
|
|
e3bcff62fc | ||
|
|
ce3a439d06 | ||
|
|
b47d4b46f3 | ||
|
|
1cc87860c4 | ||
|
|
5d6aa4479d | ||
|
|
5a25b06f2d | ||
|
|
bb055ed061 | ||
|
|
974610a555 | ||
|
|
d78574e640 | ||
|
|
ff367ae9f5 | ||
|
|
40b5e74645 | ||
|
|
dee509e8d7 | ||
|
|
fd5921fa32 | ||
|
|
c74a44a4a8 | ||
|
|
367c985642 | ||
|
|
f7a970e15b | ||
|
|
9a914a5af4 | ||
|
|
e5315be85a | ||
|
|
6daf663a69 | ||
|
|
45a65f1db8 | ||
|
|
240c291728 | ||
|
|
4aec14c576 | ||
|
|
f7d4d3a9c3 | ||
|
|
3c64a8aa58 | ||
|
|
5f692ea299 | ||
|
|
ab1e97ac18 | ||
|
|
78630ae2c0 | ||
|
|
0f48628782 | ||
|
|
93e9fbac92 | ||
|
|
231b2ef02b | ||
|
|
7132c12831 | ||
|
|
2b547e8279 | ||
|
|
8b84524244 | ||
|
|
60fe1bd2c6 | ||
|
|
0edea80ffa | ||
|
|
493e50a999 | ||
|
|
8440e7f164 | ||
|
|
906aa91fe7 | ||
|
|
34e282172f | ||
|
|
bddf642b58 | ||
|
|
25b89c497f | ||
|
|
23a51dbcaa | ||
|
|
26761198d7 | ||
|
|
5b4e88e791 | ||
|
|
83cc796687 | ||
|
|
3e29cc62c7 | ||
|
|
2b1bb77f4b | ||
|
|
7144b87f01 | ||
|
|
ebf4d6d8be | ||
|
|
2ccd913e2e | ||
|
|
d777dd8625 | ||
|
|
d912d3d4d8 | ||
|
|
bafe623590 | ||
|
|
152077a823 | ||
|
|
81c94f9711 | ||
|
|
897e8e3e47 | ||
|
|
ddc125da69 | ||
|
|
abb66ade41 | ||
|
|
2915824641 | ||
|
|
44447637bd | ||
|
|
6a8345446d | ||
|
|
27a7b8b1da | ||
|
|
04471e7104 | ||
|
|
e78ea4e805 | ||
|
|
7487a14783 | ||
|
|
757d0c5087 | ||
|
|
60cb93a9a9 | ||
|
|
0fb72773f4 | ||
|
|
5d2fc74f78 | ||
|
|
1cc26481b2 | ||
|
|
85b0346eab | ||
|
|
910cbacb54 | ||
|
|
c7206e3cc8 | ||
|
|
12d721d33e | ||
|
|
16df2216d1 | ||
|
|
fb26b7213c | ||
|
|
d90f52e122 | ||
|
|
17f42b3044 | ||
|
|
652f34b814 | ||
|
|
c84f8738f8 | ||
|
|
9d72bbf237 | ||
|
|
85df50d06f | ||
|
|
9ab6cddade | ||
|
|
02ffffaeb7 | ||
|
|
dfc5635d34 | ||
|
|
90b686cf69 | ||
|
|
ad63153778 | ||
|
|
7858f8644e | ||
|
|
3df4098364 | ||
|
|
ae3c1877e4 | ||
|
|
2798ab1e02 | ||
|
|
7bd2c567a1 | ||
|
|
56503cce6a | ||
|
|
a5a9f53a32 | ||
|
|
469e8436e9 | ||
|
|
e9f9a5c29b | ||
|
|
102400a67f | ||
|
|
0ae53f47d4 | ||
|
|
ff3e0b4784 | ||
|
|
0f4546c18c | ||
|
|
ee381e15f5 | ||
|
|
4ddeeb290d | ||
|
|
7e99b07440 | ||
|
|
bc1ecd6260 | ||
|
|
f662ffb3e1 | ||
|
|
c40c0e5247 | ||
|
|
bd3a0f5af0 | ||
|
|
99f318333b | ||
|
|
9d36e837bb | ||
|
|
11e7ba47a4 | ||
|
|
399427c2de | ||
|
|
1a3cbb4cf0 | ||
|
|
0f116ab253 | ||
|
|
304000d719 | ||
|
|
36df462615 | ||
|
|
909f771bfd | ||
|
|
e9bef3542d | ||
|
|
037a3b041a | ||
|
|
f55e6c60cd | ||
|
|
e7e7a8e22c | ||
|
|
2cd815c640 | ||
|
|
b1c0cc9a9d | ||
|
|
af63d1c0e2 | ||
|
|
c51a82febb | ||
|
|
8e6e4729aa | ||
|
|
0e97a83836 | ||
|
|
f6645e0125 | ||
|
|
52385a6071 | ||
|
|
2365d733c4 | ||
|
|
71e6423066 | ||
|
|
139ed95ffc | ||
|
|
cafd192417 | ||
|
|
0d7ec7cd60 | ||
|
|
7fd934045a | ||
|
|
4e82877269 | ||
|
|
6ef111144d | ||
|
|
e9b8aa02e9 | ||
|
|
ac1af33c8c | ||
|
|
5bc18b01e4 | ||
|
|
e98b9d6eb4 | ||
|
|
5e6b8bf597 | ||
|
|
5b39e7d995 | ||
|
|
c4f08589a9 | ||
|
|
04c6ff4ec7 | ||
|
|
bcb0b19dc4 | ||
|
|
5586fd7c4d | ||
|
|
30e747b966 | ||
|
|
080e2b5bb5 | ||
|
|
e908774b5b | ||
|
|
60e4416a7e | ||
|
|
b207b270b4 | ||
|
|
497e93aba1 | ||
|
|
9a6c36d016 | ||
|
|
c889a57c9e | ||
|
|
dbe5d61929 | ||
|
|
c180408f41 | ||
|
|
869b19d342 | ||
|
|
3d967b180d | ||
|
|
49710a9225 | ||
|
|
9d31463585 | ||
|
|
bcd86a3707 | ||
|
|
9335ea3591 | ||
|
|
0f7343feee | ||
|
|
12cd965ce6 | ||
|
|
4e5c75fed6 | ||
|
|
b28f941abe | ||
|
|
32632711ff | ||
|
|
d676d87cce | ||
|
|
153a8044b8 | ||
|
|
c0d9250416 | ||
|
|
fd16e39f91 | ||
|
|
1551ca9435 | ||
|
|
80fcd2904f | ||
|
|
e974c034ba | ||
|
|
f0112cfc9a | ||
|
|
d2d4493397 | ||
|
|
33e7d18502 | ||
|
|
6628866130 | ||
|
|
0cd6146a6c | ||
|
|
b61395f465 | ||
|
|
649b209577 | ||
|
|
506a6e66d7 | ||
|
|
5bd6cfe6a7 | ||
|
|
ca27881ca7 | ||
|
|
5fa0ed6185 | ||
|
|
14f58e30c5 | ||
|
|
6af94b51aa | ||
|
|
2f818117db | ||
|
|
04fe89c556 | ||
|
|
f42a184171 | ||
|
|
03f0647b76 | ||
|
|
1f39732ae9 | ||
|
|
7dd0b31b58 | ||
|
|
ff843173cf | ||
|
|
da19b116e9 | ||
|
|
d8b365dfd4 | ||
|
|
1247c80fed | ||
|
|
2cf2bf1080 | ||
|
|
5e9e8139c1 | ||
|
|
0728a0036f | ||
|
|
aa52d21643 | ||
|
|
103888d75e | ||
|
|
13d0d5d9b0 | ||
|
|
79c6669686 | ||
|
|
dceb0c4c1c | ||
|
|
0c9cdca713 | ||
|
|
6124092681 | ||
|
|
629e739327 | ||
|
|
b68cbd8255 | ||
|
|
7fec30c12f | ||
|
|
a754843c39 | ||
|
|
436db4a35b | ||
|
|
8dba2d040b | ||
|
|
560dd9da15 | ||
|
|
8ec17d6aca | ||
|
|
f545282c36 | ||
|
|
7e4e14e084 | ||
|
|
be5933115d | ||
|
|
be46140138 | ||
|
|
79f4dbaafe | ||
|
|
9577f8324c | ||
|
|
01274fe767 | ||
|
|
1690b07e4a | ||
|
|
6b0de60a5c | ||
|
|
19b541b6cb | ||
|
|
22f6841079 | ||
|
|
7c47c95e3a | ||
|
|
7735e6ae69 | ||
|
|
247a540625 | ||
|
|
f017606f77 | ||
|
|
1d7024341a | ||
|
|
9181dba316 | ||
|
|
a8320f3943 | ||
|
|
6fc34ae4f1 | ||
|
|
5566346fdc | ||
|
|
e584acdb48 | ||
|
|
4022811d3c | ||
|
|
4d29c490f8 | ||
|
|
2315942901 | ||
|
|
505d5049e0 | ||
|
|
20411db737 | ||
|
|
39dbbde22c | ||
|
|
34251594a4 | ||
|
|
7342673331 | ||
|
|
b5d19719e0 | ||
|
|
59536e9e61 | ||
|
|
7d74bc3caa | ||
|
|
f681879a8a | ||
|
|
b5b65198a6 | ||
|
|
3a5a14f1d8 | ||
|
|
157f8538ed | ||
|
|
532bf04933 | ||
|
|
99547ccb73 | ||
|
|
2e0cd74533 | ||
|
|
b9a9d76e8b | ||
|
|
fb61e0631c | ||
|
|
16c38c8fbf | ||
|
|
8888e8ad7f | ||
|
|
c787a0e99e | ||
|
|
8ea77a7cb0 | ||
|
|
2bb6d6deb2 | ||
|
|
7b235c935a | ||
|
|
3c88e9284c | ||
|
|
e967b02a22 | ||
|
|
aeb87cbc44 | ||
|
|
1f39a8f892 | ||
|
|
d2a6508379 | ||
|
|
39d1646b3c | ||
|
|
4c5ede0130 | ||
|
|
7715f79807 | ||
|
|
7c8eeeb1d1 | ||
|
|
6caffbe5c3 | ||
|
|
99929ca018 | ||
|
|
6aadabd967 | ||
|
|
9b5be742c1 | ||
|
|
63d5b5e3bf | ||
|
|
1448645ba4 | ||
|
|
3d19ffb131 | ||
|
|
b6018551a5 | ||
|
|
65fbf0ee0b | ||
|
|
427bd3d5ea | ||
|
|
5f41599745 | ||
|
|
67fbd84832 | ||
|
|
9b427b6a1f | ||
|
|
37d5d5b992 | ||
|
|
287911b681 | ||
|
|
c83387181a | ||
|
|
236d45b87e | ||
|
|
4eb7b3ce39 | ||
|
|
d74554f641 | ||
|
|
3e70c63899 | ||
|
|
4c79ab91e2 | ||
|
|
dd8a7ad325 | ||
|
|
a3bb273e78 | ||
|
|
1ff0872546 | ||
|
|
91144b8476 | ||
|
|
9822bd64a1 | ||
|
|
f14ff50d2b | ||
|
|
fdc30dab67 | ||
|
|
93229f62c9 | ||
|
|
b37f474255 | ||
|
|
344b0dd6d7 | ||
|
|
48b7cdb21d | ||
|
|
cefdc32d5f | ||
|
|
7558411fbc | ||
|
|
e01174f169 | ||
|
|
1c0487c459 | ||
|
|
62c903f47d | ||
|
|
6b7bb867ab | ||
|
|
8c7363c2b0 | ||
|
|
2ea22da2bf | ||
|
|
1d96584421 | ||
|
|
06d57da90c | ||
|
|
355105218d | ||
|
|
da77846b88 | ||
|
|
3090a312c0 | ||
|
|
8c265ee1ef | ||
|
|
7c123e68d3 | ||
|
|
9f26e8385d | ||
|
|
0fffaee6dc | ||
|
|
c34b7ab651 | ||
|
|
d57d9be9d4 | ||
|
|
88f3ecf567 | ||
|
|
ecfbeaa8ce | ||
|
|
3e5a319455 | ||
|
|
f35ce3432a | ||
|
|
2e9ff4a941 | ||
|
|
61fbd37fa4 | ||
|
|
474e4e602b | ||
|
|
e409cf710b | ||
|
|
e9bac09dce | ||
|
|
b799aad08a | ||
|
|
4d6bd1afff | ||
|
|
b4040ff01d | ||
|
|
c29e4fde26 | ||
|
|
c6fdad745f | ||
|
|
3c60c2cb97 | ||
|
|
278a014817 | ||
|
|
89ec43c706 | ||
|
|
ba6be7ee99 |
@@ -5,6 +5,15 @@ from resource_cleanup_manager import (
|
||||
ModelResourceCleanupManager,
|
||||
EndpointResourceCleanupManager,
|
||||
ResourceCleanupManager,
|
||||
MatchingEngineIndexEndpointResourceCleanupManager,
|
||||
MatchingEngineIndexResourceCleanupManager,
|
||||
FeatureStoreCleanupManager,
|
||||
PipelineJobCleanupManager,
|
||||
TrainingJobCleanupManager,
|
||||
HyperparameterTuningCleanupManager,
|
||||
BatchPredictionJobCleanupManager,
|
||||
ExperimentCleanupManager,
|
||||
BucketCleanupManager
|
||||
)
|
||||
|
||||
rate_limit = RateLimit(max_count=25, per=60, greedy=False)
|
||||
@@ -21,7 +30,6 @@ def run_cleanup_managers(managers: List[ResourceCleanupManager], is_dry_run: boo
|
||||
try:
|
||||
if not manager.is_deletable(resource):
|
||||
continue
|
||||
|
||||
if is_dry_run:
|
||||
resource_name = manager.resource_name(resource)
|
||||
print(f"Will delete '{type_name}': {resource_name}")
|
||||
@@ -40,10 +48,19 @@ if is_dry_run:
|
||||
print("Starting cleanup in dry run mode...")
|
||||
|
||||
# List of all cleanup managers
|
||||
managers = [
|
||||
managers: List[ResourceCleanupManager] = [
|
||||
DatasetResourceCleanupManager(),
|
||||
EndpointResourceCleanupManager(),
|
||||
ModelResourceCleanupManager(), # ModelResourceCleanupManager must follow EndpointResourceCleanupManager due to deployed models blocking model deletion.
|
||||
MatchingEngineIndexEndpointResourceCleanupManager(),
|
||||
MatchingEngineIndexResourceCleanupManager(),
|
||||
FeatureStoreCleanupManager(),
|
||||
PipelineJobCleanupManager(),
|
||||
TrainingJobCleanupManager(),
|
||||
HyperparameterTuningCleanupManager(),
|
||||
BatchPredictionJobCleanupManager(),
|
||||
ExperimentCleanupManager(), # Experiment missing _resource_noun
|
||||
BucketCleanupManager()
|
||||
]
|
||||
|
||||
run_cleanup_managers(managers=managers, is_dry_run=is_dry_run)
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
'''
|
||||
READ FIRST BEFORE MAKING CHANGES
|
||||
- Create a convention for resources created from vertex-ai-samples GH. We already have one IIRC
|
||||
- Only delete those objects as part of our clean-up script.
|
||||
- Don't run any tests on python-docs-samples-tests project, especially ones that affect resources created outside of our purview
|
||||
- Add --dry-run option to the clean-up script. This option will just output the list of resources the script will delete instead of actually deleting the resources.
|
||||
- Have a larger conversation in DEE before touching any resources that were not created as part of vertex-ai-samples
|
||||
'''
|
||||
import abc
|
||||
from typing import Any, Type
|
||||
|
||||
from google.cloud import aiplatform
|
||||
from google.cloud.aiplatform import base
|
||||
from google.cloud import storage
|
||||
from proto.datetime_helpers import DatetimeWithNanoseconds
|
||||
|
||||
# If a resource was updated within this number of seconds, do not delete.
|
||||
@@ -69,7 +78,7 @@ class VertexAIResourceCleanupManager(ResourceCleanupManager):
|
||||
def delete(self, resource):
|
||||
resource.delete()
|
||||
|
||||
def get_seconds_since_modification(self, resource: Any) -> bool:
|
||||
def get_seconds_since_modification(self, resource: Any) -> float:
|
||||
update_time = resource.update_time
|
||||
current_time = DatetimeWithNanoseconds.now(tz=update_time.tzinfo)
|
||||
return (current_time - update_time).total_seconds()
|
||||
@@ -97,15 +106,119 @@ class EndpointResourceCleanupManager(VertexAIResourceCleanupManager):
|
||||
vertex_ai_resource = aiplatform.Endpoint
|
||||
|
||||
def delete(self, resource):
|
||||
# TODO: Remove this once https://github.com/googleapis/python-aiplatform/issues/1441 is fixed
|
||||
resource._sync_gca_resource()
|
||||
for deployed_model_id in [
|
||||
models.id for models in resource._gca_resource.deployed_models
|
||||
]:
|
||||
resource._undeploy(deployed_model_id=deployed_model_id)
|
||||
|
||||
resource.delete(force=True)
|
||||
|
||||
|
||||
class ModelResourceCleanupManager(VertexAIResourceCleanupManager):
|
||||
vertex_ai_resource = aiplatform.Model
|
||||
|
||||
|
||||
class MatchingEngineIndexResourceCleanupManager(VertexAIResourceCleanupManager):
|
||||
vertex_ai_resource = aiplatform.MatchingEngineIndex
|
||||
|
||||
|
||||
class MatchingEngineIndexEndpointResourceCleanupManager(VertexAIResourceCleanupManager):
|
||||
vertex_ai_resource = aiplatform.MatchingEngineIndexEndpoint
|
||||
|
||||
def delete(self, resource):
|
||||
resource.undeploy_all()
|
||||
resource.delete(force=True)
|
||||
|
||||
class FeatureStoreCleanupManager(VertexAIResourceCleanupManager):
|
||||
vertex_ai_resource = aiplatform.Featurestore
|
||||
|
||||
def resource_name(self, resource: Any) -> str:
|
||||
return resource.name
|
||||
|
||||
class PipelineJobCleanupManager(VertexAIResourceCleanupManager):
|
||||
vertex_ai_resource = aiplatform.PipelineJob
|
||||
|
||||
class TrainingJobCleanupManager(VertexAIResourceCleanupManager):
|
||||
vertex_ai_resource = aiplatform.training_jobs._CustomTrainingJob
|
||||
|
||||
job_types = [
|
||||
aiplatform.AutoMLImageTrainingJob,
|
||||
aiplatform.AutoMLTextTrainingJob,
|
||||
aiplatform.AutoMLTabularTrainingJob,
|
||||
aiplatform.AutoMLVideoTrainingJob,
|
||||
aiplatform.AutoMLForecastingTrainingJob,
|
||||
aiplatform.CustomJob,
|
||||
aiplatform.CustomTrainingJob,
|
||||
aiplatform.CustomContainerTrainingJob,
|
||||
aiplatform.CustomPythonPackageTrainingJob
|
||||
]
|
||||
|
||||
def list(self) -> Any:
|
||||
return [
|
||||
job
|
||||
for job_type in self.job_types
|
||||
for job in job_type.list()
|
||||
]
|
||||
|
||||
class HyperparameterTuningCleanupManager(VertexAIResourceCleanupManager):
|
||||
vertex_ai_resource = aiplatform.HyperparameterTuningJob
|
||||
|
||||
|
||||
class BatchPredictionJobCleanupManager(VertexAIResourceCleanupManager):
|
||||
vertex_ai_resource = aiplatform.BatchPredictionJob
|
||||
|
||||
class ExperimentCleanupManager(VertexAIResourceCleanupManager):
|
||||
vertex_ai_resource = aiplatform.Experiment
|
||||
|
||||
@property
|
||||
def type_name(self) -> str:
|
||||
return "Experiment"
|
||||
|
||||
def resource_name(self, resource: Any) -> str:
|
||||
return resource.name
|
||||
|
||||
def get_seconds_since_modification(self, resource: Any) -> float:
|
||||
update_time = resource._metadata_context.update_time
|
||||
current_time = DatetimeWithNanoseconds.now()
|
||||
return float(current_time.timestamp() - update_time.timestamp())
|
||||
|
||||
class BucketCleanupManager(ResourceCleanupManager):
|
||||
vertex_ai_resource = storage.bucket.Bucket
|
||||
|
||||
def list(self) -> Any:
|
||||
storage_client = storage.Client()
|
||||
return list(storage_client.list_buckets())
|
||||
|
||||
def delete(self, resource):
|
||||
try:
|
||||
resource.delete(force=True)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
@property
|
||||
def type_name(self) -> str:
|
||||
return "Bucket"
|
||||
|
||||
def get_seconds_since_modification(self, resource: Any) -> float:
|
||||
# Bucket has no last_update property, only time created
|
||||
created_time = resource.time_created
|
||||
current_time = DatetimeWithNanoseconds.now()
|
||||
return float(current_time.timestamp() - created_time.timestamp())
|
||||
|
||||
def resource_name(self, resource: Any) -> str:
|
||||
return resource.name
|
||||
|
||||
def is_deletable(self, resource: Any) -> bool:
|
||||
time_difference = self.get_seconds_since_modification(resource)
|
||||
|
||||
if not self.resource_name(resource).startswith('your-bucket-name'):
|
||||
print(f"Skipping '{resource}' not a Vertex AI notebook bucket")
|
||||
return False
|
||||
|
||||
# Check that it wasn't created too recently, to prevent race conditions
|
||||
if time_difference <= RESOURCE_UPDATE_BUFFER_IN_SECONDS:
|
||||
print(
|
||||
f"Skipping '{resource}' due to update_time being '{time_difference}', which is less than '{RESOURCE_UPDATE_BUFFER_IN_SECONDS}'."
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@@ -156,7 +156,7 @@ def _create_tag(filepath: str) -> str:
|
||||
return tag
|
||||
|
||||
|
||||
rate_limit = RateLimit(max_count=50, per=60, greedy=True)
|
||||
rate_limit = RateLimit(max_count=10, per=60, greedy=True)
|
||||
|
||||
|
||||
def process_and_execute_notebook(
|
||||
@@ -245,7 +245,7 @@ def process_and_execute_notebook(
|
||||
result.logs_bucket = operation_metadata.build.logs_bucket
|
||||
|
||||
# Block and wait for the result
|
||||
operation_result = operation.result()
|
||||
operation_result = operation.result(timeout=timeout_in_seconds)
|
||||
|
||||
result.duration = datetime.datetime.now() - time_start
|
||||
result.is_pass = True
|
||||
|
||||
@@ -10,4 +10,5 @@ google-cloud-aiplatform
|
||||
google-cloud-storage
|
||||
google-cloud-build
|
||||
ratemate
|
||||
GitPython
|
||||
GitPython
|
||||
tqdm
|
||||
@@ -2,9 +2,9 @@ git+https://github.com/tensorflow/docs
|
||||
ipython
|
||||
jupyter
|
||||
nbconvert
|
||||
black==22.10.0
|
||||
black==22.12.0
|
||||
pyupgrade==2.38.4
|
||||
isort==5.10.1
|
||||
flake8==4.0.1
|
||||
isort==5.12.0
|
||||
flake8==6.0.0
|
||||
nbqa==1.5.3
|
||||
|
||||
|
||||
+3
-5
@@ -44,12 +44,10 @@ Finally, run this code block to check for errors. Each step will attempt to
|
||||
automatically fix any issues. If the fixes can't be performed automatically,
|
||||
then you will need to manually address them before submitting your PR.
|
||||
|
||||
Note: For official, only submit one notebook per PR.
|
||||
|
||||
```shell
|
||||
nbqa black "$notebook"
|
||||
nbqa pyupgrade "$notebook"
|
||||
nbqa isort "$notebook"
|
||||
nbqa flake8 "$notebook" --extend-ignore=W391,E501,F821,E402,F404,W503,E203,E722,W293,W291
|
||||
python3 -m tensorflow_docs.tools.nbfmt --remove_outputs "$notebook"
|
||||
docker run -v ${PWD}:/setup/app gcr.io/cloud-devrel-public-resources/notebook_linter:latest your_notebook
|
||||
```
|
||||
|
||||
## Code Reviews
|
||||
|
||||
@@ -7,3 +7,6 @@
|
||||
/pluto_on_workbench @wkharold
|
||||
/cpr-examples @samthrasher
|
||||
/Train_tabular_models_with_many_frameworks_and_import_to_Vertex_AI_using_Pipelines @Ark-kun
|
||||
/pipeline_components @Ark-kun
|
||||
/pipeline_components/image_ml_model_training @lakeyk
|
||||
/prediction_featurestore_integration @googleapis/vertex-prediction-team
|
||||
|
||||
+7
-7
@@ -2,13 +2,13 @@
|
||||
from kfp import components
|
||||
|
||||
# %% Loading components
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/8c78aae096806cff3bc331a40566f42f5c3e9d4b/components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/23405971f5f16a41b16c343129b893c52e4d1d48/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
binarize_column_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/1e2558325f4c708aca75827c8acc13d230ee7e9f/components/pandas/Binarize_column/in_CSV_format/component.yaml")
|
||||
train_logistic_regression_model_using_scikit_learn_from_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/cb44b75c9c062fcc40c2b905b2024b4493dbc62b/components/ML_frameworks/Scikit_learn/Train_logistic_regression_model/from_CSV/component.yaml")
|
||||
upload_Scikit_learn_pickle_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_Scikit-learn_pickle_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/storage/download/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
binarize_column_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Binarize_column/in_CSV_format/component.yaml")
|
||||
train_logistic_regression_model_using_scikit_learn_from_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/1f5cf6e06409b704064b2086c0a705e4e6b4fcde/community-content/pipeline_components/ML_frameworks/Scikit_learn/Train_logistic_regression_model/from_CSV/component.yaml")
|
||||
upload_Scikit_learn_pickle_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_Scikit-learn_pickle_model/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml")
|
||||
|
||||
# %% Pipeline definition
|
||||
def train_tabular_classification_logistic_regression_model_using_Scikit_learn_pipeline():
|
||||
|
||||
+9
-9
@@ -2,15 +2,15 @@
|
||||
from kfp import components
|
||||
|
||||
# %% Loading components
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/8c78aae096806cff3bc331a40566f42f5c3e9d4b/components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/23405971f5f16a41b16c343129b893c52e4d1d48/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
binarize_column_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/1e2558325f4c708aca75827c8acc13d230ee7e9f/components/pandas/Binarize_column/in_CSV_format/component.yaml")
|
||||
create_fully_connected_pytorch_network_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/1a2ef3eeb77bc278f33cad0dd29008ea2431e191/components/PyTorch/Create_fully_connected_network/component.yaml")
|
||||
train_pytorch_model_from_csv_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/d8c4cf5e6403bc65bcf8d606e6baf87e2528a3dc/components/PyTorch/Train_PyTorch_model/from_CSV/component.yaml")
|
||||
create_pytorch_model_archive_with_base_handler_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/46d51383e6554b7f3ab4fd8cf614d8c2b422fb22/components/PyTorch/Create_PyTorch_Model_Archive/with_base_handler/component.yaml")
|
||||
upload_PyTorch_model_archive_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_PyTorch_model_archive/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/storage/download/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
binarize_column_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Binarize_column/in_CSV_format/component.yaml")
|
||||
create_fully_connected_pytorch_network_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Create_fully_connected_network/component.yaml")
|
||||
train_pytorch_model_from_csv_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Train_PyTorch_model/from_CSV/component.yaml")
|
||||
create_pytorch_model_archive_with_base_handler_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Create_PyTorch_Model_Archive/with_base_handler/component.yaml")
|
||||
upload_PyTorch_model_archive_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_PyTorch_model_archive/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml")
|
||||
|
||||
# %% Pipeline definition
|
||||
def train_tabular_classification_model_using_PyTorch_pipeline():
|
||||
|
||||
+10
-10
@@ -2,16 +2,16 @@
|
||||
from kfp import components
|
||||
|
||||
# %% Loading components
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/8c78aae096806cff3bc331a40566f42f5c3e9d4b/components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/23405971f5f16a41b16c343129b893c52e4d1d48/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
binarize_column_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/1e2558325f4c708aca75827c8acc13d230ee7e9f/components/pandas/Binarize_column/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/daae5a4abaa35e44501818b1534ed7827d7da073/components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
create_fully_connected_tensorflow_network_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/9ca0f9eecf5f896f65b8538bbd809747052617d1/components/tensorflow/Create_fully_connected_network/component.yaml")
|
||||
train_model_using_Keras_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c504a4010348c50eaaf6d4337586ccc008f4dcef/components/tensorflow/Train_model_using_Keras/on_CSV/component.yaml")
|
||||
predict_with_TensorFlow_model_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/59c759ce6f543184e30db6817d2a703879bc0f39/components/tensorflow/Predict/on_CSV/component.yaml")
|
||||
upload_Tensorflow_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/storage/download/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
binarize_column_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Binarize_column/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
create_fully_connected_tensorflow_network_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Create_fully_connected_network/component.yaml")
|
||||
train_model_using_Keras_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Train_model_using_Keras/on_CSV/component.yaml")
|
||||
predict_with_TensorFlow_model_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Predict/on_CSV/component.yaml")
|
||||
upload_Tensorflow_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml")
|
||||
|
||||
# %% Pipeline definition
|
||||
def train_tabular_classification_model_using_TensorFlow_pipeline():
|
||||
|
||||
+9
-9
@@ -2,15 +2,15 @@
|
||||
from kfp import components
|
||||
|
||||
# %% Loading components
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/8c78aae096806cff3bc331a40566f42f5c3e9d4b/components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/23405971f5f16a41b16c343129b893c52e4d1d48/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
binarize_column_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/1e2558325f4c708aca75827c8acc13d230ee7e9f/components/pandas/Binarize_column/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/daae5a4abaa35e44501818b1534ed7827d7da073/components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
train_XGBoost_model_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/58d3a47f904f32a64af8403330ba7e2134cae46d/components/XGBoost/Train/component.yaml")
|
||||
xgboost_predict_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/4694ec97baccf59284c2a1db4aa2250c22291eab/components/XGBoost/Predict/component.yaml")
|
||||
upload_XGBoost_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_XGBoost_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/storage/download/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
binarize_column_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Binarize_column/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
train_XGBoost_model_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/XGBoost/Train/component.yaml")
|
||||
xgboost_predict_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/XGBoost/Predict/component.yaml")
|
||||
upload_XGBoost_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_XGBoost_model/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml")
|
||||
|
||||
# %% Pipeline definition
|
||||
def train_tabular_classification_model_using_XGBoost_pipeline():
|
||||
|
||||
+20
-20
@@ -2,36 +2,36 @@
|
||||
from kfp import components
|
||||
|
||||
# %% Loading components
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/8c78aae096806cff3bc331a40566f42f5c3e9d4b/components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/23405971f5f16a41b16c343129b893c52e4d1d48/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
binarize_column_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/1e2558325f4c708aca75827c8acc13d230ee7e9f/components/pandas/Binarize_column/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/daae5a4abaa35e44501818b1534ed7827d7da073/components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/storage/download/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
binarize_column_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Binarize_column/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
|
||||
# TensorFlow
|
||||
create_fully_connected_tensorflow_network_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/9ca0f9eecf5f896f65b8538bbd809747052617d1/components/tensorflow/Create_fully_connected_network/component.yaml")
|
||||
train_model_using_Keras_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c504a4010348c50eaaf6d4337586ccc008f4dcef/components/tensorflow/Train_model_using_Keras/on_CSV/component.yaml")
|
||||
predict_with_TensorFlow_model_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/59c759ce6f543184e30db6817d2a703879bc0f39/components/tensorflow/Predict/on_CSV/component.yaml")
|
||||
upload_Tensorflow_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
create_fully_connected_tensorflow_network_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Create_fully_connected_network/component.yaml")
|
||||
train_model_using_Keras_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Train_model_using_Keras/on_CSV/component.yaml")
|
||||
predict_with_TensorFlow_model_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Predict/on_CSV/component.yaml")
|
||||
upload_Tensorflow_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/component.yaml")
|
||||
|
||||
# PyTorch
|
||||
create_fully_connected_pytorch_network_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/1a2ef3eeb77bc278f33cad0dd29008ea2431e191/components/PyTorch/Create_fully_connected_network/component.yaml")
|
||||
train_pytorch_model_from_csv_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/d8c4cf5e6403bc65bcf8d606e6baf87e2528a3dc/components/PyTorch/Train_PyTorch_model/from_CSV/component.yaml")
|
||||
create_pytorch_model_archive_with_base_handler_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/46d51383e6554b7f3ab4fd8cf614d8c2b422fb22/components/PyTorch/Create_PyTorch_Model_Archive/with_base_handler/component.yaml")
|
||||
upload_PyTorch_model_archive_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_PyTorch_model_archive/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
create_fully_connected_pytorch_network_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Create_fully_connected_network/component.yaml")
|
||||
train_pytorch_model_from_csv_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Train_PyTorch_model/from_CSV/component.yaml")
|
||||
create_pytorch_model_archive_with_base_handler_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Create_PyTorch_Model_Archive/with_base_handler/component.yaml")
|
||||
upload_PyTorch_model_archive_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_PyTorch_model_archive/component.yaml")
|
||||
|
||||
# XGBoost
|
||||
train_XGBoost_model_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/58d3a47f904f32a64af8403330ba7e2134cae46d/components/XGBoost/Train/component.yaml")
|
||||
xgboost_predict_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/4694ec97baccf59284c2a1db4aa2250c22291eab/components/XGBoost/Predict/component.yaml")
|
||||
upload_XGBoost_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_XGBoost_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
train_XGBoost_model_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/XGBoost/Train/component.yaml")
|
||||
xgboost_predict_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/XGBoost/Predict/component.yaml")
|
||||
upload_XGBoost_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_XGBoost_model/component.yaml")
|
||||
|
||||
# Scikit-learn
|
||||
#train_linear_regression_model_using_scikit_learn_from_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/f807e02b54d4886c65a05f40848fd51c72407f40/components/ML_frameworks/Scikit_learn/Train_linear_regression_model/from_CSV/component.yaml")
|
||||
train_logistic_regression_model_using_scikit_learn_from_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/cb44b75c9c062fcc40c2b905b2024b4493dbc62b/components/ML_frameworks/Scikit_learn/Train_logistic_regression_model/from_CSV/component.yaml")
|
||||
upload_Scikit_learn_pickle_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_Scikit-learn_pickle_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
#train_linear_regression_model_using_scikit_learn_from_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/1f5cf6e06409b704064b2086c0a705e4e6b4fcde/community-content/pipeline_components/ML_frameworks/Scikit_learn/Train_linear_regression_model/from_CSV/component.yaml")
|
||||
train_logistic_regression_model_using_scikit_learn_from_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/1f5cf6e06409b704064b2086c0a705e4e6b4fcde/community-content/pipeline_components/ML_frameworks/Scikit_learn/Train_logistic_regression_model/from_CSV/component.yaml")
|
||||
upload_Scikit_learn_pickle_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_Scikit-learn_pickle_model/component.yaml")
|
||||
|
||||
# Vertex AI
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml")
|
||||
|
||||
# %% Pipeline definition
|
||||
def train_tabular_classification_model_using_all_frameworks_pipeline():
|
||||
|
||||
+6
-6
@@ -2,12 +2,12 @@
|
||||
from kfp import components
|
||||
|
||||
# %% Loading components
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/8c78aae096806cff3bc331a40566f42f5c3e9d4b/components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/23405971f5f16a41b16c343129b893c52e4d1d48/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
train_linear_regression_model_using_scikit_learn_from_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/f807e02b54d4886c65a05f40848fd51c72407f40/components/ML_frameworks/Scikit_learn/Train_linear_regression_model/from_CSV/component.yaml")
|
||||
upload_Scikit_learn_pickle_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_Scikit-learn_pickle_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/storage/download/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
train_linear_regression_model_using_scikit_learn_from_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/1f5cf6e06409b704064b2086c0a705e4e6b4fcde/community-content/pipeline_components/ML_frameworks/Scikit_learn/Train_linear_regression_model/from_CSV/component.yaml")
|
||||
upload_Scikit_learn_pickle_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_Scikit-learn_pickle_model/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml")
|
||||
|
||||
# %% Pipeline definition
|
||||
def train_tabular_regression_linear_model_using_Scikit_learn_pipeline():
|
||||
|
||||
+8
-8
@@ -2,14 +2,14 @@
|
||||
from kfp import components
|
||||
|
||||
# %% Loading components
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/8c78aae096806cff3bc331a40566f42f5c3e9d4b/components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/23405971f5f16a41b16c343129b893c52e4d1d48/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
create_fully_connected_pytorch_network_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/1a2ef3eeb77bc278f33cad0dd29008ea2431e191/components/PyTorch/Create_fully_connected_network/component.yaml")
|
||||
train_pytorch_model_from_csv_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/d8c4cf5e6403bc65bcf8d606e6baf87e2528a3dc/components/PyTorch/Train_PyTorch_model/from_CSV/component.yaml")
|
||||
create_pytorch_model_archive_with_base_handler_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/46d51383e6554b7f3ab4fd8cf614d8c2b422fb22/components/PyTorch/Create_PyTorch_Model_Archive/with_base_handler/component.yaml")
|
||||
upload_PyTorch_model_archive_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_PyTorch_model_archive/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/storage/download/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
create_fully_connected_pytorch_network_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Create_fully_connected_network/component.yaml")
|
||||
train_pytorch_model_from_csv_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Train_PyTorch_model/from_CSV/component.yaml")
|
||||
create_pytorch_model_archive_with_base_handler_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Create_PyTorch_Model_Archive/with_base_handler/component.yaml")
|
||||
upload_PyTorch_model_archive_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_PyTorch_model_archive/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml")
|
||||
|
||||
# %% Pipeline definition
|
||||
def train_tabular_regression_model_using_PyTorch_pipeline():
|
||||
|
||||
+9
-9
@@ -2,15 +2,15 @@
|
||||
from kfp import components
|
||||
|
||||
# %% Loading components
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/8c78aae096806cff3bc331a40566f42f5c3e9d4b/components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/23405971f5f16a41b16c343129b893c52e4d1d48/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/daae5a4abaa35e44501818b1534ed7827d7da073/components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
create_fully_connected_tensorflow_network_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/9ca0f9eecf5f896f65b8538bbd809747052617d1/components/tensorflow/Create_fully_connected_network/component.yaml")
|
||||
train_model_using_Keras_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c504a4010348c50eaaf6d4337586ccc008f4dcef/components/tensorflow/Train_model_using_Keras/on_CSV/component.yaml")
|
||||
predict_with_TensorFlow_model_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/59c759ce6f543184e30db6817d2a703879bc0f39/components/tensorflow/Predict/on_CSV/component.yaml")
|
||||
upload_Tensorflow_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/storage/download/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
create_fully_connected_tensorflow_network_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Create_fully_connected_network/component.yaml")
|
||||
train_model_using_Keras_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Train_model_using_Keras/on_CSV/component.yaml")
|
||||
predict_with_TensorFlow_model_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Predict/on_CSV/component.yaml")
|
||||
upload_Tensorflow_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml")
|
||||
|
||||
# %% Pipeline definition
|
||||
def train_tabular_regression_model_using_Tensorflow_pipeline():
|
||||
|
||||
+8
-8
@@ -2,14 +2,14 @@
|
||||
from kfp import components
|
||||
|
||||
# %% Loading components
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/8c78aae096806cff3bc331a40566f42f5c3e9d4b/components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/23405971f5f16a41b16c343129b893c52e4d1d48/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/daae5a4abaa35e44501818b1534ed7827d7da073/components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
train_XGBoost_model_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/58d3a47f904f32a64af8403330ba7e2134cae46d/components/XGBoost/Train/component.yaml")
|
||||
xgboost_predict_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/4694ec97baccf59284c2a1db4aa2250c22291eab/components/XGBoost/Predict/component.yaml")
|
||||
upload_XGBoost_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_XGBoost_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/storage/download/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
train_XGBoost_model_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/XGBoost/Train/component.yaml")
|
||||
xgboost_predict_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/XGBoost/Predict/component.yaml")
|
||||
upload_XGBoost_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_XGBoost_model/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml")
|
||||
|
||||
# %% Pipeline definition
|
||||
def train_tabular_regression_model_using_XGBoost_pipeline():
|
||||
|
||||
+18
-18
@@ -2,34 +2,34 @@
|
||||
from kfp import components
|
||||
|
||||
# %% Loading components
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/8c78aae096806cff3bc331a40566f42f5c3e9d4b/components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/23405971f5f16a41b16c343129b893c52e4d1d48/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/daae5a4abaa35e44501818b1534ed7827d7da073/components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
download_from_gcs_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/storage/download/component.yaml")
|
||||
select_columns_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Select_columns/in_CSV_format/component.yaml")
|
||||
fill_all_missing_values_using_Pandas_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml")
|
||||
split_rows_into_subsets_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml")
|
||||
|
||||
# TensorFlow
|
||||
create_fully_connected_tensorflow_network_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/9ca0f9eecf5f896f65b8538bbd809747052617d1/components/tensorflow/Create_fully_connected_network/component.yaml")
|
||||
train_model_using_Keras_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c504a4010348c50eaaf6d4337586ccc008f4dcef/components/tensorflow/Train_model_using_Keras/on_CSV/component.yaml")
|
||||
predict_with_TensorFlow_model_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/59c759ce6f543184e30db6817d2a703879bc0f39/components/tensorflow/Predict/on_CSV/component.yaml")
|
||||
upload_Tensorflow_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
create_fully_connected_tensorflow_network_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Create_fully_connected_network/component.yaml")
|
||||
train_model_using_Keras_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Train_model_using_Keras/on_CSV/component.yaml")
|
||||
predict_with_TensorFlow_model_on_CSV_data_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/tensorflow/Predict/on_CSV/component.yaml")
|
||||
upload_Tensorflow_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/component.yaml")
|
||||
|
||||
# PyTorch
|
||||
create_fully_connected_pytorch_network_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/1a2ef3eeb77bc278f33cad0dd29008ea2431e191/components/PyTorch/Create_fully_connected_network/component.yaml")
|
||||
train_pytorch_model_from_csv_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/d8c4cf5e6403bc65bcf8d606e6baf87e2528a3dc/components/PyTorch/Train_PyTorch_model/from_CSV/component.yaml")
|
||||
create_pytorch_model_archive_with_base_handler_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/46d51383e6554b7f3ab4fd8cf614d8c2b422fb22/components/PyTorch/Create_PyTorch_Model_Archive/with_base_handler/component.yaml")
|
||||
upload_PyTorch_model_archive_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_PyTorch_model_archive/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
create_fully_connected_pytorch_network_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Create_fully_connected_network/component.yaml")
|
||||
train_pytorch_model_from_csv_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Train_PyTorch_model/from_CSV/component.yaml")
|
||||
create_pytorch_model_archive_with_base_handler_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/PyTorch/Create_PyTorch_Model_Archive/with_base_handler/component.yaml")
|
||||
upload_PyTorch_model_archive_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_PyTorch_model_archive/component.yaml")
|
||||
|
||||
# XGBoost
|
||||
train_XGBoost_model_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/58d3a47f904f32a64af8403330ba7e2134cae46d/components/XGBoost/Train/component.yaml")
|
||||
xgboost_predict_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/4694ec97baccf59284c2a1db4aa2250c22291eab/components/XGBoost/Predict/component.yaml")
|
||||
upload_XGBoost_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_XGBoost_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
train_XGBoost_model_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/XGBoost/Train/component.yaml")
|
||||
xgboost_predict_on_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/XGBoost/Predict/component.yaml")
|
||||
upload_XGBoost_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_XGBoost_model/component.yaml")
|
||||
|
||||
# Scikit-learn
|
||||
train_linear_regression_model_using_scikit_learn_from_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/f807e02b54d4886c65a05f40848fd51c72407f40/components/ML_frameworks/Scikit_learn/Train_linear_regression_model/from_CSV/component.yaml")
|
||||
upload_Scikit_learn_pickle_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_Scikit-learn_pickle_model/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
train_linear_regression_model_using_scikit_learn_from_CSV_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/1f5cf6e06409b704064b2086c0a705e4e6b4fcde/community-content/pipeline_components/ML_frameworks/Scikit_learn/Train_linear_regression_model/from_CSV/component.yaml")
|
||||
upload_Scikit_learn_pickle_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_Scikit-learn_pickle_model/component.yaml")
|
||||
|
||||
# Vertex AI
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/Ark-kun/pipeline_components/27a5ea25e849c9e8c0cb6ed65518bc3ece259aaf/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml")
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url("https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml")
|
||||
|
||||
# %% Pipeline definition
|
||||
def train_tabular_regression_model_using_all_frameworks_pipeline():
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
name: Train linear regression model using scikit learn from CSV
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/ML_frameworks/Scikit_learn/Train_linear_regression_model/from_CSV/component.yaml'}
|
||||
inputs:
|
||||
- {name: dataset, type: CSV}
|
||||
- {name: label_column_name, type: String}
|
||||
outputs:
|
||||
- {name: model, type: ScikitLearnPickleModel}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'scikit-learn==1.0.2' 'pandas==1.4.3' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3
|
||||
-m pip install --quiet --no-warn-script-location 'scikit-learn==1.0.2' 'pandas==1.4.3'
|
||||
--user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def train_linear_regression_model_using_scikit_learn_from_CSV(
|
||||
dataset_path,
|
||||
model_path,
|
||||
label_column_name,
|
||||
):
|
||||
import pandas
|
||||
import pickle
|
||||
from sklearn import linear_model
|
||||
|
||||
df = pandas.read_csv(dataset_path)
|
||||
model = linear_model.LinearRegression()
|
||||
model.fit(
|
||||
X=df.drop(columns=label_column_name),
|
||||
y=df[label_column_name],
|
||||
)
|
||||
|
||||
with open(model_path, "wb") as f:
|
||||
pickle.dump(model, f)
|
||||
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Train linear regression model using scikit learn from CSV', description='')
|
||||
_parser.add_argument("--dataset", dest="dataset_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--label-column-name", dest="label_column_name", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--model", dest="model_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = train_linear_regression_model_using_scikit_learn_from_CSV(**_parsed_args)
|
||||
args:
|
||||
- --dataset
|
||||
- {inputPath: dataset}
|
||||
- --label-column-name
|
||||
- {inputValue: label_column_name}
|
||||
- --model
|
||||
- {outputPath: model}
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
name: Train logistic regression model using scikit learn from CSV
|
||||
description: Train logistic regression model using Scikit-learn
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/ML_frameworks/Scikit_learn/Train_logistic_regression_model/from_CSV/component.yaml'}
|
||||
inputs:
|
||||
- {name: dataset, type: CSV}
|
||||
- {name: label_column_name, type: String}
|
||||
- {name: penalty, type: String, default: l2, optional: true}
|
||||
- {name: solver, type: String, default: lbfgs, optional: true}
|
||||
- {name: max_iterations, type: Integer, default: '100', optional: true}
|
||||
- {name: multi_class_mode, type: String, default: auto, optional: true}
|
||||
- {name: random_seed, type: Integer, default: '0', optional: true}
|
||||
outputs:
|
||||
- {name: model, type: ScikitLearnPickleModel}
|
||||
- {name: model_parameters, type: JsonObject}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'scikit-learn==1.0.2' 'pandas==1.4.3' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3
|
||||
-m pip install --quiet --no-warn-script-location 'scikit-learn==1.0.2' 'pandas==1.4.3'
|
||||
--user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def train_logistic_regression_model_using_scikit_learn_from_CSV(
|
||||
dataset_path,
|
||||
model_path,
|
||||
label_column_name,
|
||||
penalty = "l2", # l1, l2, elasticnet, none
|
||||
solver = "lbfgs", # newton-cg, lbfgs, liblinear, sag, saga
|
||||
max_iterations = 100,
|
||||
multi_class_mode = "auto", # auto, ovr, multinomial
|
||||
random_seed = 0,
|
||||
):
|
||||
"""Train logistic regression model using Scikit-learn
|
||||
|
||||
See https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html
|
||||
"""
|
||||
import json
|
||||
import pandas
|
||||
import pickle
|
||||
from sklearn import linear_model
|
||||
|
||||
df = pandas.read_csv(dataset_path)
|
||||
model = linear_model.LogisticRegression(
|
||||
penalty=penalty,
|
||||
#dual=False,
|
||||
#tol=1e-4,
|
||||
#C=1.0,
|
||||
#fit_intercept=True,
|
||||
#intercept_scaling=1,
|
||||
#class_weight=None,
|
||||
random_state=random_seed,
|
||||
solver=solver,
|
||||
max_iter=max_iterations,
|
||||
multi_class=multi_class_mode,
|
||||
#l1_ratio=None,
|
||||
verbose=1,
|
||||
)
|
||||
|
||||
model_parameters = model.get_params()
|
||||
model_parameters_json = json.dumps(model_parameters, indent=2)
|
||||
print("Model parameters:")
|
||||
print(model_parameters_json)
|
||||
print()
|
||||
|
||||
model.fit(
|
||||
X=df.drop(columns=label_column_name),
|
||||
y=df[label_column_name],
|
||||
)
|
||||
|
||||
with open(model_path, "wb") as f:
|
||||
pickle.dump(model, f)
|
||||
|
||||
return (model_parameters_json,)
|
||||
|
||||
def _serialize_json(obj) -> str:
|
||||
if isinstance(obj, str):
|
||||
return obj
|
||||
import json
|
||||
def default_serializer(obj):
|
||||
if hasattr(obj, 'to_struct'):
|
||||
return obj.to_struct()
|
||||
else:
|
||||
raise TypeError("Object of type '%s' is not JSON serializable and does not have .to_struct() method." % obj.__class__.__name__)
|
||||
return json.dumps(obj, default=default_serializer, sort_keys=True)
|
||||
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Train logistic regression model using scikit learn from CSV', description='Train logistic regression model using Scikit-learn')
|
||||
_parser.add_argument("--dataset", dest="dataset_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--label-column-name", dest="label_column_name", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--penalty", dest="penalty", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--solver", dest="solver", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--max-iterations", dest="max_iterations", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--multi-class-mode", dest="multi_class_mode", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--random-seed", dest="random_seed", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--model", dest="model_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=1)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
_output_files = _parsed_args.pop("_output_paths", [])
|
||||
|
||||
_outputs = train_logistic_regression_model_using_scikit_learn_from_CSV(**_parsed_args)
|
||||
|
||||
_output_serializers = [
|
||||
_serialize_json,
|
||||
|
||||
]
|
||||
|
||||
import os
|
||||
for idx, output_file in enumerate(_output_files):
|
||||
try:
|
||||
os.makedirs(os.path.dirname(output_file))
|
||||
except OSError:
|
||||
pass
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(_output_serializers[idx](_outputs[idx]))
|
||||
args:
|
||||
- --dataset
|
||||
- {inputPath: dataset}
|
||||
- --label-column-name
|
||||
- {inputValue: label_column_name}
|
||||
- if:
|
||||
cond: {isPresent: penalty}
|
||||
then:
|
||||
- --penalty
|
||||
- {inputValue: penalty}
|
||||
- if:
|
||||
cond: {isPresent: solver}
|
||||
then:
|
||||
- --solver
|
||||
- {inputValue: solver}
|
||||
- if:
|
||||
cond: {isPresent: max_iterations}
|
||||
then:
|
||||
- --max-iterations
|
||||
- {inputValue: max_iterations}
|
||||
- if:
|
||||
cond: {isPresent: multi_class_mode}
|
||||
then:
|
||||
- --multi-class-mode
|
||||
- {inputValue: multi_class_mode}
|
||||
- if:
|
||||
cond: {isPresent: random_seed}
|
||||
then:
|
||||
- --random-seed
|
||||
- {inputValue: random_seed}
|
||||
- --model
|
||||
- {outputPath: model}
|
||||
- '----output-paths'
|
||||
- {outputPath: model_parameters}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
name: Create PyTorch Model Archive with base handler
|
||||
inputs:
|
||||
- {name: Model, type: PyTorchScriptModule}
|
||||
- {name: Model name, type: String, default: model}
|
||||
- {name: Model version, type: String, default: "1.0"}
|
||||
outputs:
|
||||
- {name: Model archive, type: PyTorchModelArchive}
|
||||
metadata:
|
||||
annotations:
|
||||
author: Alexey Volkov <alexey.volkov@ark-kun.com>
|
||||
canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/PyTorch/Create_PyTorch_Model_Archive/with_base_handler/component.yaml'
|
||||
implementation:
|
||||
container:
|
||||
image: pytorch/torchserve:0.6.0-cpu
|
||||
command:
|
||||
- bash
|
||||
- -exc
|
||||
- |
|
||||
model_path=$0
|
||||
model_name=$1
|
||||
model_version=$2
|
||||
output_model_archive_path=$3
|
||||
|
||||
mkdir -p "$(dirname "$output_model_archive_path")"
|
||||
|
||||
# TODO: Use the built-in base_handler once my fix is merged: https://github.com/pytorch/serve/pull/1682
|
||||
echo '
|
||||
from ts.torch_handler import base_handler
|
||||
class BaseHandler(base_handler.BaseHandler):
|
||||
pass
|
||||
' > base_handler.py # torch-model-archiver needs the handler to have .py extension
|
||||
torch-model-archiver --model-name "$model_name" --version "$model_version" --serialized-file "$model_path" --handler base_handler.py
|
||||
|
||||
# torch-model-archiver does not allow specifying the output path, but always writes to "${model_name}.<format>"
|
||||
expected_model_archive_path="${model_name}.mar"
|
||||
mv "$expected_model_archive_path" "$output_model_archive_path"
|
||||
|
||||
- {inputPath: Model}
|
||||
- {inputValue: Model name}
|
||||
- {inputValue: Model version}
|
||||
- {outputPath: Model archive}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
name: Create fully connected pytorch network
|
||||
description: Creates fully-connected network in PyTorch ScriptModule format
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/PyTorch/Create_fully_connected_network/component.yaml'}
|
||||
inputs:
|
||||
- {name: input_size, type: Integer}
|
||||
- {name: hidden_layer_sizes, type: JsonArray, default: '[]', optional: true}
|
||||
- {name: output_size, type: Integer, default: '1', optional: true}
|
||||
- {name: activation_name, type: String, default: relu, optional: true}
|
||||
- {name: output_activation_name, type: String, optional: true}
|
||||
- {name: random_seed, type: Integer, default: '0', optional: true}
|
||||
outputs:
|
||||
- {name: model, type: PyTorchScriptModule}
|
||||
implementation:
|
||||
container:
|
||||
image: pytorch/pytorch:1.7.1-cuda11.0-cudnn8-runtime
|
||||
command:
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def create_fully_connected_pytorch_network(
|
||||
input_size,
|
||||
model_path,
|
||||
hidden_layer_sizes = [],
|
||||
output_size = 1,
|
||||
activation_name = 'relu',
|
||||
output_activation_name = None,
|
||||
random_seed = 0,
|
||||
):
|
||||
'''Creates fully-connected network in PyTorch ScriptModule format'''
|
||||
import torch
|
||||
torch.manual_seed(random_seed)
|
||||
|
||||
activation = getattr(torch, activation_name, None) or getattr(torch.nn.functional, activation_name, None)
|
||||
if not activation:
|
||||
raise ValueError(f'Activation "{activation_name}" was not found.')
|
||||
|
||||
class ActivationLayer(torch.nn.Module):
|
||||
def forward(self, input):
|
||||
return activation(input)
|
||||
|
||||
layers = []
|
||||
prev_layer_size = input_size
|
||||
for layer_size in hidden_layer_sizes:
|
||||
layer = torch.nn.Linear(prev_layer_size, layer_size)
|
||||
prev_layer_size = layer_size
|
||||
layers.append(layer)
|
||||
layers.append(ActivationLayer())
|
||||
|
||||
# Adding the output layer
|
||||
layers.append(torch.nn.Linear(prev_layer_size, output_size))
|
||||
|
||||
# Adding the optional activation after the output layer
|
||||
if output_activation_name:
|
||||
output_activation = getattr(torch, output_activation_name, None) or getattr(torch.nn.functional, output_activation_name, None)
|
||||
class OutputActivationLayer(torch.nn.Module):
|
||||
def forward(self, input):
|
||||
return output_activation(input)
|
||||
layers.append(OutputActivationLayer())
|
||||
|
||||
network = torch.nn.Sequential(*layers)
|
||||
script_module = torch.jit.script(network)
|
||||
print(script_module)
|
||||
script_module.save(model_path)
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Create fully connected pytorch network', description='Creates fully-connected network in PyTorch ScriptModule format')
|
||||
_parser.add_argument("--input-size", dest="input_size", type=int, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--hidden-layer-sizes", dest="hidden_layer_sizes", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--output-size", dest="output_size", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--activation-name", dest="activation_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--output-activation-name", dest="output_activation_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--random-seed", dest="random_seed", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--model", dest="model_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = create_fully_connected_pytorch_network(**_parsed_args)
|
||||
args:
|
||||
- --input-size
|
||||
- {inputValue: input_size}
|
||||
- if:
|
||||
cond: {isPresent: hidden_layer_sizes}
|
||||
then:
|
||||
- --hidden-layer-sizes
|
||||
- {inputValue: hidden_layer_sizes}
|
||||
- if:
|
||||
cond: {isPresent: output_size}
|
||||
then:
|
||||
- --output-size
|
||||
- {inputValue: output_size}
|
||||
- if:
|
||||
cond: {isPresent: activation_name}
|
||||
then:
|
||||
- --activation-name
|
||||
- {inputValue: activation_name}
|
||||
- if:
|
||||
cond: {isPresent: output_activation_name}
|
||||
then:
|
||||
- --output-activation-name
|
||||
- {inputValue: output_activation_name}
|
||||
- if:
|
||||
cond: {isPresent: random_seed}
|
||||
then:
|
||||
- --random-seed
|
||||
- {inputValue: random_seed}
|
||||
- --model
|
||||
- {outputPath: model}
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
name: Train pytorch model from csv
|
||||
description: Trains PyTorch model
|
||||
metadata:
|
||||
annotations:
|
||||
author: Alexey Volkov <alexey.volkov@ark-kun.com>
|
||||
canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/PyTorch/Train_PyTorch_model/from_CSV/component.yaml'
|
||||
inputs:
|
||||
- {name: model, type: PyTorchScriptModule}
|
||||
- {name: training_data, type: CSV}
|
||||
- {name: label_column_name, type: String}
|
||||
- {name: loss_function_name, type: String, default: mse_loss, optional: true}
|
||||
- {name: number_of_epochs, type: Integer, default: '1', optional: true}
|
||||
- {name: learning_rate, type: Float, default: '0.1', optional: true}
|
||||
- {name: optimizer_name, type: String, default: Adadelta, optional: true}
|
||||
- {name: optimizer_parameters, type: JsonObject, optional: true}
|
||||
- {name: batch_size, type: Integer, default: '32', optional: true}
|
||||
- {name: batch_log_interval, type: Integer, default: '100', optional: true}
|
||||
- {name: random_seed, type: Integer, default: '0', optional: true}
|
||||
outputs:
|
||||
- {name: trained_model, type: PyTorchScriptModule}
|
||||
implementation:
|
||||
container:
|
||||
image: pytorch/pytorch:1.7.1-cuda11.0-cudnn8-runtime
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'pandas==1.4.3' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet
|
||||
--no-warn-script-location 'pandas==1.4.3' --user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def train_pytorch_model_from_csv(
|
||||
model_path,
|
||||
training_data_path,
|
||||
trained_model_path,
|
||||
label_column_name,
|
||||
loss_function_name = 'mse_loss',
|
||||
number_of_epochs = 1,
|
||||
learning_rate = 0.1,
|
||||
optimizer_name = 'Adadelta',
|
||||
optimizer_parameters = None,
|
||||
batch_size = 32,
|
||||
batch_log_interval = 100,
|
||||
random_seed = 0,
|
||||
):
|
||||
'''Trains PyTorch model'''
|
||||
import pandas
|
||||
import torch
|
||||
|
||||
torch.manual_seed(random_seed)
|
||||
|
||||
use_cuda = torch.cuda.is_available()
|
||||
device = torch.device("cuda" if use_cuda else "cpu")
|
||||
|
||||
model = torch.jit.load(model_path)
|
||||
model.to(device)
|
||||
model.train()
|
||||
|
||||
optimizer_class = getattr(torch.optim, optimizer_name, None)
|
||||
if not optimizer_class:
|
||||
raise ValueError(f'Optimizer "{optimizer_name}" was not found.')
|
||||
|
||||
optimizer_parameters = optimizer_parameters or {}
|
||||
optimizer_parameters['lr'] = learning_rate
|
||||
optimizer = optimizer_class(model.parameters(), **optimizer_parameters)
|
||||
|
||||
loss_function = getattr(torch, loss_function_name, None) or getattr(torch.nn, loss_function_name, None) or getattr(torch.nn.functional, loss_function_name, None)
|
||||
if not loss_function:
|
||||
raise ValueError(f'Loss function "{loss_function_name}" was not found.')
|
||||
|
||||
class CsvDataset(torch.utils.data.Dataset):
|
||||
|
||||
def __init__(self, file_path, label_column_name, drop_nan_columns_or_rows = 'columns'):
|
||||
dataframe = pandas.read_csv(file_path).convert_dtypes()
|
||||
# Preventing error: default_collate: batch must contain tensors, numpy arrays, numbers, dicts or lists; found object
|
||||
if drop_nan_columns_or_rows == 'columns':
|
||||
non_nan_data = dataframe.dropna(axis='columns')
|
||||
removed_columns = set(dataframe.columns) - set(non_nan_data.columns)
|
||||
if removed_columns:
|
||||
print('Skipping columns with NaNs: ' + str(removed_columns))
|
||||
dataframe = non_nan_data
|
||||
if drop_nan_columns_or_rows == 'rows':
|
||||
non_nan_data = dataframe.dropna(axis='index')
|
||||
number_of_removed_rows = len(dataframe) - len(non_nan_data)
|
||||
if number_of_removed_rows:
|
||||
print(f'Skipped {number_of_removed_rows} rows with NaNs.')
|
||||
dataframe = non_nan_data
|
||||
numerical_data = dataframe.select_dtypes(include='number')
|
||||
non_numerical_data = dataframe.select_dtypes(exclude='number')
|
||||
if not non_numerical_data.empty:
|
||||
print('Skipping non-number columns:')
|
||||
print(non_numerical_data.dtypes)
|
||||
self._dataframe = dataframe
|
||||
self.labels = numerical_data[[label_column_name]]
|
||||
self.features = numerical_data.drop(columns=[label_column_name])
|
||||
|
||||
def __len__(self):
|
||||
return len(self._dataframe)
|
||||
|
||||
def __getitem__(self, index):
|
||||
return [self.features.loc[index].to_numpy(dtype='float32'), self.labels.loc[index].to_numpy(dtype='float32')]
|
||||
|
||||
dataset = CsvDataset(
|
||||
file_path=training_data_path,
|
||||
label_column_name=label_column_name,
|
||||
)
|
||||
train_loader = torch.utils.data.DataLoader(
|
||||
dataset=dataset,
|
||||
batch_size=batch_size,
|
||||
shuffle=True,
|
||||
)
|
||||
|
||||
last_full_batch_loss = None
|
||||
for epoch in range(1, number_of_epochs + 1):
|
||||
for batch_idx, (data, target) in enumerate(train_loader):
|
||||
data, target = data.to(device), target.to(device)
|
||||
optimizer.zero_grad()
|
||||
output = model(data)
|
||||
loss = loss_function(output, target)
|
||||
loss.backward()
|
||||
optimizer.step()
|
||||
if len(data) == batch_size:
|
||||
last_full_batch_loss = loss.item()
|
||||
if batch_idx % batch_log_interval == 0:
|
||||
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
|
||||
epoch, batch_idx * len(data), len(train_loader.dataset),
|
||||
100. * batch_idx / len(train_loader), loss.item()))
|
||||
print(f'Training epoch {epoch} completed. Last full batch loss: {last_full_batch_loss:.6f}')
|
||||
|
||||
# print(optimizer.state_dict())
|
||||
model.save(trained_model_path)
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Train pytorch model from csv', description='Trains PyTorch model')
|
||||
_parser.add_argument("--model", dest="model_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--training-data", dest="training_data_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--label-column-name", dest="label_column_name", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--loss-function-name", dest="loss_function_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--number-of-epochs", dest="number_of_epochs", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--learning-rate", dest="learning_rate", type=float, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--optimizer-name", dest="optimizer_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--optimizer-parameters", dest="optimizer_parameters", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--batch-size", dest="batch_size", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--batch-log-interval", dest="batch_log_interval", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--random-seed", dest="random_seed", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--trained-model", dest="trained_model_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = train_pytorch_model_from_csv(**_parsed_args)
|
||||
args:
|
||||
- --model
|
||||
- {inputPath: model}
|
||||
- --training-data
|
||||
- {inputPath: training_data}
|
||||
- --label-column-name
|
||||
- {inputValue: label_column_name}
|
||||
- if:
|
||||
cond: {isPresent: loss_function_name}
|
||||
then:
|
||||
- --loss-function-name
|
||||
- {inputValue: loss_function_name}
|
||||
- if:
|
||||
cond: {isPresent: number_of_epochs}
|
||||
then:
|
||||
- --number-of-epochs
|
||||
- {inputValue: number_of_epochs}
|
||||
- if:
|
||||
cond: {isPresent: learning_rate}
|
||||
then:
|
||||
- --learning-rate
|
||||
- {inputValue: learning_rate}
|
||||
- if:
|
||||
cond: {isPresent: optimizer_name}
|
||||
then:
|
||||
- --optimizer-name
|
||||
- {inputValue: optimizer_name}
|
||||
- if:
|
||||
cond: {isPresent: optimizer_parameters}
|
||||
then:
|
||||
- --optimizer-parameters
|
||||
- {inputValue: optimizer_parameters}
|
||||
- if:
|
||||
cond: {isPresent: batch_size}
|
||||
then:
|
||||
- --batch-size
|
||||
- {inputValue: batch_size}
|
||||
- if:
|
||||
cond: {isPresent: batch_log_interval}
|
||||
then:
|
||||
- --batch-log-interval
|
||||
- {inputValue: batch_log_interval}
|
||||
- if:
|
||||
cond: {isPresent: random_seed}
|
||||
then:
|
||||
- --random-seed
|
||||
- {inputValue: random_seed}
|
||||
- --trained-model
|
||||
- {outputPath: trained_model}
|
||||
@@ -0,0 +1,110 @@
|
||||
name: Xgboost predict on CSV
|
||||
description: Makes predictions using a trained XGBoost model.
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/XGBoost/Predict/component.yaml'}
|
||||
inputs:
|
||||
- {name: data, type: CSV, description: Feature data in Apache Parquet format.}
|
||||
- {name: model, type: XGBoostModel, description: Trained model in binary XGBoost format.}
|
||||
- {name: label_column_name, type: String, description: Optional. Name of the column
|
||||
containing the label data that is excluded during the prediction., optional: true}
|
||||
outputs:
|
||||
- {name: predictions, description: Model predictions.}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.10
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'xgboost==1.6.1' 'pandas==1.4.3' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3
|
||||
-m pip install --quiet --no-warn-script-location 'xgboost==1.6.1' 'pandas==1.4.3'
|
||||
--user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def xgboost_predict_on_CSV(
|
||||
data_path,
|
||||
model_path,
|
||||
predictions_path,
|
||||
label_column_name = None,
|
||||
):
|
||||
"""Makes predictions using a trained XGBoost model.
|
||||
|
||||
Args:
|
||||
data_path: Feature data in Apache Parquet format.
|
||||
model_path: Trained model in binary XGBoost format.
|
||||
predictions_path: Model predictions.
|
||||
label_column_name: Optional. Name of the column containing the label data that is excluded during the prediction.
|
||||
|
||||
Annotations:
|
||||
author: Alexey Volkov <alexey.volkov@ark-kun.com>
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
import numpy
|
||||
import pandas
|
||||
import xgboost
|
||||
|
||||
df = pandas.read_csv(
|
||||
data_path,
|
||||
).convert_dtypes()
|
||||
print("Evaluation data information:")
|
||||
df.info(verbose=True)
|
||||
# Converting column types that XGBoost does not support
|
||||
for column_name, dtype in df.dtypes.items():
|
||||
if dtype in ["string", "object"]:
|
||||
print(f"Treating the {dtype.name} column '{column_name}' as categorical.")
|
||||
df[column_name] = df[column_name].astype("category")
|
||||
print(f"Inferred {len(df[column_name].cat.categories)} categories for the '{column_name}' column.")
|
||||
# Working around the XGBoost issue with nullable floats: https://github.com/dmlc/xgboost/issues/8213
|
||||
if pandas.api.types.is_float_dtype(dtype):
|
||||
# Converting from "Float64" to "float64"
|
||||
df[column_name] = df[column_name].astype(dtype.name.lower())
|
||||
print("Final evaluation data information:")
|
||||
df.info(verbose=True)
|
||||
|
||||
if label_column_name is not None:
|
||||
df = df.drop(columns=[label_column_name])
|
||||
|
||||
testing_data = xgboost.DMatrix(
|
||||
data=df,
|
||||
enable_categorical=True,
|
||||
)
|
||||
|
||||
model = xgboost.Booster(model_file=model_path)
|
||||
|
||||
predictions = model.predict(testing_data)
|
||||
|
||||
Path(predictions_path).parent.mkdir(parents=True, exist_ok=True)
|
||||
numpy.savetxt(predictions_path, predictions)
|
||||
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Xgboost predict on CSV', description='Makes predictions using a trained XGBoost model.')
|
||||
_parser.add_argument("--data", dest="data_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--model", dest="model_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--label-column-name", dest="label_column_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--predictions", dest="predictions_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = xgboost_predict_on_CSV(**_parsed_args)
|
||||
args:
|
||||
- --data
|
||||
- {inputPath: data}
|
||||
- --model
|
||||
- {inputPath: model}
|
||||
- if:
|
||||
cond: {isPresent: label_column_name}
|
||||
then:
|
||||
- --label-column-name
|
||||
- {inputValue: label_column_name}
|
||||
- --predictions
|
||||
- {outputPath: predictions}
|
||||
@@ -0,0 +1,241 @@
|
||||
name: Train XGBoost model on CSV
|
||||
description: Trains an XGBoost model.
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/XGBoost/Train/component.yaml'}
|
||||
inputs:
|
||||
- {name: training_data, type: CSV, description: Training data in CSV format.}
|
||||
- {name: label_column_name, type: String, description: Name of the column containing
|
||||
the label data.}
|
||||
- {name: starting_model, type: XGBoostModel, description: Existing trained model to
|
||||
start from (in the binary XGBoost format)., optional: true}
|
||||
- {name: num_iterations, type: Integer, description: Number of boosting iterations.,
|
||||
default: '10', optional: true}
|
||||
- name: objective
|
||||
type: String
|
||||
description: |-
|
||||
The learning task and the corresponding learning objective.
|
||||
See https://xgboost.readthedocs.io/en/latest/parameter.html#learning-task-parameters
|
||||
The most common values are:
|
||||
"reg:squarederror" - Regression with squared loss (default).
|
||||
"reg:logistic" - Logistic regression.
|
||||
"binary:logistic" - Logistic regression for binary classification, output probability.
|
||||
"binary:logitraw" - Logistic regression for binary classification, output score before logistic transformation
|
||||
"rank:pairwise" - Use LambdaMART to perform pairwise ranking where the pairwise loss is minimized
|
||||
"rank:ndcg" - Use LambdaMART to perform list-wise ranking where Normalized Discounted Cumulative Gain (NDCG) is maximized
|
||||
default: reg:squarederror
|
||||
optional: true
|
||||
- {name: booster, type: String, description: 'The booster to use. Can be `gbtree`,
|
||||
`gblinear` or `dart`; `gbtree` and `dart` use tree based models while `gblinear`
|
||||
uses linear functions.', default: gbtree, optional: true}
|
||||
- {name: learning_rate, type: Float, description: 'Step size shrinkage used in update
|
||||
to prevents overfitting. Range: [0,1].', default: '0.3', optional: true}
|
||||
- name: min_split_loss
|
||||
type: Float
|
||||
description: |-
|
||||
Minimum loss reduction required to make a further partition on a leaf node of the tree.
|
||||
The larger `min_split_loss` is, the more conservative the algorithm will be. Range: [0,Inf].
|
||||
default: '0'
|
||||
optional: true
|
||||
- name: max_depth
|
||||
type: Integer
|
||||
description: |-
|
||||
Maximum depth of a tree. Increasing this value will make the model more complex and more likely to overfit.
|
||||
0 indicates no limit on depth. Range: [0,Inf].
|
||||
default: '6'
|
||||
optional: true
|
||||
- {name: booster_params, type: JsonObject, description: 'Parameters for the booster.
|
||||
See https://xgboost.readthedocs.io/en/latest/parameter.html', optional: true}
|
||||
outputs:
|
||||
- {name: model, type: XGBoostModel, description: Trained model in the binary XGBoost
|
||||
format.}
|
||||
- {name: model_config, type: XGBoostModelConfig, description: The internal parameter
|
||||
configuration of Booster as a JSON string.}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.10
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'xgboost==1.6.1' 'pandas==1.4.3' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3
|
||||
-m pip install --quiet --no-warn-script-location 'xgboost==1.6.1' 'pandas==1.4.3'
|
||||
--user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def train_XGBoost_model_on_CSV(
|
||||
training_data_path,
|
||||
model_path,
|
||||
model_config_path,
|
||||
label_column_name,
|
||||
starting_model_path = None,
|
||||
num_iterations = 10,
|
||||
# Booster parameters
|
||||
objective = "reg:squarederror",
|
||||
booster = "gbtree",
|
||||
learning_rate = 0.3,
|
||||
min_split_loss = 0,
|
||||
max_depth = 6,
|
||||
booster_params = None,
|
||||
):
|
||||
"""Trains an XGBoost model.
|
||||
|
||||
Args:
|
||||
training_data_path: Training data in CSV format.
|
||||
model_path: Trained model in the binary XGBoost format.
|
||||
model_config_path: The internal parameter configuration of Booster as a JSON string.
|
||||
starting_model_path: Existing trained model to start from (in the binary XGBoost format).
|
||||
label_column_name: Name of the column containing the label data.
|
||||
num_iterations: Number of boosting iterations.
|
||||
booster_params: Parameters for the booster. See https://xgboost.readthedocs.io/en/latest/parameter.html
|
||||
objective: The learning task and the corresponding learning objective.
|
||||
See https://xgboost.readthedocs.io/en/latest/parameter.html#learning-task-parameters
|
||||
The most common values are:
|
||||
"reg:squarederror" - Regression with squared loss (default).
|
||||
"reg:logistic" - Logistic regression.
|
||||
"binary:logistic" - Logistic regression for binary classification, output probability.
|
||||
"binary:logitraw" - Logistic regression for binary classification, output score before logistic transformation
|
||||
"rank:pairwise" - Use LambdaMART to perform pairwise ranking where the pairwise loss is minimized
|
||||
"rank:ndcg" - Use LambdaMART to perform list-wise ranking where Normalized Discounted Cumulative Gain (NDCG) is maximized
|
||||
booster: The booster to use. Can be `gbtree`, `gblinear` or `dart`; `gbtree` and `dart` use tree based models while `gblinear` uses linear functions.
|
||||
learning_rate: Step size shrinkage used in update to prevents overfitting. Range: [0,1].
|
||||
min_split_loss: Minimum loss reduction required to make a further partition on a leaf node of the tree.
|
||||
The larger `min_split_loss` is, the more conservative the algorithm will be. Range: [0,Inf].
|
||||
max_depth: Maximum depth of a tree. Increasing this value will make the model more complex and more likely to overfit.
|
||||
0 indicates no limit on depth. Range: [0,Inf].
|
||||
|
||||
Annotations:
|
||||
author: Alexey Volkov <alexey.volkov@ark-kun.com>
|
||||
"""
|
||||
import pandas
|
||||
import xgboost
|
||||
|
||||
df = pandas.read_csv(
|
||||
training_data_path,
|
||||
).convert_dtypes()
|
||||
print("Training data information:")
|
||||
df.info(verbose=True)
|
||||
# Converting column types that XGBoost does not support
|
||||
for column_name, dtype in df.dtypes.items():
|
||||
if dtype in ["string", "object"]:
|
||||
print(f"Treating the {dtype.name} column '{column_name}' as categorical.")
|
||||
df[column_name] = df[column_name].astype("category")
|
||||
print(f"Inferred {len(df[column_name].cat.categories)} categories for the '{column_name}' column.")
|
||||
# Working around the XGBoost issue with nullable floats: https://github.com/dmlc/xgboost/issues/8213
|
||||
if pandas.api.types.is_float_dtype(dtype):
|
||||
# Converting from "Float64" to "float64"
|
||||
df[column_name] = df[column_name].astype(dtype.name.lower())
|
||||
print()
|
||||
print("Final training data information:")
|
||||
df.info(verbose=True)
|
||||
|
||||
training_data = xgboost.DMatrix(
|
||||
data=df.drop(columns=[label_column_name]),
|
||||
label=df[[label_column_name]],
|
||||
enable_categorical=True,
|
||||
)
|
||||
|
||||
booster_params = booster_params or {}
|
||||
booster_params.setdefault("objective", objective)
|
||||
booster_params.setdefault("booster", booster)
|
||||
booster_params.setdefault("learning_rate", learning_rate)
|
||||
booster_params.setdefault("min_split_loss", min_split_loss)
|
||||
booster_params.setdefault("max_depth", max_depth)
|
||||
|
||||
starting_model = None
|
||||
if starting_model_path:
|
||||
starting_model = xgboost.Booster(model_file=starting_model_path)
|
||||
|
||||
print()
|
||||
print("Training the model:")
|
||||
model = xgboost.train(
|
||||
params=booster_params,
|
||||
dtrain=training_data,
|
||||
num_boost_round=num_iterations,
|
||||
xgb_model=starting_model,
|
||||
evals=[(training_data, "training_data")],
|
||||
)
|
||||
|
||||
# Saving the model in binary format
|
||||
model.save_model(model_path)
|
||||
|
||||
model_config_str = model.save_config()
|
||||
with open(model_config_path, "w") as model_config_file:
|
||||
model_config_file.write(model_config_str)
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Train XGBoost model on CSV', description='Trains an XGBoost model.')
|
||||
_parser.add_argument("--training-data", dest="training_data_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--label-column-name", dest="label_column_name", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--starting-model", dest="starting_model_path", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--num-iterations", dest="num_iterations", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--objective", dest="objective", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--booster", dest="booster", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--learning-rate", dest="learning_rate", type=float, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--min-split-loss", dest="min_split_loss", type=float, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--max-depth", dest="max_depth", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--booster-params", dest="booster_params", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--model", dest="model_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--model-config", dest="model_config_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = train_XGBoost_model_on_CSV(**_parsed_args)
|
||||
args:
|
||||
- --training-data
|
||||
- {inputPath: training_data}
|
||||
- --label-column-name
|
||||
- {inputValue: label_column_name}
|
||||
- if:
|
||||
cond: {isPresent: starting_model}
|
||||
then:
|
||||
- --starting-model
|
||||
- {inputPath: starting_model}
|
||||
- if:
|
||||
cond: {isPresent: num_iterations}
|
||||
then:
|
||||
- --num-iterations
|
||||
- {inputValue: num_iterations}
|
||||
- if:
|
||||
cond: {isPresent: objective}
|
||||
then:
|
||||
- --objective
|
||||
- {inputValue: objective}
|
||||
- if:
|
||||
cond: {isPresent: booster}
|
||||
then:
|
||||
- --booster
|
||||
- {inputValue: booster}
|
||||
- if:
|
||||
cond: {isPresent: learning_rate}
|
||||
then:
|
||||
- --learning-rate
|
||||
- {inputValue: learning_rate}
|
||||
- if:
|
||||
cond: {isPresent: min_split_loss}
|
||||
then:
|
||||
- --min-split-loss
|
||||
- {inputValue: min_split_loss}
|
||||
- if:
|
||||
cond: {isPresent: max_depth}
|
||||
then:
|
||||
- --max-depth
|
||||
- {inputValue: max_depth}
|
||||
- if:
|
||||
cond: {isPresent: booster_params}
|
||||
then:
|
||||
- --booster-params
|
||||
- {inputValue: booster_params}
|
||||
- --model
|
||||
- {outputPath: model}
|
||||
- --model-config
|
||||
- {outputPath: model_config}
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
name: Split rows into subsets
|
||||
description: Splits the data table according to the split fractions.
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/dataset_manipulation/Split_rows_into_subsets/in_CSV/component.yaml'}
|
||||
inputs:
|
||||
- {name: table, type: CSV}
|
||||
- {name: fraction_1, type: Float, description: 'The proportion of the lines to put
|
||||
into the 1st split. Range: [0, 1]'}
|
||||
- name: fraction_2
|
||||
type: Float
|
||||
description: |-
|
||||
The proportion of the lines to put into the 2nd split. Range: [0, 1]
|
||||
If fraction_2 is not specified, then fraction_2 = 1 - fraction_1.
|
||||
The remaining lines go to the 3rd split (if any).
|
||||
optional: true
|
||||
- {name: random_seed, type: Integer, default: '0', optional: true}
|
||||
outputs:
|
||||
- {name: split_1, type: CSV}
|
||||
- {name: split_2, type: CSV}
|
||||
- {name: split_3, type: CSV}
|
||||
- {name: split_1_count, type: Integer}
|
||||
- {name: split_2_count, type: Integer}
|
||||
- {name: split_3_count, type: Integer}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def split_rows_into_subsets(
|
||||
table_path,
|
||||
split_1_path,
|
||||
split_2_path,
|
||||
split_3_path,
|
||||
fraction_1,
|
||||
fraction_2 = None,
|
||||
random_seed = 0,
|
||||
):
|
||||
"""Splits the data table according to the split fractions.
|
||||
|
||||
Args:
|
||||
fraction_1: The proportion of the lines to put into the 1st split. Range: [0, 1]
|
||||
fraction_2: The proportion of the lines to put into the 2nd split. Range: [0, 1]
|
||||
If fraction_2 is not specified, then fraction_2 = 1 - fraction_1.
|
||||
The remaining lines go to the 3rd split (if any).
|
||||
"""
|
||||
import random
|
||||
|
||||
random.seed(random_seed)
|
||||
|
||||
SHUFFLE_BUFFER_SIZE = 10000
|
||||
|
||||
num_splits = 3
|
||||
|
||||
if fraction_1 < 0 or fraction_1 > 1:
|
||||
raise ValueError("fraction_1 must be in between 0 and 1.")
|
||||
|
||||
if fraction_2 is None:
|
||||
fraction_2 = 1 - fraction_1
|
||||
if fraction_2 < 0 or fraction_2 > 1:
|
||||
raise ValueError("fraction_2 must be in between 0 and 1.")
|
||||
|
||||
fraction_3 = 1 - fraction_1 - fraction_2
|
||||
|
||||
fractions = [
|
||||
fraction_1,
|
||||
fraction_2,
|
||||
fraction_3,
|
||||
]
|
||||
|
||||
assert sum(fractions) == 1
|
||||
|
||||
written_line_counts = [0] * num_splits
|
||||
|
||||
output_files = [
|
||||
open(split_1_path, "wb"),
|
||||
open(split_2_path, "wb"),
|
||||
open(split_3_path, "wb"),
|
||||
]
|
||||
|
||||
with open(table_path, "rb") as input_file:
|
||||
# Writing the headers
|
||||
header_line = input_file.readline()
|
||||
for output_file in output_files:
|
||||
output_file.write(header_line)
|
||||
|
||||
while True:
|
||||
line_buffer = []
|
||||
for i in range(SHUFFLE_BUFFER_SIZE):
|
||||
line = input_file.readline()
|
||||
if not line:
|
||||
break
|
||||
line_buffer.append(line)
|
||||
|
||||
# We need to exactly partition the lines between the output files
|
||||
# To overcome possible systematic bias, we could calculate the total numbers
|
||||
# of lines written to each file and take that into account.
|
||||
num_read_lines = len(line_buffer)
|
||||
number_of_lines_for_files = [0] * num_splits
|
||||
# List that will have the index of the destination file for each line
|
||||
file_index_for_line = []
|
||||
remaining_lines = num_read_lines
|
||||
remaining_fraction = 1
|
||||
for i in range(num_splits):
|
||||
number_of_lines_for_file = (
|
||||
round(remaining_lines * (fractions[i] / remaining_fraction))
|
||||
if remaining_fraction > 0
|
||||
else 0
|
||||
)
|
||||
number_of_lines_for_files[i] = number_of_lines_for_file
|
||||
remaining_lines -= number_of_lines_for_file
|
||||
remaining_fraction -= fractions[i]
|
||||
file_index_for_line.extend([i] * number_of_lines_for_file)
|
||||
|
||||
assert remaining_lines == 0, f"{remaining_lines}"
|
||||
assert len(file_index_for_line) == num_read_lines
|
||||
|
||||
random.shuffle(file_index_for_line)
|
||||
|
||||
for i in range(num_read_lines):
|
||||
output_files[file_index_for_line[i]].write(line_buffer[i])
|
||||
written_line_counts[file_index_for_line[i]] += 1
|
||||
|
||||
# Exit if the file ended before we were able to fully fill the buffer
|
||||
if len(line_buffer) != SHUFFLE_BUFFER_SIZE:
|
||||
break
|
||||
|
||||
for output_file in output_files:
|
||||
output_file.close()
|
||||
|
||||
return written_line_counts
|
||||
|
||||
def _serialize_int(int_value: int) -> str:
|
||||
if isinstance(int_value, str):
|
||||
return int_value
|
||||
if not isinstance(int_value, int):
|
||||
raise TypeError('Value "{}" has type "{}" instead of int.'.format(str(int_value), str(type(int_value))))
|
||||
return str(int_value)
|
||||
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Split rows into subsets', description='Splits the data table according to the split fractions.')
|
||||
_parser.add_argument("--table", dest="table_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--fraction-1", dest="fraction_1", type=float, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--fraction-2", dest="fraction_2", type=float, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--random-seed", dest="random_seed", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--split-1", dest="split_1_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--split-2", dest="split_2_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--split-3", dest="split_3_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=3)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
_output_files = _parsed_args.pop("_output_paths", [])
|
||||
|
||||
_outputs = split_rows_into_subsets(**_parsed_args)
|
||||
|
||||
_output_serializers = [
|
||||
_serialize_int,
|
||||
_serialize_int,
|
||||
_serialize_int,
|
||||
|
||||
]
|
||||
|
||||
import os
|
||||
for idx, output_file in enumerate(_output_files):
|
||||
try:
|
||||
os.makedirs(os.path.dirname(output_file))
|
||||
except OSError:
|
||||
pass
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(_output_serializers[idx](_outputs[idx]))
|
||||
args:
|
||||
- --table
|
||||
- {inputPath: table}
|
||||
- --fraction-1
|
||||
- {inputValue: fraction_1}
|
||||
- if:
|
||||
cond: {isPresent: fraction_2}
|
||||
then:
|
||||
- --fraction-2
|
||||
- {inputValue: fraction_2}
|
||||
- if:
|
||||
cond: {isPresent: random_seed}
|
||||
then:
|
||||
- --random-seed
|
||||
- {inputValue: random_seed}
|
||||
- --split-1
|
||||
- {outputPath: split_1}
|
||||
- --split-2
|
||||
- {outputPath: split_2}
|
||||
- --split-3
|
||||
- {outputPath: split_3}
|
||||
- '----output-paths'
|
||||
- {outputPath: split_1_count}
|
||||
- {outputPath: split_2_count}
|
||||
- {outputPath: split_3_count}
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
name: Deploy model to endpoint for Google Cloud Vertex AI Model
|
||||
description: Deploys Google Cloud Vertex AI Model to a Google Cloud Vertex AI Endpoint.
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/KFPv2_hell/components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/workaround_for_buggy_KFPv2_compiler/component.yaml'}
|
||||
inputs:
|
||||
- {name: model_name, type: String, description: Full resource name of a Google Cloud
|
||||
Vertex AI Model}
|
||||
- name: endpoint_name
|
||||
type: String
|
||||
description: |-
|
||||
Optional. Full name of Google Cloud Vertex Endpoint. A new
|
||||
endpoint is created if the name is not passed.
|
||||
optional: true
|
||||
- name: machine_type
|
||||
type: String
|
||||
description: |-
|
||||
The type of the machine. See the [list of machine types
|
||||
supported for prediction
|
||||
](https://cloud.google.com/vertex-ai/docs/predictions/configure-compute#machine-types).
|
||||
Defaults to "n1-standard-2"
|
||||
default: n1-standard-2
|
||||
optional: true
|
||||
- name: min_replica_count
|
||||
type: Integer
|
||||
description: |-
|
||||
Optional. The minimum number of machine replicas this deployed
|
||||
model will be always deployed on. If traffic against it increases,
|
||||
it may dynamically be deployed onto more replicas, and as traffic
|
||||
decreases, some of these extra replicas may be freed.
|
||||
default: '1'
|
||||
optional: true
|
||||
- name: max_replica_count
|
||||
type: Integer
|
||||
description: |-
|
||||
Optional. The maximum number of replicas this deployed model may
|
||||
be deployed on when the traffic against it increases. If requested
|
||||
value is too large, the deployment will error, but if deployment
|
||||
succeeds then the ability to scale the model to that many replicas
|
||||
is guaranteed (barring service outages). If traffic against the
|
||||
deployed model increases beyond what its replicas at maximum may
|
||||
handle, a portion of the traffic will be dropped. If this value
|
||||
is not provided, the smaller value of min_replica_count or 1 will
|
||||
be used.
|
||||
default: '1'
|
||||
optional: true
|
||||
- name: accelerator_type
|
||||
type: String
|
||||
description: |-
|
||||
Optional. Hardware accelerator type. Must also set accelerator_count if used.
|
||||
One of ACCELERATOR_TYPE_UNSPECIFIED, NVIDIA_TESLA_K80, NVIDIA_TESLA_P100,
|
||||
NVIDIA_TESLA_V100, NVIDIA_TESLA_P4, NVIDIA_TESLA_T4
|
||||
optional: true
|
||||
- {name: accelerator_count, type: Integer, description: Optional. The number of accelerators
|
||||
to attach to a worker replica., optional: true}
|
||||
outputs:
|
||||
- {name: endpoint_name, type: String}
|
||||
- {name: endpoint_dict, type: JsonObject}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'google-cloud-aiplatform==1.7.0' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3
|
||||
-m pip install --quiet --no-warn-script-location 'google-cloud-aiplatform==1.7.0'
|
||||
--user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def deploy_model_to_endpoint_for_Google_Cloud_Vertex_AI_Model(
|
||||
model_name,
|
||||
endpoint_name = None,
|
||||
machine_type = "n1-standard-2",
|
||||
min_replica_count = 1,
|
||||
max_replica_count = 1,
|
||||
accelerator_type = None,
|
||||
accelerator_count = None,
|
||||
#
|
||||
# Uncomment when anyone requests these:
|
||||
# deployed_model_display_name: str = None,
|
||||
# traffic_percentage: int = 0,
|
||||
# traffic_split: dict = None,
|
||||
# service_account: str = None,
|
||||
# explanation_metadata: "google.cloud.aiplatform_v1.types.explanation_metadata.ExplanationMetadata" = None,
|
||||
# explanation_parameters: "google.cloud.aiplatform_v1.types.explanation.ExplanationParameters" = None,
|
||||
#
|
||||
# encryption_spec_key_name: str = None,
|
||||
):
|
||||
"""Deploys Google Cloud Vertex AI Model to a Google Cloud Vertex AI Endpoint.
|
||||
|
||||
Args:
|
||||
model_name: Full resource name of a Google Cloud Vertex AI Model
|
||||
endpoint_name: Optional. Full name of Google Cloud Vertex Endpoint. A new
|
||||
endpoint is created if the name is not passed.
|
||||
machine_type: The type of the machine. See the [list of machine types
|
||||
supported for prediction
|
||||
](https://cloud.google.com/vertex-ai/docs/predictions/configure-compute#machine-types).
|
||||
Defaults to "n1-standard-2"
|
||||
min_replica_count (int):
|
||||
Optional. The minimum number of machine replicas this deployed
|
||||
model will be always deployed on. If traffic against it increases,
|
||||
it may dynamically be deployed onto more replicas, and as traffic
|
||||
decreases, some of these extra replicas may be freed.
|
||||
max_replica_count (int):
|
||||
Optional. The maximum number of replicas this deployed model may
|
||||
be deployed on when the traffic against it increases. If requested
|
||||
value is too large, the deployment will error, but if deployment
|
||||
succeeds then the ability to scale the model to that many replicas
|
||||
is guaranteed (barring service outages). If traffic against the
|
||||
deployed model increases beyond what its replicas at maximum may
|
||||
handle, a portion of the traffic will be dropped. If this value
|
||||
is not provided, the smaller value of min_replica_count or 1 will
|
||||
be used.
|
||||
accelerator_type (str):
|
||||
Optional. Hardware accelerator type. Must also set accelerator_count if used.
|
||||
One of ACCELERATOR_TYPE_UNSPECIFIED, NVIDIA_TESLA_K80, NVIDIA_TESLA_P100,
|
||||
NVIDIA_TESLA_V100, NVIDIA_TESLA_P4, NVIDIA_TESLA_T4
|
||||
accelerator_count (int):
|
||||
Optional. The number of accelerators to attach to a worker replica.
|
||||
"""
|
||||
import json
|
||||
from google.cloud import aiplatform
|
||||
|
||||
model = aiplatform.Model(model_name=model_name)
|
||||
|
||||
if endpoint_name:
|
||||
endpoint = aiplatform.Endpoint(endpoint_name=endpoint_name)
|
||||
else:
|
||||
endpoint_display_name = model.display_name[:118] + "_endpoint"
|
||||
endpoint = aiplatform.Endpoint.create(
|
||||
display_name=endpoint_display_name,
|
||||
project=model.project,
|
||||
location=model.location,
|
||||
# encryption_spec_key_name=encryption_spec_key_name,
|
||||
labels={"component-source": "github-com-ark-kun-pipeline-components"},
|
||||
)
|
||||
|
||||
endpoint = model.deploy(
|
||||
endpoint=endpoint,
|
||||
# deployed_model_display_name=deployed_model_display_name,
|
||||
machine_type=machine_type,
|
||||
min_replica_count=min_replica_count,
|
||||
max_replica_count=max_replica_count,
|
||||
accelerator_type=accelerator_type,
|
||||
accelerator_count=accelerator_count,
|
||||
# service_account=service_account,
|
||||
# explanation_metadata=explanation_metadata,
|
||||
# explanation_parameters=explanation_parameters,
|
||||
# encryption_spec_key_name=encryption_spec_key_name,
|
||||
)
|
||||
|
||||
endpoint_json = json.dumps(endpoint.to_dict(), indent=2)
|
||||
print(endpoint_json)
|
||||
return (endpoint.resource_name, endpoint_json)
|
||||
|
||||
def _serialize_json(obj) -> str:
|
||||
if isinstance(obj, str):
|
||||
return obj
|
||||
import json
|
||||
def default_serializer(obj):
|
||||
if hasattr(obj, 'to_struct'):
|
||||
return obj.to_struct()
|
||||
else:
|
||||
raise TypeError("Object of type '%s' is not JSON serializable and does not have .to_struct() method." % obj.__class__.__name__)
|
||||
return json.dumps(obj, default=default_serializer, sort_keys=True)
|
||||
|
||||
def _serialize_str(str_value: str) -> str:
|
||||
if not isinstance(str_value, str):
|
||||
raise TypeError('Value "{}" has type "{}" instead of str.'.format(str(str_value), str(type(str_value))))
|
||||
return str_value
|
||||
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Deploy model to endpoint for Google Cloud Vertex AI Model', description='Deploys Google Cloud Vertex AI Model to a Google Cloud Vertex AI Endpoint.')
|
||||
_parser.add_argument("--model-name", dest="model_name", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--endpoint-name", dest="endpoint_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--machine-type", dest="machine_type", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--min-replica-count", dest="min_replica_count", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--max-replica-count", dest="max_replica_count", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--accelerator-type", dest="accelerator_type", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--accelerator-count", dest="accelerator_count", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=2)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
_output_files = _parsed_args.pop("_output_paths", [])
|
||||
|
||||
_outputs = deploy_model_to_endpoint_for_Google_Cloud_Vertex_AI_Model(**_parsed_args)
|
||||
|
||||
_output_serializers = [
|
||||
_serialize_str,
|
||||
_serialize_json,
|
||||
|
||||
]
|
||||
|
||||
import os
|
||||
for idx, output_file in enumerate(_output_files):
|
||||
try:
|
||||
os.makedirs(os.path.dirname(output_file))
|
||||
except OSError:
|
||||
pass
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(_output_serializers[idx](_outputs[idx]))
|
||||
args:
|
||||
- --model-name
|
||||
- {inputValue: model_name}
|
||||
- if:
|
||||
cond: {isPresent: endpoint_name}
|
||||
then:
|
||||
- --endpoint-name
|
||||
- {inputValue: endpoint_name}
|
||||
- if:
|
||||
cond: {isPresent: machine_type}
|
||||
then:
|
||||
- --machine-type
|
||||
- {inputValue: machine_type}
|
||||
- if:
|
||||
cond: {isPresent: min_replica_count}
|
||||
then:
|
||||
- --min-replica-count
|
||||
- {inputValue: min_replica_count}
|
||||
- if:
|
||||
cond: {isPresent: max_replica_count}
|
||||
then:
|
||||
- --max-replica-count
|
||||
- {inputValue: max_replica_count}
|
||||
- if:
|
||||
cond: {isPresent: accelerator_type}
|
||||
then:
|
||||
- --accelerator-type
|
||||
- {inputValue: accelerator_type}
|
||||
- if:
|
||||
cond: {isPresent: accelerator_count}
|
||||
then:
|
||||
- --accelerator-count
|
||||
- {inputValue: accelerator_count}
|
||||
- '----output-paths'
|
||||
- {outputPath: endpoint_name}
|
||||
- {outputPath: endpoint_dict}
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
name: Upload PyTorch model archive to Google Cloud Vertex AI
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/KFPv2_hell/components/google-cloud/Vertex_AI/Models/Upload_PyTorch_model_archive/workaround_for_buggy_KFPv2_compiler/component.yaml'}
|
||||
inputs:
|
||||
- {name: model_archive, type: PyTorchModelArchive}
|
||||
- {name: torchserve_version, type: String, default: 0.6.0, optional: true}
|
||||
- name: use_gpu
|
||||
type: Boolean
|
||||
default: "False"
|
||||
optional: true
|
||||
- {name: display_name, type: String, optional: true}
|
||||
- {name: description, type: String, optional: true}
|
||||
- {name: project, type: String, optional: true}
|
||||
- {name: location, type: String, optional: true}
|
||||
- {name: labels, type: JsonObject, optional: true}
|
||||
- {name: staging_bucket, type: String, optional: true}
|
||||
outputs:
|
||||
- {name: model_name, type: String}
|
||||
- {name: model_dict, type: JsonObject}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'google-cloud-aiplatform==1.13.1' 'google-cloud-build==3.8.3' || PIP_DISABLE_PIP_VERSION_CHECK=1
|
||||
python3 -m pip install --quiet --no-warn-script-location 'google-cloud-aiplatform==1.13.1'
|
||||
'google-cloud-build==3.8.3' --user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def upload_PyTorch_model_archive_to_Google_Cloud_Vertex_AI(
|
||||
model_archive_path,
|
||||
torchserve_version = "0.6.0",
|
||||
use_gpu = False,
|
||||
|
||||
display_name = None,
|
||||
description = None,
|
||||
|
||||
# Uncomment when anyone requests these:
|
||||
# instance_schema_uri: str = None,
|
||||
# parameters_schema_uri: str = None,
|
||||
# prediction_schema_uri: str = None,
|
||||
# explanation_metadata: "google.cloud.aiplatform_v1.types.explanation_metadata.ExplanationMetadata" = None,
|
||||
# explanation_parameters: "google.cloud.aiplatform_v1.types.explanation.ExplanationParameters" = None,
|
||||
|
||||
project = None,
|
||||
location = None,
|
||||
labels = None,
|
||||
# encryption_spec_key_name: str = None,
|
||||
staging_bucket = None,
|
||||
):
|
||||
import json
|
||||
import os
|
||||
from google.cloud import aiplatform
|
||||
|
||||
if not location:
|
||||
location = os.environ.get("CLOUD_ML_REGION")
|
||||
|
||||
if not labels:
|
||||
labels = {}
|
||||
labels["component-source"] = "github-com-ark-kun-pipeline-components"
|
||||
|
||||
container_image_tag = torchserve_version + "-" + ("gpu" if use_gpu else "cpu")
|
||||
container_image_uri = f"pytorch/torchserve:{container_image_tag}"
|
||||
|
||||
# Vertex Endpoints refuse to support non-Google container registries.
|
||||
# We have to work around this to reduce user frustration
|
||||
# TODO: Remove this code when Vertex Endpoints service starts supporting other container registries.
|
||||
def copy_container_image(
|
||||
src_container_image_uri,
|
||||
dst_container_image_uri,
|
||||
project_id,
|
||||
):
|
||||
from google.cloud.devtools import cloudbuild
|
||||
from google import protobuf
|
||||
build_client = cloudbuild.CloudBuildClient()
|
||||
build_config = cloudbuild.Build(
|
||||
images=[dst_container_image_uri],
|
||||
steps=[
|
||||
cloudbuild.BuildStep(
|
||||
name="gcr.io/cloud-builders/docker",
|
||||
entrypoint="bash",
|
||||
args=[
|
||||
"-exc",
|
||||
'docker pull --quiet "$0" && docker tag "$0" "$1"',
|
||||
src_container_image_uri,
|
||||
dst_container_image_uri,
|
||||
],
|
||||
),
|
||||
],
|
||||
timeout=protobuf.duration_pb2.Duration(
|
||||
seconds=1800,
|
||||
),
|
||||
)
|
||||
build_operation = build_client.create_build(
|
||||
project_id=project_id,
|
||||
build=build_config,
|
||||
)
|
||||
try:
|
||||
result = build_operation.result()
|
||||
except:
|
||||
print(f"Logs are available at [{build_operation.metadata.build.log_url}].")
|
||||
raise
|
||||
return result
|
||||
|
||||
project_id = aiplatform.initializer.global_config.project
|
||||
mirrored_container_uri = f"gcr.io/{project_id}/container_mirror/{container_image_uri}"
|
||||
# FIX: Only mirror when image does not exist
|
||||
# docker does is unable to get the registry data from inside container (it cannot connecto to docker socket):
|
||||
# docker.errors.DockerException: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))
|
||||
# import docker
|
||||
# try:
|
||||
# docker_client = docker.from_env()
|
||||
# docker_client.images.get_registry_data(mirrored_container_uri)
|
||||
# except docker.errors.NotFound:
|
||||
if True:
|
||||
print(f"Mirroring {container_image_uri} to {mirrored_container_uri}")
|
||||
copy_container_image(
|
||||
src_container_image_uri=container_image_uri,
|
||||
dst_container_image_uri=mirrored_container_uri,
|
||||
project_id=project_id,
|
||||
)
|
||||
container_image_uri = mirrored_container_uri
|
||||
# End of container image mirroring code
|
||||
|
||||
model_archive_file_name = os.path.basename(model_archive_path)
|
||||
model_archive_dir = os.path.dirname(model_archive_path)
|
||||
|
||||
model = aiplatform.Model.upload(
|
||||
# FIX: Use public image or mirror the official image
|
||||
#serving_container_image_uri="gcr.io/avolkov-31337/mirror/pytorch/torchserve",
|
||||
serving_container_image_uri=container_image_uri,
|
||||
artifact_uri=model_archive_dir,
|
||||
serving_container_command=[
|
||||
"bash",
|
||||
"-exc",
|
||||
'''
|
||||
model_archive_uri="$0"
|
||||
#model_archive_local_path=$(mktemp --suffix ".mar")
|
||||
# For some reason the model must already be inside the model-store directory.
|
||||
model_archive_local_path=./model-store/model.mar
|
||||
|
||||
# Downloading the model archive from GCS
|
||||
# TODO: Fix gsutil bugs (requires project ID, has auth issues) and use gsutil instead.
|
||||
# gsutil cp "$model_archive_uri" "$model_archive_local_path"
|
||||
pip install google-cloud-storage
|
||||
python -c '
|
||||
import sys
|
||||
from google.cloud import storage
|
||||
|
||||
model_archive_uri = sys.argv[1]
|
||||
model_archive_local_path = sys.argv[2]
|
||||
|
||||
storage_client = storage.Client()
|
||||
blob = storage.Blob.from_string(uri=model_archive_uri, client=storage_client)
|
||||
blob.download_to_filename(filename=model_archive_local_path)
|
||||
' "$model_archive_uri" "$model_archive_local_path"
|
||||
|
||||
#Note: config.properties is owned by root. Our user is not root.
|
||||
echo "
|
||||
service_envelope=json
|
||||
# Needed for external access
|
||||
inference_address=http://0.0.0.0:8080
|
||||
management_address=http://0.0.0.0:8081
|
||||
" > config2.properties
|
||||
torchserve --start --foreground --no-config-snapshots --models main-model="$model_archive_local_path" --model-store ./model-store/ --ts-config config2.properties
|
||||
''',
|
||||
"$(AIP_STORAGE_URI)/" + model_archive_file_name,
|
||||
],
|
||||
serving_container_predict_route="/predictions/main-model",
|
||||
#serving_container_predict_route="/v1/models/main-model:predict",
|
||||
serving_container_health_route="/ping",
|
||||
serving_container_ports=[8080],
|
||||
|
||||
display_name=display_name,
|
||||
description=description,
|
||||
|
||||
# instance_schema_uri=instance_schema_uri,
|
||||
# parameters_schema_uri=parameters_schema_uri,
|
||||
# prediction_schema_uri=prediction_schema_uri,
|
||||
# explanation_metadata=explanation_metadata,
|
||||
# explanation_parameters=explanation_parameters,
|
||||
|
||||
project=project,
|
||||
location=location,
|
||||
labels=labels,
|
||||
# encryption_spec_key_name=encryption_spec_key_name,
|
||||
staging_bucket=staging_bucket,
|
||||
)
|
||||
model_json = json.dumps(model.to_dict(), indent=2)
|
||||
print(model_json)
|
||||
return (model.resource_name, model_json)
|
||||
|
||||
def _deserialize_bool(s) -> bool:
|
||||
from distutils.util import strtobool
|
||||
return strtobool(s) == 1
|
||||
|
||||
def _serialize_json(obj) -> str:
|
||||
if isinstance(obj, str):
|
||||
return obj
|
||||
import json
|
||||
def default_serializer(obj):
|
||||
if hasattr(obj, 'to_struct'):
|
||||
return obj.to_struct()
|
||||
else:
|
||||
raise TypeError("Object of type '%s' is not JSON serializable and does not have .to_struct() method." % obj.__class__.__name__)
|
||||
return json.dumps(obj, default=default_serializer, sort_keys=True)
|
||||
|
||||
def _serialize_str(str_value: str) -> str:
|
||||
if not isinstance(str_value, str):
|
||||
raise TypeError('Value "{}" has type "{}" instead of str.'.format(str(str_value), str(type(str_value))))
|
||||
return str_value
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Upload PyTorch model archive to Google Cloud Vertex AI', description='')
|
||||
_parser.add_argument("--model-archive", dest="model_archive_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--torchserve-version", dest="torchserve_version", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--use-gpu", dest="use_gpu", type=_deserialize_bool, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--display-name", dest="display_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--description", dest="description", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--project", dest="project", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--location", dest="location", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--labels", dest="labels", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--staging-bucket", dest="staging_bucket", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=2)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
_output_files = _parsed_args.pop("_output_paths", [])
|
||||
|
||||
_outputs = upload_PyTorch_model_archive_to_Google_Cloud_Vertex_AI(**_parsed_args)
|
||||
|
||||
_output_serializers = [
|
||||
_serialize_str,
|
||||
_serialize_json,
|
||||
|
||||
]
|
||||
|
||||
import os
|
||||
for idx, output_file in enumerate(_output_files):
|
||||
try:
|
||||
os.makedirs(os.path.dirname(output_file))
|
||||
except OSError:
|
||||
pass
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(_output_serializers[idx](_outputs[idx]))
|
||||
args:
|
||||
- --model-archive
|
||||
- {inputPath: model_archive}
|
||||
- if:
|
||||
cond: {isPresent: torchserve_version}
|
||||
then:
|
||||
- --torchserve-version
|
||||
- {inputValue: torchserve_version}
|
||||
- if:
|
||||
cond: {isPresent: use_gpu}
|
||||
then:
|
||||
- --use-gpu
|
||||
- {inputValue: use_gpu}
|
||||
- if:
|
||||
cond: {isPresent: display_name}
|
||||
then:
|
||||
- --display-name
|
||||
- {inputValue: display_name}
|
||||
- if:
|
||||
cond: {isPresent: description}
|
||||
then:
|
||||
- --description
|
||||
- {inputValue: description}
|
||||
- if:
|
||||
cond: {isPresent: project}
|
||||
then:
|
||||
- --project
|
||||
- {inputValue: project}
|
||||
- if:
|
||||
cond: {isPresent: location}
|
||||
then:
|
||||
- --location
|
||||
- {inputValue: location}
|
||||
- if:
|
||||
cond: {isPresent: labels}
|
||||
then:
|
||||
- --labels
|
||||
- {inputValue: labels}
|
||||
- if:
|
||||
cond: {isPresent: staging_bucket}
|
||||
then:
|
||||
- --staging-bucket
|
||||
- {inputValue: staging_bucket}
|
||||
- '----output-paths'
|
||||
- {outputPath: model_name}
|
||||
- {outputPath: model_dict}
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
name: Upload Scikit learn pickle model to Google Cloud Vertex AI
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/KFPv2_hell/components/google-cloud/Vertex_AI/Models/Upload_Scikit-learn_pickle_model/workaround_for_buggy_KFPv2_compiler/component.yaml'}
|
||||
inputs:
|
||||
- {name: model, type: ScikitLearnPickleModel}
|
||||
- {name: sklearn_version, type: String, optional: true}
|
||||
- {name: display_name, type: String, optional: true}
|
||||
- {name: description, type: String, optional: true}
|
||||
- {name: project, type: String, optional: true}
|
||||
- {name: location, type: String, optional: true}
|
||||
- {name: labels, type: JsonObject, optional: true}
|
||||
- {name: staging_bucket, type: String, optional: true}
|
||||
outputs:
|
||||
- {name: model_name, type: String}
|
||||
- {name: model_dict, type: JsonObject}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'google-cloud-aiplatform==1.16.0' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3
|
||||
-m pip install --quiet --no-warn-script-location 'google-cloud-aiplatform==1.16.0'
|
||||
--user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def upload_Scikit_learn_pickle_model_to_Google_Cloud_Vertex_AI(
|
||||
model_path,
|
||||
sklearn_version = None,
|
||||
|
||||
display_name = None,
|
||||
description = None,
|
||||
|
||||
# Uncomment when anyone requests these:
|
||||
# instance_schema_uri: str = None,
|
||||
# parameters_schema_uri: str = None,
|
||||
# prediction_schema_uri: str = None,
|
||||
# explanation_metadata: "google.cloud.aiplatform_v1.types.explanation_metadata.ExplanationMetadata" = None,
|
||||
# explanation_parameters: "google.cloud.aiplatform_v1.types.explanation.ExplanationParameters" = None,
|
||||
|
||||
project = None,
|
||||
location = None,
|
||||
labels = None,
|
||||
# encryption_spec_key_name: str = None,
|
||||
staging_bucket = None,
|
||||
):
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from google.cloud import aiplatform
|
||||
|
||||
if not location:
|
||||
location = os.environ.get("CLOUD_ML_REGION")
|
||||
|
||||
if not labels:
|
||||
labels = {}
|
||||
labels["component-source"] = "github-com-ark-kun-pipeline-components"
|
||||
|
||||
# The serving container decides the model type based on the model file extension.
|
||||
# So we need to rename the mode file (e.g. /tmp/inputs/model/data) to *.pkl
|
||||
_, renamed_model_path = tempfile.mkstemp(suffix=".pkl")
|
||||
shutil.copyfile(src=model_path, dst=renamed_model_path)
|
||||
|
||||
model = aiplatform.Model.upload_scikit_learn_model_file(
|
||||
model_file_path=renamed_model_path,
|
||||
sklearn_version=sklearn_version,
|
||||
|
||||
display_name=display_name,
|
||||
description=description,
|
||||
|
||||
# instance_schema_uri=instance_schema_uri,
|
||||
# parameters_schema_uri=parameters_schema_uri,
|
||||
# prediction_schema_uri=prediction_schema_uri,
|
||||
# explanation_metadata=explanation_metadata,
|
||||
# explanation_parameters=explanation_parameters,
|
||||
|
||||
project=project,
|
||||
location=location,
|
||||
labels=labels,
|
||||
# encryption_spec_key_name=encryption_spec_key_name,
|
||||
staging_bucket=staging_bucket,
|
||||
)
|
||||
model_json = json.dumps(model.to_dict(), indent=2)
|
||||
print(model_json)
|
||||
return (model.resource_name, model_json)
|
||||
|
||||
def _serialize_json(obj) -> str:
|
||||
if isinstance(obj, str):
|
||||
return obj
|
||||
import json
|
||||
def default_serializer(obj):
|
||||
if hasattr(obj, 'to_struct'):
|
||||
return obj.to_struct()
|
||||
else:
|
||||
raise TypeError("Object of type '%s' is not JSON serializable and does not have .to_struct() method." % obj.__class__.__name__)
|
||||
return json.dumps(obj, default=default_serializer, sort_keys=True)
|
||||
|
||||
def _serialize_str(str_value: str) -> str:
|
||||
if not isinstance(str_value, str):
|
||||
raise TypeError('Value "{}" has type "{}" instead of str.'.format(str(str_value), str(type(str_value))))
|
||||
return str_value
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Upload Scikit learn pickle model to Google Cloud Vertex AI', description='')
|
||||
_parser.add_argument("--model", dest="model_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--sklearn-version", dest="sklearn_version", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--display-name", dest="display_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--description", dest="description", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--project", dest="project", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--location", dest="location", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--labels", dest="labels", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--staging-bucket", dest="staging_bucket", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=2)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
_output_files = _parsed_args.pop("_output_paths", [])
|
||||
|
||||
_outputs = upload_Scikit_learn_pickle_model_to_Google_Cloud_Vertex_AI(**_parsed_args)
|
||||
|
||||
_output_serializers = [
|
||||
_serialize_str,
|
||||
_serialize_json,
|
||||
|
||||
]
|
||||
|
||||
import os
|
||||
for idx, output_file in enumerate(_output_files):
|
||||
try:
|
||||
os.makedirs(os.path.dirname(output_file))
|
||||
except OSError:
|
||||
pass
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(_output_serializers[idx](_outputs[idx]))
|
||||
args:
|
||||
- --model
|
||||
- {inputPath: model}
|
||||
- if:
|
||||
cond: {isPresent: sklearn_version}
|
||||
then:
|
||||
- --sklearn-version
|
||||
- {inputValue: sklearn_version}
|
||||
- if:
|
||||
cond: {isPresent: display_name}
|
||||
then:
|
||||
- --display-name
|
||||
- {inputValue: display_name}
|
||||
- if:
|
||||
cond: {isPresent: description}
|
||||
then:
|
||||
- --description
|
||||
- {inputValue: description}
|
||||
- if:
|
||||
cond: {isPresent: project}
|
||||
then:
|
||||
- --project
|
||||
- {inputValue: project}
|
||||
- if:
|
||||
cond: {isPresent: location}
|
||||
then:
|
||||
- --location
|
||||
- {inputValue: location}
|
||||
- if:
|
||||
cond: {isPresent: labels}
|
||||
then:
|
||||
- --labels
|
||||
- {inputValue: labels}
|
||||
- if:
|
||||
cond: {isPresent: staging_bucket}
|
||||
then:
|
||||
- --staging-bucket
|
||||
- {inputValue: staging_bucket}
|
||||
- '----output-paths'
|
||||
- {outputPath: model_name}
|
||||
- {outputPath: model_dict}
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
name: Upload Tensorflow model to Google Cloud Vertex AI
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/KFPv2_hell/components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/workaround_for_buggy_KFPv2_compiler/component.yaml'}
|
||||
inputs:
|
||||
- {name: model, type: TensorflowSavedModel}
|
||||
- {name: tensorflow_version, type: String, optional: true}
|
||||
- name: use_gpu
|
||||
type: Boolean
|
||||
default: "False"
|
||||
optional: true
|
||||
- {name: display_name, type: String, optional: true}
|
||||
- {name: description, type: String, optional: true}
|
||||
- {name: project, type: String, optional: true}
|
||||
- {name: location, type: String, optional: true}
|
||||
- {name: labels, type: JsonObject, optional: true}
|
||||
- {name: staging_bucket, type: String, optional: true}
|
||||
outputs:
|
||||
- {name: model_name, type: String}
|
||||
- {name: model_dict, type: JsonObject}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'google-cloud-aiplatform==1.16.0' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3
|
||||
-m pip install --quiet --no-warn-script-location 'google-cloud-aiplatform==1.16.0'
|
||||
--user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def upload_Tensorflow_model_to_Google_Cloud_Vertex_AI(
|
||||
model_path,
|
||||
tensorflow_version = None,
|
||||
use_gpu = False,
|
||||
|
||||
display_name = None,
|
||||
description = None,
|
||||
|
||||
# Uncomment when anyone requests these:
|
||||
# instance_schema_uri: str = None,
|
||||
# parameters_schema_uri: str = None,
|
||||
# prediction_schema_uri: str = None,
|
||||
# explanation_metadata: "google.cloud.aiplatform_v1.types.explanation_metadata.ExplanationMetadata" = None,
|
||||
# explanation_parameters: "google.cloud.aiplatform_v1.types.explanation.ExplanationParameters" = None,
|
||||
|
||||
project = None,
|
||||
location = None,
|
||||
labels = None,
|
||||
# encryption_spec_key_name: str = None,
|
||||
staging_bucket = None,
|
||||
):
|
||||
import json
|
||||
import os
|
||||
from google.cloud import aiplatform
|
||||
|
||||
if not location:
|
||||
location = os.environ.get("CLOUD_ML_REGION")
|
||||
|
||||
if not labels:
|
||||
labels = {}
|
||||
labels["component-source"] = "github-com-ark-kun-pipeline-components"
|
||||
|
||||
model = aiplatform.Model.upload_tensorflow_saved_model(
|
||||
saved_model_dir=model_path,
|
||||
tensorflow_version=tensorflow_version,
|
||||
use_gpu=use_gpu,
|
||||
|
||||
display_name=display_name,
|
||||
description=description,
|
||||
|
||||
# instance_schema_uri=instance_schema_uri,
|
||||
# parameters_schema_uri=parameters_schema_uri,
|
||||
# prediction_schema_uri=prediction_schema_uri,
|
||||
# explanation_metadata=explanation_metadata,
|
||||
# explanation_parameters=explanation_parameters,
|
||||
|
||||
project=project,
|
||||
location=location,
|
||||
labels=labels,
|
||||
# encryption_spec_key_name=encryption_spec_key_name,
|
||||
staging_bucket=staging_bucket,
|
||||
)
|
||||
model_json = json.dumps(model.to_dict(), indent=2)
|
||||
print(model_json)
|
||||
return (model.resource_name, model_json)
|
||||
|
||||
def _deserialize_bool(s) -> bool:
|
||||
from distutils.util import strtobool
|
||||
return strtobool(s) == 1
|
||||
|
||||
def _serialize_json(obj) -> str:
|
||||
if isinstance(obj, str):
|
||||
return obj
|
||||
import json
|
||||
def default_serializer(obj):
|
||||
if hasattr(obj, 'to_struct'):
|
||||
return obj.to_struct()
|
||||
else:
|
||||
raise TypeError("Object of type '%s' is not JSON serializable and does not have .to_struct() method." % obj.__class__.__name__)
|
||||
return json.dumps(obj, default=default_serializer, sort_keys=True)
|
||||
|
||||
def _serialize_str(str_value: str) -> str:
|
||||
if not isinstance(str_value, str):
|
||||
raise TypeError('Value "{}" has type "{}" instead of str.'.format(str(str_value), str(type(str_value))))
|
||||
return str_value
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Upload Tensorflow model to Google Cloud Vertex AI', description='')
|
||||
_parser.add_argument("--model", dest="model_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--tensorflow-version", dest="tensorflow_version", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--use-gpu", dest="use_gpu", type=_deserialize_bool, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--display-name", dest="display_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--description", dest="description", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--project", dest="project", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--location", dest="location", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--labels", dest="labels", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--staging-bucket", dest="staging_bucket", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=2)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
_output_files = _parsed_args.pop("_output_paths", [])
|
||||
|
||||
_outputs = upload_Tensorflow_model_to_Google_Cloud_Vertex_AI(**_parsed_args)
|
||||
|
||||
_output_serializers = [
|
||||
_serialize_str,
|
||||
_serialize_json,
|
||||
|
||||
]
|
||||
|
||||
import os
|
||||
for idx, output_file in enumerate(_output_files):
|
||||
try:
|
||||
os.makedirs(os.path.dirname(output_file))
|
||||
except OSError:
|
||||
pass
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(_output_serializers[idx](_outputs[idx]))
|
||||
args:
|
||||
- --model
|
||||
- {inputPath: model}
|
||||
- if:
|
||||
cond: {isPresent: tensorflow_version}
|
||||
then:
|
||||
- --tensorflow-version
|
||||
- {inputValue: tensorflow_version}
|
||||
- if:
|
||||
cond: {isPresent: use_gpu}
|
||||
then:
|
||||
- --use-gpu
|
||||
- {inputValue: use_gpu}
|
||||
- if:
|
||||
cond: {isPresent: display_name}
|
||||
then:
|
||||
- --display-name
|
||||
- {inputValue: display_name}
|
||||
- if:
|
||||
cond: {isPresent: description}
|
||||
then:
|
||||
- --description
|
||||
- {inputValue: description}
|
||||
- if:
|
||||
cond: {isPresent: project}
|
||||
then:
|
||||
- --project
|
||||
- {inputValue: project}
|
||||
- if:
|
||||
cond: {isPresent: location}
|
||||
then:
|
||||
- --location
|
||||
- {inputValue: location}
|
||||
- if:
|
||||
cond: {isPresent: labels}
|
||||
then:
|
||||
- --labels
|
||||
- {inputValue: labels}
|
||||
- if:
|
||||
cond: {isPresent: staging_bucket}
|
||||
then:
|
||||
- --staging-bucket
|
||||
- {inputValue: staging_bucket}
|
||||
- '----output-paths'
|
||||
- {outputPath: model_name}
|
||||
- {outputPath: model_dict}
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
name: Upload XGBoost model to Google Cloud Vertex AI
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/google-cloud/Vertex_AI/Models/Upload_XGBoost_model/workaround_for_buggy_KFPv2_compiler/component.yaml'}
|
||||
inputs:
|
||||
- {name: model, type: XGBoostModel}
|
||||
- {name: xgboost_version, type: String, optional: true}
|
||||
- {name: display_name, type: String, optional: true}
|
||||
- {name: description, type: String, optional: true}
|
||||
- {name: project, type: String, optional: true}
|
||||
- {name: location, type: String, optional: true}
|
||||
- {name: labels, type: JsonObject, optional: true}
|
||||
- {name: staging_bucket, type: String, optional: true}
|
||||
outputs:
|
||||
- {name: model_name, type: String}
|
||||
- {name: model_dict, type: JsonObject}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'google-cloud-aiplatform==1.16.0' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3
|
||||
-m pip install --quiet --no-warn-script-location 'google-cloud-aiplatform==1.16.0'
|
||||
--user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def upload_XGBoost_model_to_Google_Cloud_Vertex_AI(
|
||||
model_path,
|
||||
xgboost_version = None,
|
||||
|
||||
display_name = None,
|
||||
description = None,
|
||||
|
||||
# Uncomment when anyone requests these:
|
||||
# instance_schema_uri: str = None,
|
||||
# parameters_schema_uri: str = None,
|
||||
# prediction_schema_uri: str = None,
|
||||
# explanation_metadata: "google.cloud.aiplatform_v1.types.explanation_metadata.ExplanationMetadata" = None,
|
||||
# explanation_parameters: "google.cloud.aiplatform_v1.types.explanation.ExplanationParameters" = None,
|
||||
|
||||
project = None,
|
||||
location = None,
|
||||
labels = None,
|
||||
# encryption_spec_key_name: str = None,
|
||||
staging_bucket = None,
|
||||
):
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from google.cloud import aiplatform
|
||||
|
||||
if not location:
|
||||
location = os.environ.get("CLOUD_ML_REGION")
|
||||
|
||||
if not labels:
|
||||
labels = {}
|
||||
labels["component-source"] = "github-com-ark-kun-pipeline-components"
|
||||
|
||||
# The serving container decides the model type based on the model file extension.
|
||||
# So we need to rename the mode file (e.g. /tmp/inputs/model/data) to *.pkl
|
||||
_, renamed_model_path = tempfile.mkstemp(suffix=".pkl")
|
||||
shutil.copyfile(src=model_path, dst=renamed_model_path)
|
||||
|
||||
model = aiplatform.Model.upload_xgboost_model_file(
|
||||
model_file_path=renamed_model_path,
|
||||
xgboost_version=xgboost_version,
|
||||
|
||||
display_name=display_name,
|
||||
description=description,
|
||||
|
||||
# instance_schema_uri=instance_schema_uri,
|
||||
# parameters_schema_uri=parameters_schema_uri,
|
||||
# prediction_schema_uri=prediction_schema_uri,
|
||||
# explanation_metadata=explanation_metadata,
|
||||
# explanation_parameters=explanation_parameters,
|
||||
|
||||
project=project,
|
||||
location=location,
|
||||
labels=labels,
|
||||
# encryption_spec_key_name=encryption_spec_key_name,
|
||||
staging_bucket=staging_bucket,
|
||||
)
|
||||
model_json = json.dumps(model.to_dict(), indent=2)
|
||||
print(model_json)
|
||||
return (model.resource_name, model_json)
|
||||
|
||||
def _serialize_json(obj) -> str:
|
||||
if isinstance(obj, str):
|
||||
return obj
|
||||
import json
|
||||
def default_serializer(obj):
|
||||
if hasattr(obj, 'to_struct'):
|
||||
return obj.to_struct()
|
||||
else:
|
||||
raise TypeError("Object of type '%s' is not JSON serializable and does not have .to_struct() method." % obj.__class__.__name__)
|
||||
return json.dumps(obj, default=default_serializer, sort_keys=True)
|
||||
|
||||
def _serialize_str(str_value: str) -> str:
|
||||
if not isinstance(str_value, str):
|
||||
raise TypeError('Value "{}" has type "{}" instead of str.'.format(str(str_value), str(type(str_value))))
|
||||
return str_value
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Upload XGBoost model to Google Cloud Vertex AI', description='')
|
||||
_parser.add_argument("--model", dest="model_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--xgboost-version", dest="xgboost_version", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--display-name", dest="display_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--description", dest="description", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--project", dest="project", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--location", dest="location", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--labels", dest="labels", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--staging-bucket", dest="staging_bucket", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("----output-paths", dest="_output_paths", type=str, nargs=2)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
_output_files = _parsed_args.pop("_output_paths", [])
|
||||
|
||||
_outputs = upload_XGBoost_model_to_Google_Cloud_Vertex_AI(**_parsed_args)
|
||||
|
||||
_output_serializers = [
|
||||
_serialize_str,
|
||||
_serialize_json,
|
||||
|
||||
]
|
||||
|
||||
import os
|
||||
for idx, output_file in enumerate(_output_files):
|
||||
try:
|
||||
os.makedirs(os.path.dirname(output_file))
|
||||
except OSError:
|
||||
pass
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(_output_serializers[idx](_outputs[idx]))
|
||||
args:
|
||||
- --model
|
||||
- {inputPath: model}
|
||||
- if:
|
||||
cond: {isPresent: xgboost_version}
|
||||
then:
|
||||
- --xgboost-version
|
||||
- {inputValue: xgboost_version}
|
||||
- if:
|
||||
cond: {isPresent: display_name}
|
||||
then:
|
||||
- --display-name
|
||||
- {inputValue: display_name}
|
||||
- if:
|
||||
cond: {isPresent: description}
|
||||
then:
|
||||
- --description
|
||||
- {inputValue: description}
|
||||
- if:
|
||||
cond: {isPresent: project}
|
||||
then:
|
||||
- --project
|
||||
- {inputValue: project}
|
||||
- if:
|
||||
cond: {isPresent: location}
|
||||
then:
|
||||
- --location
|
||||
- {inputValue: location}
|
||||
- if:
|
||||
cond: {isPresent: labels}
|
||||
then:
|
||||
- --labels
|
||||
- {inputValue: labels}
|
||||
- if:
|
||||
cond: {isPresent: staging_bucket}
|
||||
then:
|
||||
- --staging-bucket
|
||||
- {inputValue: staging_bucket}
|
||||
- '----output-paths'
|
||||
- {outputPath: model_name}
|
||||
- {outputPath: model_dict}
|
||||
@@ -0,0 +1,35 @@
|
||||
name: Download from GCS
|
||||
inputs:
|
||||
- {name: GCS path, type: String}
|
||||
outputs:
|
||||
- {name: Data}
|
||||
metadata:
|
||||
annotations:
|
||||
author: Alexey Volkov <alexey.volkov@ark-kun.com>
|
||||
canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/google-cloud/storage/download/workaround_for_buggy_KFPv2_compiler/component.yaml'
|
||||
implementation:
|
||||
container:
|
||||
image: google/cloud-sdk
|
||||
command:
|
||||
- bash # Pattern comparison only works in Bash
|
||||
- -ex
|
||||
- -c
|
||||
- |
|
||||
if [ -n "${GOOGLE_APPLICATION_CREDENTIALS}" ]; then
|
||||
gcloud auth activate-service-account --key-file="${GOOGLE_APPLICATION_CREDENTIALS}"
|
||||
fi
|
||||
|
||||
uri="$0"
|
||||
output_path="$1"
|
||||
|
||||
# Checking whether the URI points to a single blob, a directory or a URI pattern
|
||||
# URI points to a blob when that URI does not end with slash and listing that URI only yields the same URI
|
||||
if [[ "$uri" != */ ]] && (gsutil ls "$uri" | grep --fixed-strings --line-regexp "$uri"); then
|
||||
mkdir -p "$(dirname "$output_path")"
|
||||
gsutil -m cp -r "$uri" "$output_path"
|
||||
else
|
||||
mkdir -p "$output_path" # When source path is a directory, gsutil requires the destination to also be a directory
|
||||
gsutil -m rsync -r "$uri" "$output_path" # gsutil cp has different path handling than Linux cp. It always puts the source directory (name) inside the destination directory. gsutil rsync does not have that problem.
|
||||
fi
|
||||
- inputValue: GCS path
|
||||
- outputPath: Data
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
name: Load image classification model from tfhub
|
||||
description: |
|
||||
Loads specified model from TFHub, creates layer to receive additional (3 channel) imagery data.
|
||||
Args:
|
||||
class_names (Sequence[str]):
|
||||
Sequence of strings of categories for classification corresponding to input data.
|
||||
loaded_model_path (str):
|
||||
Output path for the loaded model.
|
||||
image_size_path (str):
|
||||
Output path for the model expected image size.
|
||||
model_name (Optional[str]):
|
||||
Name of the pre-trained image classification model to load from TFHub.
|
||||
Eligible model_name:
|
||||
- efficientnetv2-s
|
||||
- efficientnetv2-m
|
||||
- efficientnetv2-l
|
||||
- efficientnetv2-s-21k
|
||||
- efficientnetv2-m-21k
|
||||
- efficientnetv2-l-21k
|
||||
- efficientnetv2-xl-21k
|
||||
- efficientnetv2-b0-21k
|
||||
- efficientnetv2-b1-21k
|
||||
- efficientnetv2-b2-21k
|
||||
- efficientnetv2-b3-21k
|
||||
- efficientnetv2-s-21k-ft1k
|
||||
- efficientnetv2-m-21k-ft1k
|
||||
- efficientnetv2-l-21k-ft1k
|
||||
- efficientnetv2-xl-21k-ft1k
|
||||
- efficientnetv2-b0-21k-ft1k
|
||||
- efficientnetv2-b1-21k-ft1k
|
||||
- efficientnetv2-b2-21k-ft1k
|
||||
- efficientnetv2-b3-21k-ft1k
|
||||
- efficientnetv2-b0
|
||||
- efficientnetv2-b1
|
||||
- efficientnetv2-b2
|
||||
- efficientnetv2-b3
|
||||
- efficientnet_b0
|
||||
- efficientnet_b1
|
||||
- efficientnet_b2
|
||||
- efficientnet_b3
|
||||
- efficientnet_b4
|
||||
- efficientnet_b5
|
||||
- efficientnet_b6
|
||||
- efficientnet_b7
|
||||
- bit_s-r50x1
|
||||
- inception_v3
|
||||
- inception_resnet_v2
|
||||
- resnet_v1_50
|
||||
- resnet_v1_101
|
||||
- resnet_v1_152
|
||||
- resnet_v2_50
|
||||
- resnet_v2_101
|
||||
- resnet_v2_152
|
||||
- nasnet_large
|
||||
- nasnet_mobile
|
||||
- pnasnet_large
|
||||
- mobilenet_v2_100_224
|
||||
- mobilenet_v2_130_224
|
||||
- mobilenet_v2_140_224
|
||||
- mobilenet_v3_small_100_224
|
||||
- mobilenet_v3_small_075_224
|
||||
- mobilenet_v3_large_100_224
|
||||
- mobilenet_v3_large_075_224
|
||||
dropout_rate (Optional[float]):
|
||||
Fraction of input units to drop in the last layer. Value should be between 0.0 and 1.0.
|
||||
trainable (Optional[bool]):
|
||||
If true fine tuning will be performed on entire Hub model. If false only additional
|
||||
layers will be trained.
|
||||
l2_regularization_penalty (Optional[float]):
|
||||
l2 regularization penalty.
|
||||
inputs:
|
||||
- {name: class_names, type: 'typing.List[str]', description: List of class names corresponding
|
||||
to the input image data}
|
||||
- {name: model_name, type: String, description: Name of the TFHub model to load, default: efficientnetv2-xl-21k,
|
||||
optional: true}
|
||||
- {name: dropout_rate, type: Float, description: Dropout rate, default: '0.2', optional: true}
|
||||
- name: trainable
|
||||
type: Boolean
|
||||
description: True if fine tuning should be performed
|
||||
default: "True"
|
||||
optional: true
|
||||
- {name: l2_regularization_penalty, type: Float, description: Regularization penalty,
|
||||
default: '0.0001', optional: true}
|
||||
outputs:
|
||||
- {name: loaded_model_path, type: TensorflowSavedModel, description: Output path for
|
||||
the loaded model}
|
||||
- {name: image_size_path, type: HeightWidth}
|
||||
implementation:
|
||||
container:
|
||||
image: us-docker.pkg.dev/vertex-ai/ready-to-go-image-classification/image-components:v0.1
|
||||
# command is a list of strings (command-line arguments).
|
||||
# The YAML language has two syntaxes for lists and you can use either of them.
|
||||
# Here we use the "flow syntax" - comma-separated strings inside square brackets.
|
||||
command: [
|
||||
python3,
|
||||
# Path of the program inside the container
|
||||
/pipelines/component/src/loading_component.py,
|
||||
--loaded-model-path,
|
||||
{outputPath: loaded_model_path},
|
||||
--class-names,
|
||||
{inputValue: class_names},
|
||||
--model-name,
|
||||
{inputValue: model_name},
|
||||
--dropout-rate,
|
||||
{inputValue: dropout_rate},
|
||||
--trainable,
|
||||
{inputValue: trainable},
|
||||
--l2-regularization-penalty,
|
||||
{inputValue: l2_regularization_penalty},
|
||||
--image-size-path,
|
||||
{outputPath: image_size_path},
|
||||
]
|
||||
@@ -0,0 +1,62 @@
|
||||
# python3 -m pip install "kfp<2.0.0" "google-cloud-aiplatform>=1.16.0" --upgrade --quiet
|
||||
from kfp import components
|
||||
from kfp.v2 import dsl
|
||||
|
||||
# %% Loading components
|
||||
upload_Tensorflow_model_to_Google_Cloud_Vertex_AI_op = components.load_component_from_url('https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/component.yaml')
|
||||
deploy_model_to_endpoint_op = components.load_component_from_url('https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/399405402d95f4a011e2d2e967c96f8508ba5688/community-content/pipeline_components/google-cloud/Vertex_AI/Models/Deploy_to_endpoint/component.yaml')
|
||||
transcode_imagedataset_tfrecord_from_csv_op = components.load_component_from_url('https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/community-content/pipeline_components/image_ml_model_training/transcode_tfrecord_image_dataset_from_csv/component.yaml')
|
||||
load_image_classification_model_from_tfhub_op = components.load_component_from_url('https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/b5b65198a6c2ffe8c0fa2aa70127e3325752df68/community-content/pipeline_components/image_ml_model_training/load_image_classification_model/component.yaml')
|
||||
preprocess_image_data_op = components.load_component_from_url('https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/community-content/pipeline_components/image_ml_model_training/preprocess_image_data/component.yaml')
|
||||
train_tensorflow_image_classification_model_op = components.load_component_from_url('https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/community-content/pipeline_components/image_ml_model_training/train_image_classification_model/component.yaml')
|
||||
|
||||
|
||||
# %% Pipeline definition
|
||||
def image_classification_pipeline():
|
||||
class_names = ['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']
|
||||
csv_image_data_path = 'gs://cloud-samples-data/ai-platform/flowers/flowers.csv'
|
||||
deploy_model = False
|
||||
|
||||
image_data = dsl.importer(
|
||||
artifact_uri=csv_image_data_path, artifact_class=dsl.Dataset).output
|
||||
|
||||
image_tfrecord_data = transcode_imagedataset_tfrecord_from_csv_op(
|
||||
csv_image_data_path=image_data,
|
||||
class_names=class_names
|
||||
).outputs['tfrecord_image_data_path']
|
||||
|
||||
loaded_model_outputs = load_image_classification_model_from_tfhub_op(
|
||||
class_names=class_names,
|
||||
).outputs
|
||||
|
||||
preprocessed_data = preprocess_image_data_op(
|
||||
image_tfrecord_data,
|
||||
height_width_path=loaded_model_outputs['image_size_path'],
|
||||
).outputs
|
||||
|
||||
trained_model = (train_tensorflow_image_classification_model_op(
|
||||
preprocessed_training_data_path = preprocessed_data['preprocessed_training_data_path'],
|
||||
preprocessed_validation_data_path = preprocessed_data['preprocessed_validation_data_path'],
|
||||
model_path=loaded_model_outputs['loaded_model_path']).
|
||||
set_cpu_limit('96').
|
||||
set_memory_limit('128G').
|
||||
add_node_selector_constraint('cloud.google.com/gke-accelerator', 'NVIDIA_TESLA_A100').
|
||||
set_gpu_limit('8').
|
||||
outputs['trained_model_path'])
|
||||
|
||||
vertex_model_name = upload_Tensorflow_model_to_Google_Cloud_Vertex_AI_op(
|
||||
model=trained_model,
|
||||
).outputs['model_name']
|
||||
|
||||
# Deploying the model might incur additional costs over time
|
||||
if deploy_model:
|
||||
vertex_endpoint_name = deploy_model_to_endpoint_op(
|
||||
model_name=vertex_model_name,
|
||||
).outputs['endpoint_name']
|
||||
|
||||
pipeline_func = image_classification_pipeline
|
||||
|
||||
# %% Pipeline submission
|
||||
if __name__ == '__main__':
|
||||
from google.cloud import aiplatform
|
||||
aiplatform.PipelineJob.from_pipeline_func(pipeline_func=pipeline_func).submit()
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
name: Preprocess image data
|
||||
description: |
|
||||
Preprocess the image data and split between train and validation.
|
||||
Args:
|
||||
input_data_path (str):
|
||||
Input path for the TFRecord image data. Data will be formatted as 'label' (encoded image
|
||||
label), and 'image_raw' (the binary string of the image data).
|
||||
height_width_path (str):
|
||||
Path to square height and width to resize images to. File should contain single float value.
|
||||
Value is dependent on training model.
|
||||
preprocessed_training_data_path (str):
|
||||
Output path for the TFRecord training data. Data will be formatted as 'label' (encoded image
|
||||
label), and 'image_raw' (the binary string of the image data).
|
||||
preprocessed_validation_data_path (str):
|
||||
Output path for the TFRecord validation data. Data will be formatted as 'label' (encoded
|
||||
image label), and 'image_raw' (the binary string of the image data).
|
||||
validation_split (Optional[float]):
|
||||
Fraction of data that will make up validation dataset. Value should be between 0.0 and 1.0.
|
||||
seed (Optional[int]):
|
||||
The global random seed to ensure the system gets a unique random sequence
|
||||
that is deterministic (https://www.tensorflow.org/api_docs/python/tf/random/set_seed).
|
||||
inputs:
|
||||
- {name: input_data_path, type: ImageDatasetTFRecord, description: 'Input path for
|
||||
the TFRecord image data,'}
|
||||
- {name: height_width_path, type: HeightWidth, description: 'Path to square height and width to
|
||||
resize images to,'}
|
||||
- {name: validation_split, type: Float, description: 'Fraction of data that will make
|
||||
up validation dataset,', default: '0.2', optional: true}
|
||||
- {name: seed, type: Integer, description: Random seed, default: '0', optional: true}
|
||||
outputs:
|
||||
- {name: preprocessed_training_data_path, type: ImageDatasetTFRecord, description: 'Output
|
||||
path for the training data,'}
|
||||
- {name: preprocessed_validation_data_path, type: ImageDatasetTFRecord, description: 'Output
|
||||
path for the validation data,'}
|
||||
implementation:
|
||||
container:
|
||||
image: us-docker.pkg.dev/vertex-ai/ready-to-go-image-classification/image-components:v0.1
|
||||
# command is a list of strings (command-line arguments).
|
||||
# The YAML language has two syntaxes for lists and you can use either of them.
|
||||
# Here we use the "flow syntax" - comma-separated strings inside square brackets.
|
||||
command: [
|
||||
python3,
|
||||
# Path of the program inside the container
|
||||
/pipelines/component/src/preprocessing_component.py,
|
||||
--input-data-path,
|
||||
{inputPath: input_data_path},
|
||||
--height-width-path,
|
||||
{inputPath: height_width_path},
|
||||
--validation-split,
|
||||
{inputValue: validation_split},
|
||||
--seed,
|
||||
{inputValue: seed},
|
||||
--preprocessed-training-data-path,
|
||||
{outputPath: preprocessed_training_data_path},
|
||||
--preprocessed-validation-data-path,
|
||||
{outputPath: preprocessed_validation_data_path},
|
||||
]
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
name: Train tensorflow image classification model
|
||||
description: |
|
||||
Creates a trained image classification TensorFlow model.
|
||||
Args:
|
||||
preprocessed_training_data_path (str):
|
||||
Input path to the TFRecord training data. Data will be formatted as 'label' (encoded image
|
||||
label), and 'image_raw' (the binary string of the image data).
|
||||
preprocessed_validation_data_path (str):
|
||||
Input path to the TFRecord validation data. Data will be formatted as 'label' (encoded
|
||||
image label), and 'image_raw' (the binary string of the image data).
|
||||
model_path (str):
|
||||
Input path to the loaded pre-trained model.
|
||||
trained_model_path (str):
|
||||
Output path to save the trained model to.
|
||||
optimizer_name (Optional[str]):
|
||||
Name of the tf.keras optimizer. Available optimizers are listed at
|
||||
https://keras.io/api/optimizers/
|
||||
optimizer_parameters (Optional[Dict[str, str]]):
|
||||
Optimizer parameters.
|
||||
loss_function_name (Optional[str]):
|
||||
Name of the loss function.
|
||||
loss_function_parameters (Optional[Dict[str, str]]):
|
||||
Loss function parameters.
|
||||
number_of_epochs (Optional[int]):
|
||||
Number of training iterations over data.
|
||||
metric_names (Optional[Sequence[str]]):
|
||||
List of tf.keras.metrics to be evaluated by the model during training and testing. Available
|
||||
metrics are listed at https://keras.io/api/metrics/.
|
||||
seed Optional(int):
|
||||
The global random seed to ensure the system gets a unique random sequence
|
||||
that is deterministic (https://www.tensorflow.org/api_docs/python/tf/random/set_seed).
|
||||
inputs:
|
||||
- {name: preprocessed_training_data_path, type: ImageDatasetTFRecord, description: 'Input
|
||||
path for the training data,'}
|
||||
- {name: preprocessed_validation_data_path, type: ImageDatasetTFRecord, description: 'Input
|
||||
path for the validation data,'}
|
||||
- {name: model_path, type: TensorflowSavedModel, description: 'Input path for the
|
||||
model,'}
|
||||
- {name: optimizer_name, type: String, description: 'Name of the optimizer,', default: SGD,
|
||||
optional: true}
|
||||
- {name: optimizer_parameters, type: 'typing.Dict[str, str]', description: 'Optimizer
|
||||
parameters,', default: '{}', optional: true}
|
||||
- {name: loss_function_name, type: String, description: 'Name of the loss function,',
|
||||
default: CategoricalCrossentropy, optional: true}
|
||||
- {name: loss_function_parameters, type: 'typing.Dict[str, str]', description: 'Loss
|
||||
function parameters,', default: '{}', optional: true}
|
||||
- {name: number_of_epochs, type: Integer, description: 'Number of epochs,', default: '10',
|
||||
optional: true}
|
||||
- {name: metric_names, type: 'typing.List[str]', description: 'List of metrics to
|
||||
use,', default: '["accuracy"]', optional: true}
|
||||
- {name: seed, type: Integer, description: 'Random seed,', default: '0', optional: true}
|
||||
- {name: batch_size, type: Integer, description: Batch size, default: '16', optional: true}
|
||||
outputs:
|
||||
- {name: trained_model_path, type: TensorflowSavedModel, description: 'Output path
|
||||
for the saved model,'}
|
||||
implementation:
|
||||
container:
|
||||
image: us-docker.pkg.dev/vertex-ai/ready-to-go-image-classification/image-components:v0.1
|
||||
# command is a list of strings (command-line arguments).
|
||||
# The YAML language has two syntaxes for lists and you can use either of them.
|
||||
# Here we use the "flow syntax" - comma-separated strings inside square brackets.
|
||||
command: [
|
||||
python3,
|
||||
# Path of the program inside the container
|
||||
/pipelines/component/src/training_component.py,
|
||||
--preprocessed-training-data-path,
|
||||
{inputPath: preprocessed_training_data_path},
|
||||
--preprocessed-validation-data-path,
|
||||
{inputPath: preprocessed_validation_data_path},
|
||||
--model-path,
|
||||
{inputPath: model_path},
|
||||
--trained-model-path,
|
||||
{outputPath: trained_model_path},
|
||||
--optimizer-name,
|
||||
{inputValue: optimizer_name},
|
||||
--loss-function-name,
|
||||
{inputValue: loss_function_name},
|
||||
--number-of-epochs,
|
||||
{inputValue: number_of_epochs},
|
||||
--seed,
|
||||
{inputValue: seed},
|
||||
--batch-size,
|
||||
{inputValue: batch_size},
|
||||
--metric-names,
|
||||
{inputValue: metric_names},
|
||||
--optimizer-parameters,
|
||||
{inputValue: optimizer_parameters},
|
||||
--loss-function-parameters,
|
||||
{inputValue: loss_function_parameters},
|
||||
]
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
name: Transcode imagedataset tfrecord from csv
|
||||
description: |
|
||||
Transcodes CSV Data into TFRecord file of TFExamples.
|
||||
Args:
|
||||
csv_image_data_path (str):
|
||||
Path to the CSV image data. Data must include 'image_filepath' (Path to image file) and
|
||||
'image_label' (output for a prediction) fields.
|
||||
class_names (Sequence[str]):
|
||||
Sequence of strings of categories for classification corresponding to input data.
|
||||
tfrecord_image_data_path (str):
|
||||
Output path for the TFRecord image data. Data will be formatted as 'label' (encoded image
|
||||
label), and 'image_raw' (the binary string of the image data).
|
||||
inputs:
|
||||
- {name: csv_image_data_path, type: ImageDatasetCSV, description: Input path for the
|
||||
CSV image data}
|
||||
- {name: class_names, type: 'typing.List[str]', description: List of class names corresponding
|
||||
to the input image data}
|
||||
outputs:
|
||||
- {name: tfrecord_image_data_path, type: ImageDatasetTFRecord, description: Output
|
||||
path for the TFRecord image data}
|
||||
implementation:
|
||||
container:
|
||||
image: us-docker.pkg.dev/vertex-ai/ready-to-go-image-classification/image-components:v0.1
|
||||
# command is a list of strings (command-line arguments).
|
||||
# The YAML language has two syntaxes for lists and you can use either of them.
|
||||
# Here we use the "flow syntax" - comma-separated strings inside square brackets.
|
||||
command: [
|
||||
python3,
|
||||
# Path of the program inside the container
|
||||
/pipelines/component/src/transcoding_csv_component.py,
|
||||
--csv-image-data-path,
|
||||
{inputPath: csv_image_data_path},
|
||||
--tfrecord-image-data-path,
|
||||
{outputPath: tfrecord_image_data_path},
|
||||
--class-names,
|
||||
{inputValue: class_names},
|
||||
]
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
name: Transcode imagedataset tfrecord from jsonlines
|
||||
description: |
|
||||
Transcodes JSONL Data into TFRecord file of TFExamples.
|
||||
Args:
|
||||
jsonl_image_data_path (str):
|
||||
Input path for the JSONL image data
|
||||
Path to the JSONL image data. Each line corresponds to a JSON input describing an image.
|
||||
Schema follows AutoML image classification JSONL format
|
||||
https://cloud.google.com/vertex-ai/docs/image-data/classification/prepare-data#json-lines.
|
||||
class_names (Sequence[str]):
|
||||
Sequence of strings of categories for classification corresponding to input data.
|
||||
tfrecord_image_data_path (str):
|
||||
Output path for the TFRecord image data. Data will be formatted as 'label' (encoded image
|
||||
label), and 'image_raw' (the binary string of the image data).
|
||||
inputs:
|
||||
- {name: jsonl_image_data_path, type: ImageDatasetJsonLines, description: Input path
|
||||
for the JSONL image data}
|
||||
- {name: class_names, type: 'typing.List[str]', description: List of class names corresponding
|
||||
to the input image data}
|
||||
outputs:
|
||||
- {name: tfrecord_image_data_path, type: ImageDatasetTFRecord, description: Output
|
||||
path for the TFRecord image data}
|
||||
implementation:
|
||||
container:
|
||||
image: us-docker.pkg.dev/vertex-ai/ready-to-go-image-classification/image-components:v0.1
|
||||
# command is a list of strings (command-line arguments).
|
||||
# The YAML language has two syntaxes for lists and you can use either of them.
|
||||
# Here we use the "flow syntax" - comma-separated strings inside square brackets.
|
||||
command: [
|
||||
python3,
|
||||
# Path of the program inside the container
|
||||
/pipelines/component/src/transcoding_jsonl_component.py,
|
||||
--jsonl-image-data-path,
|
||||
{inputPath: jsonl_image_data_path},
|
||||
--tfrecord-image-data-path,
|
||||
{outputPath: tfrecord_image_data_path},
|
||||
--class-names,
|
||||
{inputValue: class_names},
|
||||
]
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
name: Binarize column using Pandas on CSV data
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/pandas/Binarize_column/in_CSV_format/component.yaml'}
|
||||
inputs:
|
||||
- {name: table, type: CSV}
|
||||
- {name: column_name, type: String}
|
||||
- {name: predicate, type: String, default: '> 0', optional: true}
|
||||
- {name: new_column_name, type: String, optional: true}
|
||||
- name: keep_original_column
|
||||
type: Boolean
|
||||
default: "False"
|
||||
optional: true
|
||||
outputs:
|
||||
- {name: transformed_table, type: CSV}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'pandas==1.4.3' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet
|
||||
--no-warn-script-location 'pandas==1.4.3' --user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def binarize_column_using_Pandas_on_CSV_data(
|
||||
table_path,
|
||||
transformed_table_path,
|
||||
column_name,
|
||||
predicate = "> 0",
|
||||
new_column_name = None,
|
||||
keep_original_column = False,
|
||||
):
|
||||
import pandas
|
||||
|
||||
df = pandas.read_csv(table_path).convert_dtypes()
|
||||
original_series = df[column_name]
|
||||
|
||||
# Dynamically executing the predicate code
|
||||
# Variable namespace for code execution
|
||||
namespace = dict(x=original_series)
|
||||
# I though that there should be no space before `predicate` so that "dot" predicate methods like ".between(min, max)" work.
|
||||
# However Python allows spaces before dot: `df .isna()`.
|
||||
# So having a space is not a problem
|
||||
transform_code = f"""new_series_boolean = x {predicate}"""
|
||||
# Note: exec() takes no keyword arguments
|
||||
# exec(__source=transform_code, __globals=namespace)
|
||||
exec(transform_code, namespace)
|
||||
new_series_boolean = namespace["new_series_boolean"]
|
||||
|
||||
# There are multiple ways to convert boolean column to integer.
|
||||
# .apply(int) might be faster. https://stackoverflow.com/a/49804868/1497385
|
||||
# TODO: Do a proper benchmark.
|
||||
new_series = new_series_boolean.apply(int)
|
||||
# new_series = new_series_boolean.astype(int)
|
||||
# new_series = new_series_boolean.replace({False: 0, True: 1})
|
||||
|
||||
if new_column_name:
|
||||
df.insert(loc=0, column=new_column_name, value=new_series)
|
||||
if not keep_original_column:
|
||||
df = df.drop(columns=[column_name])
|
||||
else:
|
||||
df[column_name] = new_series
|
||||
|
||||
df.to_csv(transformed_table_path, index=False)
|
||||
|
||||
def _deserialize_bool(s) -> bool:
|
||||
from distutils.util import strtobool
|
||||
return strtobool(s) == 1
|
||||
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Binarize column using Pandas on CSV data', description='')
|
||||
_parser.add_argument("--table", dest="table_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--column-name", dest="column_name", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--predicate", dest="predicate", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--new-column-name", dest="new_column_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--keep-original-column", dest="keep_original_column", type=_deserialize_bool, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--transformed-table", dest="transformed_table_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = binarize_column_using_Pandas_on_CSV_data(**_parsed_args)
|
||||
args:
|
||||
- --table
|
||||
- {inputPath: table}
|
||||
- --column-name
|
||||
- {inputValue: column_name}
|
||||
- if:
|
||||
cond: {isPresent: predicate}
|
||||
then:
|
||||
- --predicate
|
||||
- {inputValue: predicate}
|
||||
- if:
|
||||
cond: {isPresent: new_column_name}
|
||||
then:
|
||||
- --new-column-name
|
||||
- {inputValue: new_column_name}
|
||||
- if:
|
||||
cond: {isPresent: keep_original_column}
|
||||
then:
|
||||
- --keep-original-column
|
||||
- {inputValue: keep_original_column}
|
||||
- --transformed-table
|
||||
- {outputPath: transformed_table}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
name: Fill all missing values using Pandas on CSV data
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/pandas/Fill_all_missing_values/in_CSV_format/component.yaml'}
|
||||
inputs:
|
||||
- {name: table, type: CSV}
|
||||
- {name: replacement_value, type: String, default: '0', optional: true}
|
||||
- {name: column_names, type: JsonArray, optional: true}
|
||||
outputs:
|
||||
- {name: transformed_table, type: CSV}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'pandas==1.4.1' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet
|
||||
--no-warn-script-location 'pandas==1.4.1' --user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def fill_all_missing_values_using_Pandas_on_CSV_data(
|
||||
table_path,
|
||||
transformed_table_path,
|
||||
replacement_value = "0",
|
||||
column_names = None,
|
||||
):
|
||||
import pandas
|
||||
|
||||
df = pandas.read_csv(
|
||||
table_path,
|
||||
dtype="string",
|
||||
)
|
||||
|
||||
for column_name in column_names or df.columns:
|
||||
df[column_name] = df[column_name].fillna(value=replacement_value)
|
||||
|
||||
df.to_csv(
|
||||
transformed_table_path, index=False,
|
||||
)
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Fill all missing values using Pandas on CSV data', description='')
|
||||
_parser.add_argument("--table", dest="table_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--replacement-value", dest="replacement_value", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--column-names", dest="column_names", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--transformed-table", dest="transformed_table_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = fill_all_missing_values_using_Pandas_on_CSV_data(**_parsed_args)
|
||||
args:
|
||||
- --table
|
||||
- {inputPath: table}
|
||||
- if:
|
||||
cond: {isPresent: replacement_value}
|
||||
then:
|
||||
- --replacement-value
|
||||
- {inputValue: replacement_value}
|
||||
- if:
|
||||
cond: {isPresent: column_names}
|
||||
then:
|
||||
- --column-names
|
||||
- {inputValue: column_names}
|
||||
- --transformed-table
|
||||
- {outputPath: transformed_table}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
name: Select columns using Pandas on CSV data
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/pandas/Select_columns/in_CSV_format/component.yaml'}
|
||||
inputs:
|
||||
- {name: table, type: CSV}
|
||||
- {name: column_names, type: JsonArray}
|
||||
outputs:
|
||||
- {name: transformed_table, type: CSV}
|
||||
implementation:
|
||||
container:
|
||||
image: python:3.9
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- (PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet --no-warn-script-location
|
||||
'pandas==1.4.2' || PIP_DISABLE_PIP_VERSION_CHECK=1 python3 -m pip install --quiet
|
||||
--no-warn-script-location 'pandas==1.4.2' --user) && "$0" "$@"
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def select_columns_using_Pandas_on_CSV_data(
|
||||
table_path,
|
||||
transformed_table_path,
|
||||
column_names,
|
||||
):
|
||||
import pandas
|
||||
|
||||
df = pandas.read_csv(
|
||||
table_path,
|
||||
dtype="string",
|
||||
)
|
||||
df = df[column_names]
|
||||
df.to_csv(transformed_table_path, index=False)
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Select columns using Pandas on CSV data', description='')
|
||||
_parser.add_argument("--table", dest="table_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--column-names", dest="column_names", type=json.loads, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--transformed-table", dest="transformed_table_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = select_columns_using_Pandas_on_CSV_data(**_parsed_args)
|
||||
args:
|
||||
- --table
|
||||
- {inputPath: table}
|
||||
- --column-names
|
||||
- {inputValue: column_names}
|
||||
- --transformed-table
|
||||
- {outputPath: transformed_table}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
name: Create fully connected tensorflow network
|
||||
description: Creates fully-connected network in Tensorflow SavedModel format
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/tensorflow/Create_fully_connected_network/component.yaml'}
|
||||
inputs:
|
||||
- {name: input_size, type: Integer}
|
||||
- {name: hidden_layer_sizes, type: JsonArray, default: '[]', optional: true}
|
||||
- {name: output_size, type: Integer, default: '1', optional: true}
|
||||
- {name: activation_name, type: String, default: relu, optional: true}
|
||||
- {name: output_activation_name, type: String, optional: true}
|
||||
- {name: random_seed, type: Integer, default: '0', optional: true}
|
||||
outputs:
|
||||
- {name: model, type: TensorflowSavedModel}
|
||||
implementation:
|
||||
container:
|
||||
image: tensorflow/tensorflow:2.7.0
|
||||
command:
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def create_fully_connected_tensorflow_network(
|
||||
input_size,
|
||||
model_path,
|
||||
hidden_layer_sizes = [],
|
||||
output_size = 1,
|
||||
activation_name = "relu",
|
||||
output_activation_name = None,
|
||||
random_seed = 0,
|
||||
):
|
||||
"""Creates fully-connected network in Tensorflow SavedModel format"""
|
||||
import tensorflow as tf
|
||||
tf.random.set_seed(seed=random_seed)
|
||||
|
||||
model = tf.keras.models.Sequential()
|
||||
model.add(tf.keras.Input(shape=(input_size,)))
|
||||
for layer_size in hidden_layer_sizes:
|
||||
model.add(tf.keras.layers.Dense(units=layer_size, activation=activation_name))
|
||||
# The last layer is left without activation
|
||||
model.add(tf.keras.layers.Dense(units=output_size, activation=output_activation_name))
|
||||
|
||||
print(model.summary())
|
||||
|
||||
# Using tf.keras.models.save_model instead of tf.saved_model.save to prevent downstream error:
|
||||
#tf.saved_model.save(model, model_path)
|
||||
# ValueError: Unable to create a Keras model from this SavedModel.
|
||||
# This SavedModel was created with `tf.saved_model.save`, and lacks the Keras metadata.
|
||||
# Please save your Keras model by calling `model.save`or `tf.keras.models.save_model`.
|
||||
# See https://github.com/keras-team/keras/issues/16451
|
||||
tf.keras.models.save_model(model, model_path)
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Create fully connected tensorflow network', description='Creates fully-connected network in Tensorflow SavedModel format')
|
||||
_parser.add_argument("--input-size", dest="input_size", type=int, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--hidden-layer-sizes", dest="hidden_layer_sizes", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--output-size", dest="output_size", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--activation-name", dest="activation_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--output-activation-name", dest="output_activation_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--random-seed", dest="random_seed", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--model", dest="model_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = create_fully_connected_tensorflow_network(**_parsed_args)
|
||||
args:
|
||||
- --input-size
|
||||
- {inputValue: input_size}
|
||||
- if:
|
||||
cond: {isPresent: hidden_layer_sizes}
|
||||
then:
|
||||
- --hidden-layer-sizes
|
||||
- {inputValue: hidden_layer_sizes}
|
||||
- if:
|
||||
cond: {isPresent: output_size}
|
||||
then:
|
||||
- --output-size
|
||||
- {inputValue: output_size}
|
||||
- if:
|
||||
cond: {isPresent: activation_name}
|
||||
then:
|
||||
- --activation-name
|
||||
- {inputValue: activation_name}
|
||||
- if:
|
||||
cond: {isPresent: output_activation_name}
|
||||
then:
|
||||
- --output-activation-name
|
||||
- {inputValue: output_activation_name}
|
||||
- if:
|
||||
cond: {isPresent: random_seed}
|
||||
then:
|
||||
- --random-seed
|
||||
- {inputValue: random_seed}
|
||||
- --model
|
||||
- {outputPath: model}
|
||||
@@ -0,0 +1,100 @@
|
||||
name: Predict with TensorFlow model on CSV data
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/tensorflow/Predict/on_CSV/component.yaml'}
|
||||
inputs:
|
||||
- {name: dataset, type: CSV}
|
||||
- {name: model, type: TensorflowSavedModel}
|
||||
- {name: label_column_name, type: String, optional: true}
|
||||
- {name: batch_size, type: Integer, default: '1000', optional: true}
|
||||
outputs:
|
||||
- {name: predictions}
|
||||
implementation:
|
||||
container:
|
||||
image: tensorflow/tensorflow:2.9.1
|
||||
command:
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def predict_with_TensorFlow_model_on_CSV_data(
|
||||
dataset_path,
|
||||
model_path,
|
||||
predictions_path,
|
||||
label_column_name = None,
|
||||
batch_size = 1000,
|
||||
):
|
||||
import numpy
|
||||
import tensorflow as tf
|
||||
|
||||
model = tf.saved_model.load(export_dir=model_path)
|
||||
|
||||
dataset = tf.data.experimental.make_csv_dataset(
|
||||
file_pattern=dataset_path,
|
||||
batch_size=batch_size,
|
||||
label_name=label_column_name,
|
||||
header=True,
|
||||
num_epochs=1,
|
||||
shuffle=False,
|
||||
ignore_errors=False,
|
||||
)
|
||||
|
||||
def stack_feature_batches(features_batch):
|
||||
# Need to stack individual feature columns to create a single feature tensor
|
||||
# Need to cast all column tensor types to float to prevent errors.
|
||||
list_of_feature_batches = list(
|
||||
tf.cast(x=feature_batch, dtype=tf.float32)
|
||||
for feature_batch in features_batch.values()
|
||||
)
|
||||
return tf.stack(list_of_feature_batches, axis=-1)
|
||||
|
||||
def transform_features_and_drop_labels(features_batch, labels_batch):
|
||||
return stack_feature_batches(features_batch)
|
||||
|
||||
dataset_map_fn = (
|
||||
transform_features_and_drop_labels
|
||||
if label_column_name
|
||||
else stack_feature_batches
|
||||
)
|
||||
|
||||
dataset = dataset.map(dataset_map_fn)
|
||||
|
||||
with open(predictions_path, "w") as predictions_file:
|
||||
for features_batch in dataset:
|
||||
predictions_tensor = model(features_batch)
|
||||
numpy.savetxt(predictions_file, predictions_tensor.numpy())
|
||||
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Predict with TensorFlow model on CSV data', description='')
|
||||
_parser.add_argument("--dataset", dest="dataset_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--model", dest="model_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--label-column-name", dest="label_column_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--batch-size", dest="batch_size", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--predictions", dest="predictions_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = predict_with_TensorFlow_model_on_CSV_data(**_parsed_args)
|
||||
args:
|
||||
- --dataset
|
||||
- {inputPath: dataset}
|
||||
- --model
|
||||
- {inputPath: model}
|
||||
- if:
|
||||
cond: {isPresent: label_column_name}
|
||||
then:
|
||||
- --label-column-name
|
||||
- {inputValue: label_column_name}
|
||||
- if:
|
||||
cond: {isPresent: batch_size}
|
||||
then:
|
||||
- --batch-size
|
||||
- {inputValue: batch_size}
|
||||
- --predictions
|
||||
- {outputPath: predictions}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
name: Train model using Keras on CSV
|
||||
metadata:
|
||||
annotations: {author: Alexey Volkov <alexey.volkov@ark-kun.com>, canonical_location: 'https://raw.githubusercontent.com/Ark-kun/pipeline_components/master/components/tensorflow/Train_model_using_Keras/on_CSV/component.yaml'}
|
||||
inputs:
|
||||
- {name: training_data, type: CSV}
|
||||
- {name: model, type: TensorflowSavedModel}
|
||||
- {name: label_column_name, type: String}
|
||||
- {name: loss_function_name, type: String, default: mean_squared_error, optional: true}
|
||||
- {name: number_of_epochs, type: Integer, default: '1', optional: true}
|
||||
- {name: learning_rate, type: Float, default: '0.1', optional: true}
|
||||
- {name: optimizer_name, type: String, default: Adadelta, optional: true}
|
||||
- {name: optimizer_parameters, type: JsonObject, optional: true}
|
||||
- {name: batch_size, type: Integer, default: '32', optional: true}
|
||||
- {name: metric_names, type: JsonArray, optional: true}
|
||||
- {name: random_seed, type: Integer, default: '0', optional: true}
|
||||
outputs:
|
||||
- {name: trained_model, type: TensorflowSavedModel}
|
||||
implementation:
|
||||
container:
|
||||
image: tensorflow/tensorflow:2.8.0
|
||||
command:
|
||||
- sh
|
||||
- -ec
|
||||
- |
|
||||
program_path=$(mktemp)
|
||||
printf "%s" "$0" > "$program_path"
|
||||
python3 -u "$program_path" "$@"
|
||||
- |
|
||||
def _make_parent_dirs_and_return_path(file_path: str):
|
||||
import os
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
return file_path
|
||||
|
||||
def train_model_using_Keras_on_CSV(
|
||||
training_data_path,
|
||||
model_path,
|
||||
trained_model_path,
|
||||
label_column_name,
|
||||
loss_function_name = "mean_squared_error",
|
||||
number_of_epochs = 1,
|
||||
learning_rate = 0.1,
|
||||
optimizer_name = "Adadelta",
|
||||
optimizer_parameters = None,
|
||||
batch_size = 32,
|
||||
metric_names = None,
|
||||
random_seed = 0,
|
||||
):
|
||||
import tensorflow as tf
|
||||
tf.random.set_seed(seed=random_seed)
|
||||
|
||||
# Loading model using Keras. Model loaded using TensorFlow does not have .fit.
|
||||
#model = tf.saved_model.load(export_dir=model_path)
|
||||
keras_model = tf.keras.models.load_model(filepath=model_path)
|
||||
|
||||
optimizer_parameters = optimizer_parameters or {}
|
||||
optimizer_parameters["learning_rate"] = learning_rate
|
||||
optimizer_config = {
|
||||
"class_name": optimizer_name,
|
||||
"config": optimizer_parameters,
|
||||
}
|
||||
optimizer = tf.keras.optimizers.get(optimizer_config)
|
||||
loss = tf.keras.losses.get(loss_function_name)
|
||||
|
||||
training_dataset = tf.data.experimental.make_csv_dataset(
|
||||
file_pattern=training_data_path,
|
||||
batch_size=batch_size,
|
||||
label_name=label_column_name,
|
||||
header=True,
|
||||
# Need to specify num_epochs=1 otherwise the training becomes infinite
|
||||
num_epochs=1,
|
||||
shuffle=True,
|
||||
shuffle_seed=random_seed,
|
||||
ignore_errors=True,
|
||||
)
|
||||
def stack_feature_batches(features_batch, labels_batch):
|
||||
# Need to stack individual feature columns to create a single feature tensor
|
||||
# Need to cast all column tensor types to float to prevent error:
|
||||
# TypeError: Tensors in list passed to 'values' of 'Pack' Op have types [int32, float32, float32, int32, int32] that don't all match.
|
||||
list_of_feature_batches = list(tf.cast(x=feature_batch, dtype=tf.float32) for feature_batch in features_batch.values())
|
||||
return tf.stack(list_of_feature_batches, axis=-1), labels_batch
|
||||
|
||||
training_dataset = training_dataset.map(stack_feature_batches)
|
||||
|
||||
# Need to compile the model to prevent error:
|
||||
# ValueError: No gradients provided for any variable: [..., ...].
|
||||
keras_model.compile(
|
||||
optimizer=optimizer,
|
||||
loss=loss,
|
||||
metrics=metric_names,
|
||||
)
|
||||
keras_model.fit(
|
||||
training_dataset,
|
||||
epochs=number_of_epochs,
|
||||
)
|
||||
|
||||
# Using tf.keras.models.save_model instead of tf.saved_model.save to prevent downstream error:
|
||||
#tf.saved_model.save(keras_model, trained_model_path)
|
||||
# ValueError: Unable to create a Keras model from this SavedModel.
|
||||
# This SavedModel was created with `tf.saved_model.save`, and lacks the Keras metadata.
|
||||
# Please save your Keras model by calling `model.save`or `tf.keras.models.save_model`.
|
||||
# See https://github.com/keras-team/keras/issues/16451
|
||||
tf.keras.models.save_model(keras_model, trained_model_path)
|
||||
|
||||
import json
|
||||
import argparse
|
||||
_parser = argparse.ArgumentParser(prog='Train model using Keras on CSV', description='')
|
||||
_parser.add_argument("--training-data", dest="training_data_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--model", dest="model_path", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--label-column-name", dest="label_column_name", type=str, required=True, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--loss-function-name", dest="loss_function_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--number-of-epochs", dest="number_of_epochs", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--learning-rate", dest="learning_rate", type=float, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--optimizer-name", dest="optimizer_name", type=str, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--optimizer-parameters", dest="optimizer_parameters", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--batch-size", dest="batch_size", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--metric-names", dest="metric_names", type=json.loads, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--random-seed", dest="random_seed", type=int, required=False, default=argparse.SUPPRESS)
|
||||
_parser.add_argument("--trained-model", dest="trained_model_path", type=_make_parent_dirs_and_return_path, required=True, default=argparse.SUPPRESS)
|
||||
_parsed_args = vars(_parser.parse_args())
|
||||
|
||||
_outputs = train_model_using_Keras_on_CSV(**_parsed_args)
|
||||
args:
|
||||
- --training-data
|
||||
- {inputPath: training_data}
|
||||
- --model
|
||||
- {inputPath: model}
|
||||
- --label-column-name
|
||||
- {inputValue: label_column_name}
|
||||
- if:
|
||||
cond: {isPresent: loss_function_name}
|
||||
then:
|
||||
- --loss-function-name
|
||||
- {inputValue: loss_function_name}
|
||||
- if:
|
||||
cond: {isPresent: number_of_epochs}
|
||||
then:
|
||||
- --number-of-epochs
|
||||
- {inputValue: number_of_epochs}
|
||||
- if:
|
||||
cond: {isPresent: learning_rate}
|
||||
then:
|
||||
- --learning-rate
|
||||
- {inputValue: learning_rate}
|
||||
- if:
|
||||
cond: {isPresent: optimizer_name}
|
||||
then:
|
||||
- --optimizer-name
|
||||
- {inputValue: optimizer_name}
|
||||
- if:
|
||||
cond: {isPresent: optimizer_parameters}
|
||||
then:
|
||||
- --optimizer-parameters
|
||||
- {inputValue: optimizer_parameters}
|
||||
- if:
|
||||
cond: {isPresent: batch_size}
|
||||
then:
|
||||
- --batch-size
|
||||
- {inputValue: batch_size}
|
||||
- if:
|
||||
cond: {isPresent: metric_names}
|
||||
then:
|
||||
- --metric-names
|
||||
- {inputValue: metric_names}
|
||||
- if:
|
||||
cond: {isPresent: random_seed}
|
||||
then:
|
||||
- --random-seed
|
||||
- {inputValue: random_seed}
|
||||
- --trained-model
|
||||
- {outputPath: trained_model}
|
||||
+1507
File diff suppressed because it is too large
Load Diff
@@ -15,15 +15,19 @@ pip install -r requirements.txt
|
||||
* resnet_dp.py - Train ResNet-50 on single node multiple GPUs with `DataParallel` strategy.
|
||||
* resnet_ddp.py - Train ResNet-50 on single node multiple GPUs with `DistributedDataParallel` strategy.
|
||||
* resnet_ddp_wds.py - Train ResNet-50 on single node multiple GPUs with `DistributedDataParallel` strategy and `Webdataset`.
|
||||
* resnet_fsdp.py - Train ResNet-50 on single node multiple GPUs with `FullyShardedDataParallel` strategy.
|
||||
* resnet_fsdp_wds.py - Train ResNet-50 on single node multiple GPUs with `FullyShardedDataParallel` strategy and `Webdataset`.
|
||||
* shard_imagenet.py - Shard ImagNet individual files into `tar` files.
|
||||
|
||||
## Benchmark
|
||||
|
||||
When run the benchmark on Nvidia T4 GPUs using ImageNet validation dataset, you can get the result like:
|
||||
Strategy | Seconds/Epoch - Local Data | Seconds/Epoch - Cloud Data
|
||||
--------------------- | -------------------------- | --------------------------
|
||||
On 1 GPU | 489 | 804 (2x slower)
|
||||
On 4 GPUs (DP) | 157 | 738 (5x slower)
|
||||
On 4 GPUs (DDP) | 134 | 432 (3x slower)
|
||||
On 4 GPUs (DDP + WDS) | 131 | 133 (same performance)
|
||||
Strategy | Seconds/Epoch - Local Data | Seconds/Epoch - Cloud Data
|
||||
---------------------- | -------------------------- | --------------------------
|
||||
On 1 GPU | 489 | 804 (2x slower)
|
||||
On 4 GPUs (DP) | 157 | 738 (5x slower)
|
||||
On 4 GPUs (DDP) | 134 | 432 (3x slower)
|
||||
On 4 GPUs (DDP + WDS) | 131 | 133 (same performance)
|
||||
On 4 GPUs (FSDP) | 139 | 353 (3x slower)
|
||||
On 4 GPUs (FSDP + WDS) | 138 | 135 (same performance)
|
||||
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
# Copyright 2022 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the \"License\");
|
||||
# you may not use this file except in compliance with the License.\n",
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an \"AS IS\" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Train resnet on multiple GPUs with FSDP."""
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import os
|
||||
import time
|
||||
|
||||
from PIL import Image
|
||||
import torch
|
||||
from torch import nn
|
||||
import torch.distributed as dist
|
||||
from torch.distributed.fsdp import FullyShardedDataParallel as FSDP
|
||||
from torch.distributed.fsdp.wrap import size_based_auto_wrap_policy
|
||||
import torch.multiprocessing as mp
|
||||
import torchmetrics
|
||||
import torchvision
|
||||
from torchvision.models import resnet50
|
||||
|
||||
|
||||
class ImageFolder(torchvision.datasets.ImageFolder):
|
||||
"""Class for loading imagenet."""
|
||||
|
||||
def __init__(self, image_list_file, transform=None, target_transform=None):
|
||||
self.samples = self._make_dataset(image_list_file)
|
||||
self.loader = self._loader
|
||||
|
||||
self.imgs = self.samples
|
||||
self.targets = [s[1] for s in self.samples]
|
||||
|
||||
self.transform = transform
|
||||
self.target_transform = target_transform
|
||||
|
||||
def _make_dataset(self, image_list_file):
|
||||
items = []
|
||||
with open(image_list_file, 'r') as f:
|
||||
for line in f:
|
||||
item = line.strip().split(' ')
|
||||
items.append((item[0], int(item[1])))
|
||||
return items
|
||||
|
||||
def _loader(self, image_path):
|
||||
with open(image_path, 'rb') as f:
|
||||
img = Image.open(f)
|
||||
img = img.convert('RGB')
|
||||
return img
|
||||
|
||||
|
||||
def train(model, device, dataloader, optimizer):
|
||||
model.train()
|
||||
for image, target in dataloader:
|
||||
image = image.to(device, non_blocking=True)
|
||||
target = target.to(device, non_blocking=True)
|
||||
pred = model(image)
|
||||
# pred.shape (N, C), target.shape (N)
|
||||
loss = nn.functional.cross_entropy(pred, target)
|
||||
optimizer.zero_grad()
|
||||
loss.backward()
|
||||
optimizer.step()
|
||||
return loss
|
||||
|
||||
|
||||
def evaluate(model, device, dataloader, metric):
|
||||
model.eval()
|
||||
with torch.no_grad():
|
||||
for image, target in dataloader:
|
||||
image = image.to(device, non_blocking=True)
|
||||
target = target.to(device, non_blocking=True)
|
||||
pred = model(image)
|
||||
metric.update(pred, target)
|
||||
accuracy = metric.compute()
|
||||
metric.reset()
|
||||
return accuracy
|
||||
|
||||
|
||||
def worker(gpu, args):
|
||||
"""Run training and evaluation."""
|
||||
# Init process group.
|
||||
print(f'Initiating process {gpu}')
|
||||
dist.init_process_group(
|
||||
backend='nccl',
|
||||
init_method='env://',
|
||||
world_size=args.gpus,
|
||||
rank=gpu)
|
||||
|
||||
# Create train dataloader.
|
||||
train_dataset = ImageFolder(
|
||||
image_list_file=args.train_data_path,
|
||||
transform=torchvision.transforms.Compose([
|
||||
torchvision.transforms.RandomResizedCrop(224),
|
||||
torchvision.transforms.RandomHorizontalFlip(),
|
||||
torchvision.transforms.ToTensor(),
|
||||
torchvision.transforms.Normalize(
|
||||
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
|
||||
]))
|
||||
train_sampler = torch.utils.data.distributed.DistributedSampler(
|
||||
train_dataset, num_replicas=args.gpus, rank=gpu)
|
||||
train_dataloader = torch.utils.data.DataLoader(
|
||||
dataset=train_dataset,
|
||||
batch_size=args.train_batch_size,
|
||||
shuffle=False,
|
||||
num_workers=args.dataloader_num_workers,
|
||||
pin_memory=True,
|
||||
sampler=train_sampler)
|
||||
if gpu == 0:
|
||||
print(f'Train dataloader | samples: {len(train_dataloader.dataset)}, '
|
||||
f'num workers: {train_dataloader.num_workers}, '
|
||||
f'global batch size: {args.train_batch_size * args.gpus}, '
|
||||
f'batches/epoch: {len(train_dataloader)}')
|
||||
|
||||
# Create eval dataloader.
|
||||
eval_dataset = ImageFolder(
|
||||
image_list_file=args.eval_data_path,
|
||||
transform=torchvision.transforms.Compose([
|
||||
torchvision.transforms.Resize(256),
|
||||
torchvision.transforms.CenterCrop(224),
|
||||
torchvision.transforms.ToTensor(),
|
||||
torchvision.transforms.Normalize(
|
||||
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
|
||||
]))
|
||||
eval_sampler = torch.utils.data.distributed.DistributedSampler(
|
||||
eval_dataset, num_replicas=args.gpus, rank=gpu)
|
||||
eval_dataloader = torch.utils.data.DataLoader(
|
||||
dataset=eval_dataset,
|
||||
batch_size=args.eval_batch_size,
|
||||
shuffle=False,
|
||||
num_workers=args.dataloader_num_workers,
|
||||
pin_memory=True,
|
||||
drop_last=True,
|
||||
sampler=eval_sampler)
|
||||
if gpu == 0:
|
||||
print(f'Eval dataloader | samples: {len(eval_dataloader.dataset)}, '
|
||||
f'num workers: {eval_dataloader.num_workers}, '
|
||||
f'batch size: {args.eval_batch_size}, '
|
||||
f'batches/epoch: {len(eval_dataloader)}')
|
||||
|
||||
# Wrap policy.
|
||||
my_auto_wrap_policy = functools.partial(
|
||||
size_based_auto_wrap_policy, min_num_params=100)
|
||||
torch.cuda.set_device(gpu)
|
||||
|
||||
# Create model.
|
||||
model = resnet50(weights=None)
|
||||
model.to(args.device)
|
||||
model = FSDP(model, auto_wrap_policy=my_auto_wrap_policy)
|
||||
|
||||
# Optimizer.
|
||||
optimizer = torch.optim.SGD(model.parameters(), 0.1)
|
||||
|
||||
# Main loop.
|
||||
metric = torchmetrics.classification.Accuracy(top_k=1).to(args.device)
|
||||
for epoch in range(1, args.epochs + 1):
|
||||
if gpu == 0:
|
||||
print(f'Running epoch {epoch}')
|
||||
train_sampler.set_epoch(epoch)
|
||||
|
||||
start = time.time()
|
||||
train(model, args.device, train_dataloader, optimizer)
|
||||
end = time.time()
|
||||
if gpu == 0:
|
||||
print(f'Training finished in {(end - start):>0.3f} seconds')
|
||||
|
||||
start = time.time()
|
||||
evaluate(model, args.device, eval_dataloader, metric)
|
||||
end = time.time()
|
||||
if gpu == 0:
|
||||
print(f'Evaluation finished in {(end - start):>0.3f} seconds')
|
||||
|
||||
if gpu == 0:
|
||||
print('Done')
|
||||
dist.destroy_process_group()
|
||||
|
||||
|
||||
def create_args():
|
||||
"""Create main args."""
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument(
|
||||
'--gpus',
|
||||
default=4,
|
||||
type=int,
|
||||
help='number of gpus to use')
|
||||
parser.add_argument(
|
||||
'--epochs',
|
||||
default=2,
|
||||
type=int,
|
||||
help='number of total epochs to run')
|
||||
parser.add_argument(
|
||||
'--dataloader_num_workers',
|
||||
default=2,
|
||||
type=int,
|
||||
help='number of workders for dataloader')
|
||||
parser.add_argument(
|
||||
'--train_data_path',
|
||||
default='',
|
||||
type=str,
|
||||
help='path to training data')
|
||||
parser.add_argument(
|
||||
'--train_batch_size',
|
||||
default=32,
|
||||
type=int,
|
||||
help='batch size for training per gpu')
|
||||
parser.add_argument(
|
||||
'--eval_data_path',
|
||||
default='',
|
||||
type=str,
|
||||
help='path to evaluation data')
|
||||
parser.add_argument(
|
||||
'--eval_batch_size',
|
||||
default=32,
|
||||
type=int,
|
||||
help='batch size for evaluation per gpu')
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
def main():
|
||||
args = create_args()
|
||||
|
||||
os.environ['MASTER_ADDR'] = 'localhost'
|
||||
os.environ['MASTER_PORT'] = '8888'
|
||||
|
||||
args.device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
||||
print(f'Launch job on {args.gpus} GPUs with FSDP')
|
||||
mp.spawn(worker, nprocs=args.gpus, args=(args,))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,240 @@
|
||||
"""Train resnet on multiple GPUs with DDP."""
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import itertools
|
||||
import math
|
||||
import os
|
||||
import time
|
||||
|
||||
import torch
|
||||
from torch import nn
|
||||
import torch.distributed as dist
|
||||
from torch.distributed.fsdp import FullyShardedDataParallel as FSDP
|
||||
from torch.distributed.fsdp.wrap import size_based_auto_wrap_policy
|
||||
import torch.multiprocessing as mp
|
||||
import torchmetrics
|
||||
from torchvision.models import resnet50
|
||||
from torchvision.transforms import transforms
|
||||
import webdataset as wds
|
||||
|
||||
|
||||
def wds_split(src, rank, world_size):
|
||||
"""Shards split function for webdataset."""
|
||||
# The context of caller of this function is within multiple processes
|
||||
# (by DDP world_size) and multiple workers (by dataloader_num_workers).
|
||||
# So we totally have (world_size * num_workers) workers for processing data.
|
||||
# NOTE: Raw data should be sharded to enough shards to make sure one process
|
||||
# can handle at least one shard, otherwise the process may hang.
|
||||
worker_id = 0
|
||||
num_workers = 1
|
||||
worker_info = torch.utils.data.get_worker_info()
|
||||
if worker_info:
|
||||
worker_id = worker_info.id
|
||||
num_workers = worker_info.num_workers
|
||||
for s in itertools.islice(src, rank * num_workers + worker_id, None,
|
||||
world_size * num_workers):
|
||||
yield s
|
||||
|
||||
|
||||
def identity(x):
|
||||
return x
|
||||
|
||||
|
||||
def create_wds_dataloader(rank, args, mode):
|
||||
"""Create webdataset dataset and dataloader."""
|
||||
if mode == 'train':
|
||||
transform = transforms.Compose([
|
||||
transforms.RandomResizedCrop(224),
|
||||
transforms.RandomHorizontalFlip(),
|
||||
transforms.ToTensor(),
|
||||
transforms.Normalize(
|
||||
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
|
||||
])
|
||||
data_path = args.train_data_path
|
||||
data_size = args.train_data_size
|
||||
batch_size_local = args.train_batch_size
|
||||
batch_size_global = args.train_batch_size * args.gpus
|
||||
# Since webdataset disallows partial batch, we pad the last batch for train.
|
||||
batches = int(math.ceil(data_size / batch_size_global))
|
||||
else:
|
||||
transform = transforms.Compose([
|
||||
transforms.Resize(256),
|
||||
transforms.CenterCrop(224),
|
||||
transforms.ToTensor(),
|
||||
transforms.Normalize(
|
||||
mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
|
||||
])
|
||||
data_path = args.eval_data_path
|
||||
data_size = args.eval_data_size
|
||||
batch_size_local = args.eval_batch_size
|
||||
batch_size_global = args.eval_batch_size * args.gpus
|
||||
# Since webdataset disallows partial batch, we drop the last batch for eval.
|
||||
batches = int(data_size / batch_size_global)
|
||||
|
||||
dataset = wds.DataPipeline(
|
||||
wds.SimpleShardList(data_path),
|
||||
functools.partial(wds_split, rank=rank, world_size=args.gpus),
|
||||
wds.tarfile_to_samples(),
|
||||
wds.decode('pil'),
|
||||
wds.to_tuple('jpg;png;jpeg cls'),
|
||||
wds.map_tuple(transform, identity),
|
||||
wds.batched(batch_size_local, partial=False),
|
||||
)
|
||||
num_workers = args.dataloader_num_workers
|
||||
dataloader = wds.WebLoader(
|
||||
dataset=dataset,
|
||||
batch_size=None,
|
||||
shuffle=False,
|
||||
num_workers=num_workers,
|
||||
persistent_workers=True if num_workers > 0 else False,
|
||||
pin_memory=True).repeat(nbatches=batches)
|
||||
print(f'{mode} dataloader | samples: {data_size}, '
|
||||
f'num_workers: {num_workers}, '
|
||||
f'local batch size: {batch_size_local}, '
|
||||
f'global batch size: {batch_size_global}, '
|
||||
f'batches: {batches}')
|
||||
return dataloader
|
||||
|
||||
|
||||
def train(model, device, dataloader, optimizer):
|
||||
model.train()
|
||||
for image, target in dataloader:
|
||||
image = image.to(device, non_blocking=True)
|
||||
target = target.to(device, non_blocking=True)
|
||||
pred = model(image)
|
||||
# pred.shape (N, C), target.shape (N)
|
||||
loss = nn.functional.cross_entropy(pred, target)
|
||||
optimizer.zero_grad()
|
||||
loss.backward()
|
||||
optimizer.step()
|
||||
return loss
|
||||
|
||||
|
||||
def evaluate(model, device, dataloader, metric):
|
||||
model.eval()
|
||||
with torch.no_grad():
|
||||
for image, target in dataloader:
|
||||
image = image.to(device, non_blocking=True)
|
||||
target = target.to(device, non_blocking=True)
|
||||
pred = model(image)
|
||||
metric.update(pred, target)
|
||||
accuracy = metric.compute()
|
||||
metric.reset()
|
||||
return accuracy
|
||||
|
||||
|
||||
def worker(gpu, args):
|
||||
"""Run training and evaluation."""
|
||||
# Init process group.
|
||||
print(f'Initiating process {gpu}')
|
||||
dist.init_process_group(
|
||||
backend='nccl',
|
||||
init_method='env://',
|
||||
world_size=args.gpus,
|
||||
rank=gpu)
|
||||
|
||||
# Create dataloader.
|
||||
train_dataloader = create_wds_dataloader(gpu, args, 'train')
|
||||
eval_dataloader = create_wds_dataloader(gpu, args, 'eval')
|
||||
|
||||
# Wrap policy.
|
||||
my_auto_wrap_policy = functools.partial(
|
||||
size_based_auto_wrap_policy, min_num_params=100)
|
||||
torch.cuda.set_device(gpu)
|
||||
|
||||
# Create model.
|
||||
model = resnet50(weights=None)
|
||||
model.to(args.device)
|
||||
model = FSDP(model, auto_wrap_policy=my_auto_wrap_policy)
|
||||
|
||||
# Optimizer.
|
||||
optimizer = torch.optim.SGD(model.parameters(), 0.1)
|
||||
|
||||
# Main loop.
|
||||
metric = torchmetrics.classification.Accuracy(top_k=1).to(args.device)
|
||||
for epoch in range(1, args.epochs + 1):
|
||||
if gpu == 0:
|
||||
print(f'Running epoch {epoch}')
|
||||
|
||||
start = time.time()
|
||||
train(model, args.device, train_dataloader, optimizer)
|
||||
end = time.time()
|
||||
if gpu == 0:
|
||||
print(f'Training finished in {(end - start):>0.3f} seconds')
|
||||
|
||||
start = time.time()
|
||||
evaluate(model, args.device, eval_dataloader, metric)
|
||||
end = time.time()
|
||||
if gpu == 0:
|
||||
print(f'Evaluation finished in {(end - start):>0.3f} seconds')
|
||||
|
||||
if gpu == 0:
|
||||
print('Done')
|
||||
|
||||
|
||||
def create_args():
|
||||
"""Create main args."""
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument(
|
||||
'--gpus',
|
||||
default=4,
|
||||
type=int,
|
||||
help='number of gpus to use')
|
||||
parser.add_argument(
|
||||
'--epochs',
|
||||
default=2,
|
||||
type=int,
|
||||
help='number of total epochs to run')
|
||||
parser.add_argument(
|
||||
'--dataloader_num_workers',
|
||||
default=2,
|
||||
type=int,
|
||||
help='number of workders for dataloader')
|
||||
parser.add_argument(
|
||||
'--train_data_path',
|
||||
default='',
|
||||
type=str,
|
||||
help='path to training data')
|
||||
parser.add_argument(
|
||||
'--train_batch_size',
|
||||
default=32,
|
||||
type=int,
|
||||
help='batch size for training per gpu')
|
||||
parser.add_argument(
|
||||
'--train_data_size',
|
||||
default=50000,
|
||||
type=int,
|
||||
help='data size for training')
|
||||
parser.add_argument(
|
||||
'--eval_data_path',
|
||||
default='',
|
||||
type=str,
|
||||
help='path to evaluation data')
|
||||
parser.add_argument(
|
||||
'--eval_batch_size',
|
||||
default=32,
|
||||
type=int,
|
||||
help='batch size for evaluation per gpu')
|
||||
parser.add_argument(
|
||||
'--eval_data_size',
|
||||
default=50000,
|
||||
type=int,
|
||||
help='data size for evaluation')
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
def main():
|
||||
args = create_args()
|
||||
os.environ['MASTER_ADDR'] = 'localhost'
|
||||
os.environ['MASTER_PORT'] = '8888'
|
||||
|
||||
args.device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
||||
print(f'Launch job on {args.gpus} GPUs with FSDP')
|
||||
mp.spawn(worker, nprocs=args.gpus, args=(args,))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
torch==1.8.1
|
||||
torch==1.13.1
|
||||
torchvision==0.9.1
|
||||
tensorboard==2.5.0
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
torch==1.8.1
|
||||
torch==1.13.1
|
||||
torchvision==0.9.1
|
||||
tensorboard==2.5.0
|
||||
+1
-11
@@ -31,17 +31,7 @@
|
||||
"source": [
|
||||
"# Deploying a PyTorch Text Classification Model on [Vertex AI](https://cloud.google.com/vertex-ai)\n",
|
||||
"\n",
|
||||
"**This is an Experimental release**, covered by the Pre-GA Offerings Terms of your Google Cloud Platform [Terms of Service](https://cloud.google.com/terms).\n",
|
||||
"\n",
|
||||
"Experiments are focused on validating a prototype and are not guaranteed to be released. They are not intended for production use or covered by any SLA, support obligation, or deprecation policy and might be subject to backward-incompatible changes.\n",
|
||||
"\n",
|
||||
"**Kindly drop us a note before you run any scale tests.**\n",
|
||||
"\n",
|
||||
"**Do not hesitate to contact vertexai-prediction-preview-feedback@google.com if you have any questions or run into any issues.**\n",
|
||||
"\n",
|
||||
"The usage of the product is free during the Experimental release period: you will still incur charges for other GCP products usage, such as storage.\n",
|
||||
"\n",
|
||||
"The projects need to be added to the allowlist in order to deploy PyTorch models using Vertex AI Prediction pre-built PyTorch images. If you are interested in the feature, please send an email to vertexai-prediction-preview-feedback@google.com to provide your project numbers OR project ids."
|
||||
"**Kindly reach out to Vertex AI before you run any scale tests or you have any questions.**\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
# Administrative Howto notes on CI Notebook Ingestion
|
||||
|
||||
|
||||
This readme covers administrative actions that are performed on an as-needed basis.
|
||||
|
||||
## Team: vertex-ai-owners
|
||||
|
||||
Members of the vertex-ai-owners (git team) have administrative privileges.
|
||||
|
||||
|
||||
### Viewing members
|
||||
|
||||
1. Goto the repo
|
||||
2. From top-level menu, select: (Settings -> Collaborators and Teams)[https://github.com/GoogleCloudPlatform/vertex-ai-samples/settings/access]
|
||||
|
||||
|
||||
### Adding a new member
|
||||
|
||||
If another member needs to be added:
|
||||
- Have the new member make a request to join the team.
|
||||
- vertex-ai-owners with the `Maintainer` tag may add the new member.
|
||||
|
||||
|
||||
## Executing CI notebook ingestion checks on a PR
|
||||
|
||||
### Killing a stuck PR
|
||||
|
||||
If the CI notebook ingestion test is stuck (not terminating), you can kill the process by:
|
||||
|
||||
1. Goto the PR
|
||||
2. Under checks, find the entry: vertex-ai-notebook-execution-test (python-docs-samples-tests) In progress —> Summary
|
||||
3. Select Details
|
||||
4. At bottom of details page, select: View more details on Google Cloud Build
|
||||
5. In Cloud Build history page, select Cancel on the top menu bar.
|
||||
|
||||
### Restart a PR test
|
||||
|
||||
There are two ways to restart the CI notebook ingestion tests on an open PR.
|
||||
|
||||
1. In Cloud Build history page, select Rebuild on the top menu bar.
|
||||
2. or, in a comment in the PR enter: /gcbrun
|
||||
|
||||
## Bypassing CI notebook ingestion checks on a PR
|
||||
|
||||
We strongly discourage this, unless there is a compelling reason that would impact the integrity of the quality process.
|
||||
|
||||
There are two ways of doing this. In both cases, you do:
|
||||
|
||||
1. Goto the repo
|
||||
2. From top-level menu, select: (Settings -> Branches)[https://github.com/GoogleCloudPlatform/vertex-ai-samples/settings/branches]
|
||||
3. Under Branch Protection Rules, select the `main` branch.
|
||||
|
||||
### Allowing a member to disable requirements for merging
|
||||
|
||||
Specific member(s) can be assigned the ability to override requirements and merge a PR, by:
|
||||
|
||||
1. Select Edit for the `main` branch in Branch Protection Rules.
|
||||
2. Find the entry "Allow specified actors to bypass required pull requests".
|
||||
3. Under this entry, add the member's git LDAP.
|
||||
4. Select SAVE.
|
||||
5. The "Squash and Merge" button will now be enabled on all PRs viewed by that member.
|
||||
|
||||
### Temporarily disable checks.
|
||||
|
||||
You can disable requirement checks temporarily on all PRs.
|
||||
|
||||
1. Select Edit for the `main` branch in Branch Protection Rules.
|
||||
2. Uncheck:
|
||||
- Require approvals
|
||||
- Require review from Code Owners
|
||||
- Require status checks to pass before merging
|
||||
3. Select SAVE
|
||||
4. Now all members will see a green "Squash and Merge" on all PRs viewed by that member.
|
||||
|
||||
To reverse, recheck the settings you unchecked above.
|
||||
|
||||
## Linting
|
||||
|
||||
To execute the identical lint image locally, from the CI notebook ingestion checks, do:
|
||||
|
||||
1. Goto the corresponding local folder in the repo.
|
||||
2. Run: `docker run -v ${PWD}:/setup/app gcr.io/python-docs-samples-tests/notebook_linter:latest <your_notebooks>`
|
||||
|
||||
## Install dependency issues
|
||||
|
||||
Some packages (and combinations) have dependencies that fail on the virgin VM image used for the CI notebook ingestion test.
|
||||
|
||||
### TFDV
|
||||
|
||||
If the notebook installs and uses tensorflow_data_validation, install as follows:
|
||||
|
||||
! pip3 install -q {USER_FLAG} google-cloud-aiplatform \
|
||||
tensorflow-data-validation \
|
||||
protobuf==3.20.3
|
||||
|
||||
! pip3 install -q {USER_FLAG} cachetools==5.2.0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
/matching_engine/matching_engine_for_indexing.ipynb @yinghsienwu
|
||||
/matching_engine/stream_update_for_matching_engine.ipynb @peterping666
|
||||
/sdk/pytorch_lightning_custom_container_training.ipynb @brianchunkang
|
||||
/sdk/sdk_pytorch_torchrun_custom_container_training_imagenet.ipynb @brianchunkang
|
||||
/tensorboard @yfang1
|
||||
/feature_store @nayaknishant @morgandu
|
||||
/prediction @googleapis/vertex-prediction-team
|
||||
@@ -29,9 +30,29 @@
|
||||
/notebooks/community/neo4j/graph_paysim.ipynb @benofben @laeg
|
||||
/notebooks/community/ml_ops/stage1/get_started_with_visionapi_and_vertex_datasets.ipynb @mansari
|
||||
/notebooks/community/pipelines/google_cloud_pipeline_components_bqml_pipeline_demand_forecasting.ipynb @inardini
|
||||
/notebooks/community/cohere/cohere_embedding_with_matching_engine.ipynb @stewart-co
|
||||
/notebooks/community/ml_ops/stage2/get_started_vertex_hpt_r_kernel.ipynb @fhirschmann
|
||||
/notebooks/community/ml_ops/stage2/get_started_vertex_training_r_using_r_kernel.ipynb @fhirschmann
|
||||
/notebooks/community/vertex-ai-samples/notebooks/community/model_registry/vertex_ai_model_registry_bqml_custom_model_versioning.ipynb @inardini
|
||||
/notebooks/community/vertex-ai-samples/notebooks/community/model_registry/vertex_ai_model_registry_automl_model_versioning.ipynb @inardini
|
||||
/notebooks/community/vizier/conversions_vertex_vizier_and_open_source_vizier.ipynb @halio-g
|
||||
/notebooks/community/experiments/vertex_ai_model_experimentation.ipynb @inardini @asobran
|
||||
/notebooks/community/experiments/vertex_ai_model_experimentation.ipynb @inardini @asobran
|
||||
/notebooks/community/pipelines/google_cloud_pipeline_components_bqml_pipeline_anomaly_detection.ipynb @inardini
|
||||
/notebooks/community/pipelines/google_cloud_pipeline_components_cloud_natural_language_pipeline.ipynb @Narwhalprime
|
||||
/notebooks/community/pipelines/google_cloud_pipeline_components_ready_to_go_text_classification_pipeline.ipynb @Narwhalprime
|
||||
/notebooks/community/feature_store/get_started_vertex_feature_store.ipynb @junkourata
|
||||
/notebooks/community/model_garden/model_garden_tfvision_image_classification.ipynb @genquan9
|
||||
/notebooks/community/model_garden/model_garden_tfvision_image_object_detection.ipynb @genquan9
|
||||
/notebooks/community/model_garden/model_garden_tfvision_image_segmentation.ipynb @genquan9
|
||||
/notebooks/community/model_garden/model_garden_pytorch_stable_diffusion.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_stable_diffusion_inpainting.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_instructpix2pix.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_controlnet.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_blip_image_captioning.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_blip_vqa.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_vilt_vqa.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_vit_gpt2_image_captioning.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_clip.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_owlvit.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_layoutml_document_qa.ipynb @xiangxu-google
|
||||
/notebooks/community/model_garden/model_garden_pytorch_blip2.ipynb @xiangxu-google
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# README
|
||||
|
||||
These are notebooks [Cohere](https://cohere.ai/) built in collaboration with Google. They demonstrate how to use Cohere's modeling API along with Vertex AI.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2021 Google LLC\n",
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
@@ -24,6 +24,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "JAPoU8Sm5E6e"
|
||||
@@ -32,20 +33,28 @@
|
||||
"<table align=\"left\">\n",
|
||||
"\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/master/notebooks/community/matching_engine/matching_engine_for_indexing.ipynb\">\n",
|
||||
" Run in Google Cloud Notebooks\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/matching_engine/matching_engine_for_indexing.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\">\n",
|
||||
" Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/master/notebooks/community/matching_engine/matching_engine_for_indexing.ipynb\">\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/matching_engine/matching_engine_for_indexing.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/matching_engine/matching_engine_for_indexing.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
" Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" </td> \n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "tvgnzT1CKxrO"
|
||||
@@ -53,25 +62,49 @@
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This example demonstrates how to use the GCP ANN Service. It is a high scale, low latency solution, to find similar vectors (or more specifically \"embeddings\") for a large corpus. Moreover, it is a fully managed offering, further reducing operational overhead. It is built upon [Approximate Nearest Neighbor (ANN) technology](https://ai.googleblog.com/2020/07/announcing-scann-efficient-vector.html) developed by Google Research.\n",
|
||||
"\n",
|
||||
"### Dataset\n",
|
||||
"\n",
|
||||
"The dataset used for this tutorial is the [GloVe dataset](https://nlp.stanford.edu/projects/glove/).\n",
|
||||
"\n",
|
||||
"This example demonstrates how to use Vertex AI Matching Engine. It is a high scale, low latency solution, to find similar vectors (or more specifically \"embeddings\") for a large corpus. Moreover, it is a fully managed offering, further reducing operational overhead. It is built upon [Approximate Nearest Neighbor (ANN) technology](https://ai.googleblog.com/2020/07/announcing-scann-efficient-vector.html) developed by Google Research."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "56e5f9699c6c"
|
||||
},
|
||||
"source": [
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"In this notebook, you will learn how to create Approximate Nearest Neighbor (ANN) Index, query against indexes, and validate the performance of the index. \n",
|
||||
"\n",
|
||||
"The steps performed include:\n",
|
||||
"\n",
|
||||
"* Create ANN Index and Brute Force Index\n",
|
||||
"* Create a Vertex AI Matching Engine Index and Brute Force Index\n",
|
||||
"* Create an IndexEndpoint with VPC Network\n",
|
||||
"* Deploy ANN Index and Brute Force Index\n",
|
||||
"* Perform online query\n",
|
||||
"* Compute recall\n",
|
||||
"\n",
|
||||
"* Deploy a Vertex AI Matching Engine Index and Brute Force Index\n",
|
||||
"* Perform online queries\n",
|
||||
"* Submit batch queries\n",
|
||||
"* Compute recall metric"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0aaef374550b"
|
||||
},
|
||||
"source": [
|
||||
"### Dataset\n",
|
||||
"\n",
|
||||
"The dataset used for this tutorial is the [GloVe dataset](https://nlp.stanford.edu/projects/glove/)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "5e2eba58ad71"
|
||||
},
|
||||
"source": [
|
||||
"### Costs \n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
@@ -87,6 +120,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "S5zc4kbEiYCm"
|
||||
@@ -94,79 +128,47 @@
|
||||
"source": [
|
||||
"## Before you begin\n",
|
||||
"\n",
|
||||
"* **Prepare a VPC network**. To reduce any network overhead that might lead to unnecessary increase in overhead latency, it is best to call the ANN endpoints from your VPC via a direct [VPC Peering](https://cloud.google.com/vertex-ai/docs/general/vpc-peering) connection. The following section describes how to setup a VPC Peering connection if you don't have one. This is a one-time initial setup task. You can also reuse existing VPC network and skip this section.\n",
|
||||
"* **WARNING:** The match service gRPC API (to create online queries against your deployed index) has to be executed in a Google Cloud Notebook instance that is created with the following requirements:\n",
|
||||
" * **In the same region as where your ANN service is deployed** (for example, if you set `REGION = \"us-central1\"` as same as the tutorial, the notebook instance has to be in `us-central1`).\n",
|
||||
" * **Make sure you select the VPC network you created for ANN service** (instead of using the \"default\" one). That is, you will have to create the VPC network below and then create a new notebook instance that uses that VPC. \n",
|
||||
" * If you run it in the colab or a Google Cloud Notebook instance in a different VPC network or region, the gRPC API will fail to peer the network (InactiveRPCError)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "lW2LneA5mmmP"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"PROJECT_ID = \"<your_project_id>\" # @param {type:\"string\"}\n",
|
||||
"NETWORK_NAME = \"ucaip-haystack-vpc-network\" # @param {type:\"string\"}\n",
|
||||
"PEERING_RANGE_NAME = \"ucaip-haystack-range\"\n",
|
||||
"### Set up your Google Cloud project\n",
|
||||
"\n",
|
||||
"# Create a VPC network\n",
|
||||
"! gcloud compute networks create {NETWORK_NAME} --bgp-routing-mode=regional --subnet-mode=auto --project={PROJECT_ID}\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"# Add necessary firewall rules\n",
|
||||
"! gcloud compute firewall-rules create {NETWORK_NAME}-allow-icmp --network {NETWORK_NAME} --priority 65534 --project {PROJECT_ID} --allow icmp\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"! gcloud compute firewall-rules create {NETWORK_NAME}-allow-internal --network {NETWORK_NAME} --priority 65534 --project {PROJECT_ID} --allow all --source-ranges 10.128.0.0/9\n",
|
||||
"2. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"! gcloud compute firewall-rules create {NETWORK_NAME}-allow-rdp --network {NETWORK_NAME} --priority 65534 --project {PROJECT_ID} --allow tcp:3389\n",
|
||||
"3. [Enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com).\n",
|
||||
"\n",
|
||||
"! gcloud compute firewall-rules create {NETWORK_NAME}-allow-ssh --network {NETWORK_NAME} --priority 65534 --project {PROJECT_ID} --allow tcp:22\n",
|
||||
"\n",
|
||||
"# Reserve IP range\n",
|
||||
"! gcloud compute addresses create {PEERING_RANGE_NAME} --global --prefix-length=16 --network={NETWORK_NAME} --purpose=VPC_PEERING --project={PROJECT_ID} --description=\"peering range for uCAIP Haystack.\"\n",
|
||||
"\n",
|
||||
"# Set up peering with service networking\n",
|
||||
"! gcloud services vpc-peerings connect --service=servicenetworking.googleapis.com --network={NETWORK_NAME} --ranges={PEERING_RANGE_NAME} --project={PROJECT_ID}"
|
||||
"4. If you are running this notebook locally, you need to install the [Cloud SDK](https://cloud.google.com/sdk)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d3uj8x73nDX_"
|
||||
},
|
||||
"source": [
|
||||
"* Authentication: `$ gcloud auth login` rerun this in Google Cloud Notebook terminal when you are logged out and need the credential again."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "i7EUnXsZhAGF"
|
||||
"id": "4700b0e39c5d"
|
||||
},
|
||||
"source": [
|
||||
"### Installation\n",
|
||||
"\n",
|
||||
"Download and install the latest (preview) version of the Vertex SDK for Python."
|
||||
"Download and install the latest version of the Vertex AI SDK for Python."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "wyy5Lbnzg5fi"
|
||||
"id": "014470c6a8de"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! pip install -U git+https://github.com/googleapis/python-aiplatform.git@main-test --user"
|
||||
"! pip install -U git+https://github.com/googleapis/python-aiplatform.git@main --user"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "irSMQn6gZ19l"
|
||||
"id": "cf00462144f7"
|
||||
},
|
||||
"source": [
|
||||
"Install the `h5py` to prepare sample dataset, and the `grpcio-tools` for querying against the index. "
|
||||
@@ -176,11 +178,15 @@
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "-h5sqwOEZ5Yq"
|
||||
"id": "3f3e45e5a1d1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! pip install -U grpcio-tools --user\n",
|
||||
"! pip install protobuf==3.20.*\n",
|
||||
"! pip install -U google-api-python-client==1.8.0 --user\n",
|
||||
"! pip install -U grpcio-tools==1.47.0 --user\n",
|
||||
"! pip install -U grpcio==1.47.0 --user\n",
|
||||
"! pip install -U grpcio-status==1.47.0 --user\n",
|
||||
"! pip install -U h5py --user"
|
||||
]
|
||||
},
|
||||
@@ -199,7 +205,7 @@
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "EzrelQZ22IZj"
|
||||
"id": "aa1d87bdc90b"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -215,79 +221,216 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "BF1j6f9HApxa"
|
||||
"id": "249da91c1011"
|
||||
},
|
||||
"source": [
|
||||
"### Set up your Google Cloud project\n",
|
||||
"### Set your project ID\n",
|
||||
"\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager).\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API, and Service Networking API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component,servicenetworking.googleapis.com).\n",
|
||||
"\n",
|
||||
"1. Enter your project ID in the cell below. Then run the cell to make sure the\n",
|
||||
"Cloud SDK uses the right project for all the commands in this notebook.\n",
|
||||
"\n",
|
||||
"**Note**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "WReHDGG5g0XY"
|
||||
},
|
||||
"source": [
|
||||
"#### Set your project ID\n",
|
||||
"\n",
|
||||
"**If you don't know your project ID**, you may be able to get your project ID using `gcloud`."
|
||||
"**If you don't know your project ID**, try the following:\n",
|
||||
"* Run `gcloud config list`.\n",
|
||||
"* Run `gcloud projects list`.\n",
|
||||
"* See the support page: [Locate the project ID](https://support.google.com/googleapi/answer/7014113)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "oM1iC_MfAts1"
|
||||
"id": "10e0d2ee8c45"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"PROJECT_ID = \"\"\n",
|
||||
"\n",
|
||||
"# Get your Google Cloud project ID from gcloud\n",
|
||||
"if not os.getenv(\"IS_TESTING\"):\n",
|
||||
" shell_output=!gcloud config list --format 'value(core.project)' 2>/dev/null\n",
|
||||
" PROJECT_ID = shell_output[0]\n",
|
||||
" print(\"Project ID: \", PROJECT_ID)"
|
||||
"# Set the project id\n",
|
||||
"! gcloud config set project {PROJECT_ID}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "qJYoRfYng0XZ"
|
||||
"id": "3fbfae3ff12a"
|
||||
},
|
||||
"source": [
|
||||
"Otherwise, set your project ID here."
|
||||
"### Set the region\n",
|
||||
"\n",
|
||||
"You can also change the `REGION` variable used by Vertex AI. Learn more about [Vertex AI regions](https://cloud.google.com/vertex-ai/docs/general/locations).\n",
|
||||
"* **WARNING:** \n",
|
||||
" * **Make sure to [choose a region where Vertex AI services are available](https://cloud.google.com/vertex-ai/docs/general/locations#available_regions).**\n",
|
||||
" * **If you use Vertex Workbench, the Notebook instance needs to be in the same region where your Vertex AI Matching Engine is deployed.** (for example, if you set `REGION = \"us-central1\"` as same as the tutorial, the notebook instance has to be in `us-central1`)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "riG_qUokg0XZ"
|
||||
"id": "71c3fd82024e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if PROJECT_ID == \"\" or PROJECT_ID is None:\n",
|
||||
" PROJECT_ID = \"<your_project_id>\" # @param {type:\"string\"}"
|
||||
"REGION = \"us-central1\" # @param {type: \"string\"}\n",
|
||||
"\n",
|
||||
"# Set the regions\n",
|
||||
"! gcloud config set ai_platform/region {REGION}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "60c5a0f69ad8"
|
||||
},
|
||||
"source": [
|
||||
"### Authenticate your Google Cloud account\n",
|
||||
"\n",
|
||||
"Depending on your Jupyter environment, you may have to manually authenticate. Follow the relevant instructions below."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d118c95af93f"
|
||||
},
|
||||
"source": [
|
||||
"**1. Vertex AI Workbench**\n",
|
||||
"* Do nothing as you are already authenticated."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "3035286fcdda"
|
||||
},
|
||||
"source": [
|
||||
"**2. Local JupyterLab instance, uncomment and run:**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "455882ec0f11"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# ! gcloud auth login"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "5097f3233d53"
|
||||
},
|
||||
"source": [
|
||||
"**3. Colab, uncomment and run:**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2b88e46ac2c8"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# from google.colab import auth\n",
|
||||
"# auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "fcdbb8929927"
|
||||
},
|
||||
"source": [
|
||||
"**4. Service account or other**\n",
|
||||
"* See how to grant Cloud Storage permissions to your service account at https://cloud.google.com/storage/docs/gsutil/commands/iam#ch-examples."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "7c6eef70dfdb"
|
||||
},
|
||||
"source": [
|
||||
"### Prepare a VPC network\n",
|
||||
"\n",
|
||||
"To reduce any network overhead that might lead to unnecessary increase in overhead latency, it is best to call the Vertex AI Matching Engine endpoints from your VPC via a direct [VPC Peering](https://cloud.google.com/vertex-ai/docs/general/vpc-peering) connection. The following section describes how to setup a VPC Peering connection if you don't have one. This is a one-time initial setup task. You can also reuse existing VPC network and skip this section.\n",
|
||||
"\n",
|
||||
"* **WARNING:** The match service gRPC API (to create online queries against your deployed index) has to be executed in a Google Cloud Notebook instance that is created with the following requirements:\n",
|
||||
" * **Make sure you select the VPC network you created for Vertex AI Matching Engine service** (instead of using the \"default\" one). That is, you will have to create the VPC network below and then create a new notebook instance that uses that VPC. \n",
|
||||
" * If you run it in the colab or a Google Cloud Notebook instance in a different VPC network or region, the gRPC API will fail to peer the network (InactiveRPCError)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ab38a8cc634c"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"NETWORK_NAME = \"ucaip-haystack-vpc-network\" # @param {type:\"string\"}\n",
|
||||
"PEERING_RANGE_NAME = \"ucaip-haystack-range\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ec6bf3199835"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Create a VPC network\n",
|
||||
"! gcloud compute networks create {NETWORK_NAME} --bgp-routing-mode=regional --subnet-mode=auto --project={PROJECT_ID}\n",
|
||||
"\n",
|
||||
"# Add necessary firewall rules\n",
|
||||
"! gcloud compute firewall-rules create {NETWORK_NAME}-allow-icmp --network {NETWORK_NAME} --priority 65534 --project {PROJECT_ID} --allow icmp\n",
|
||||
"\n",
|
||||
"! gcloud compute firewall-rules create {NETWORK_NAME}-allow-internal --network {NETWORK_NAME} --priority 65534 --project {PROJECT_ID} --allow all --source-ranges 10.128.0.0/9\n",
|
||||
"\n",
|
||||
"! gcloud compute firewall-rules create {NETWORK_NAME}-allow-rdp --network {NETWORK_NAME} --priority 65534 --project {PROJECT_ID} --allow tcp:3389\n",
|
||||
"\n",
|
||||
"! gcloud compute firewall-rules create {NETWORK_NAME}-allow-ssh --network {NETWORK_NAME} --priority 65534 --project {PROJECT_ID} --allow tcp:22\n",
|
||||
"\n",
|
||||
"# Reserve IP range\n",
|
||||
"! gcloud compute addresses create {PEERING_RANGE_NAME} --global --prefix-length=16 --network={NETWORK_NAME} --purpose=VPC_PEERING --project={PROJECT_ID} --description=\"peering range for uCAIP Haystack.\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ddbace09fe81"
|
||||
},
|
||||
"source": [
|
||||
"Create the VPC Peering. If you are running this from Vertex AI Workbench it is possible you might need your notebook's instance service or user account to have the Service Networking Admin Role"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "d329aa3c54d3"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Set up peering with service networking\n",
|
||||
"! gcloud services vpc-peerings connect --service=servicenetworking.googleapis.com --network={NETWORK_NAME} --ranges={PEERING_RANGE_NAME} --project={PROJECT_ID}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "zgPO1eR3CYjk"
|
||||
@@ -297,13 +440,11 @@
|
||||
"\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"Set the name of your Cloud Storage bucket below. It must be unique across all\n",
|
||||
"Create a storage bucket to store intermediate artifacts such as datasets. Set the name of your Cloud Storage bucket below. It must be unique across all\n",
|
||||
"Cloud Storage buckets.\n",
|
||||
"\n",
|
||||
"You may also change the `REGION` variable, which is used for operations\n",
|
||||
"throughout the rest of this notebook. Make sure to [choose a region where Vertex AI services are\n",
|
||||
"available](https://cloud.google.com/vertex-ai/docs/general/locations#available_regions). You may\n",
|
||||
"not use a Multi-Regional Storage bucket for training with Vertex AI."
|
||||
"* **WARNING:** \n",
|
||||
" * **You may not use a Multi-Regional Storage bucket for training with Vertex AI.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -314,8 +455,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"BUCKET_NAME = \"gs://[your-bucket-name]\" # @param {type:\"string\"}\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}"
|
||||
"BUCKET_NAME = \"gs://[your-bucket-name-unique]\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -328,10 +468,14 @@
|
||||
"source": [
|
||||
"from datetime import datetime\n",
|
||||
"\n",
|
||||
"TIMESTAMP = datetime.now().strftime(\"%Y%m%d%H%M%S\")\n",
|
||||
"UUID = datetime.now().strftime(\"%Y%m%d%H%M%S\")\n",
|
||||
"\n",
|
||||
"if BUCKET_NAME == \"\" or BUCKET_NAME is None or BUCKET_NAME == \"gs://[your-bucket-name]\":\n",
|
||||
" BUCKET_NAME = \"gs://\" + PROJECT_ID + \"aip-\" + TIMESTAMP"
|
||||
"if (\n",
|
||||
" BUCKET_NAME == \"\"\n",
|
||||
" or BUCKET_NAME is None\n",
|
||||
" or BUCKET_NAME == \"gs://[your-bucket-name-unique]\"\n",
|
||||
"):\n",
|
||||
" BUCKET_NAME = \"gs://\" + PROJECT_ID + \"aip-\" + UUID"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -351,7 +495,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! gsutil mb -l $REGION $BUCKET_NAME"
|
||||
"! gsutil mb -l $REGION -p $PROJECT_ID $BUCKET_NAME"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -416,10 +560,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"REGION = \"us-central1\"\n",
|
||||
"ENDPOINT = \"{}-aiplatform.googleapis.com\".format(REGION)\n",
|
||||
"NETWORK_NAME = \"ucaip-haystack-vpc-network\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"AUTH_TOKEN = !gcloud auth print-access-token\n",
|
||||
"PROJECT_NUMBER = !gcloud projects list --filter=\"PROJECT_ID:'{PROJECT_ID}'\" --format='value(PROJECT_NUMBER)'\n",
|
||||
@@ -429,10 +570,7 @@
|
||||
"\n",
|
||||
"print(\"ENDPOINT: {}\".format(ENDPOINT))\n",
|
||||
"print(\"PROJECT_ID: {}\".format(PROJECT_ID))\n",
|
||||
"print(\"REGION: {}\".format(REGION))\n",
|
||||
"\n",
|
||||
"!gcloud config set project {PROJECT_ID}\n",
|
||||
"!gcloud config set ai_platform/region {REGION}"
|
||||
"print(\"REGION: {}\".format(REGION))"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -523,12 +661,13 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "QuVl8DrWG8NS"
|
||||
},
|
||||
"source": [
|
||||
"Upload the training data to GCS."
|
||||
"Upload the training data to Google Cloud Storage"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -539,9 +678,9 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# NOTE: Everything in this GCS DIR will be DELETED before uploading the data.\n",
|
||||
"# NOTE: Everything in this Google Cloud Storage directory will be DELETED before uploading the data\n",
|
||||
"\n",
|
||||
"! gsutil rm -rf {BUCKET_NAME}/*"
|
||||
"! gsutil rm -raf {BUCKET_NAME}/** 2> /dev/null || true"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -567,21 +706,23 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "mglUPwHpJH98"
|
||||
},
|
||||
"source": [
|
||||
"## Create Indexes\n"
|
||||
"## Create the indexes\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "qhIBCQ7dDSbW"
|
||||
},
|
||||
"source": [
|
||||
"### Create ANN Index (for Production Usage)"
|
||||
"### Create Vertex AI Matching Engine index (for production usage)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -597,6 +738,16 @@
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "14e1ed031d66"
|
||||
},
|
||||
"source": [
|
||||
"Set constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
@@ -611,14 +762,15 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "svLYiDf0OD2G"
|
||||
},
|
||||
"source": [
|
||||
"Create the ANN index configuration:\n",
|
||||
"#### Create the Vertex AI Matching Engine index configuration\n",
|
||||
"\n",
|
||||
"Please read the documentation to understand the various configuration parameters that can be used to tune the index\n"
|
||||
"Please read the [documentation](https://cloud.google.com/vertex-ai/docs/matching-engine/configuring-indexes) to understand the various configuration parameters that can be used to tune the index"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -656,9 +808,9 @@
|
||||
" }\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"ann_index = {\n",
|
||||
"matching_engine_index = {\n",
|
||||
" \"display_name\": DISPLAY_NAME,\n",
|
||||
" \"description\": \"Glove 100 ANN index\",\n",
|
||||
" \"description\": \"Glove 100 Vertex AI Matching Engine Index\",\n",
|
||||
" \"metadata\": struct_pb2.Value(struct_value=metadata),\n",
|
||||
"}"
|
||||
]
|
||||
@@ -671,7 +823,9 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ann_index = index_client.create_index(parent=PARENT, index=ann_index)"
|
||||
"matching_engine_index = index_client.create_index(\n",
|
||||
" parent=PARENT, index=matching_engine_index\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -686,7 +840,7 @@
|
||||
"# This will take ~45 min.\n",
|
||||
"\n",
|
||||
"while True:\n",
|
||||
" if ann_index.done():\n",
|
||||
" if matching_engine_index.done():\n",
|
||||
" break\n",
|
||||
" print(\"Poll the operation to create index...\")\n",
|
||||
" time.sleep(60)"
|
||||
@@ -700,17 +854,18 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"INDEX_RESOURCE_NAME = ann_index.result().name\n",
|
||||
"INDEX_RESOURCE_NAME = matching_engine_index.result().name\n",
|
||||
"INDEX_RESOURCE_NAME"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "kSsqZuyoA1SG"
|
||||
},
|
||||
"source": [
|
||||
"### Create Brute Force Index (for Ground Truth)\n",
|
||||
"### Create brute force index (for ground truth)\n",
|
||||
"\n",
|
||||
"The brute force index uses a naive brute force method to find the nearest neighbors. This method is not fast or efficient. Hence brute force indices are not recommended for production usage. They are to be used to find the \"ground truth\" set of neighbors, so that the \"ground truth\" set can be used to measure recall of the indices being tuned for production usage. To ensure an apples to apples comparison, the `distanceMeasureType` and `featureNormType`, `dimensions` of the brute force index should match those of the production indices being tuned.\n",
|
||||
"\n",
|
||||
@@ -725,8 +880,6 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.protobuf import *\n",
|
||||
"\n",
|
||||
"algorithmConfig = struct_pb2.Struct(\n",
|
||||
" fields={\"bruteForceConfig\": struct_pb2.Value(struct_value=struct_pb2.Struct())}\n",
|
||||
")\n",
|
||||
@@ -796,12 +949,13 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "mglUPwHpJH98"
|
||||
},
|
||||
"source": [
|
||||
"## Update Indexes\n",
|
||||
"## Update the indexes\n",
|
||||
"\n",
|
||||
"Create incremental data file.\n"
|
||||
]
|
||||
@@ -863,10 +1017,10 @@
|
||||
" }\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"ann_index = {\n",
|
||||
"matching_engine_index = {\n",
|
||||
" \"name\": INDEX_RESOURCE_NAME,\n",
|
||||
" \"display_name\": DISPLAY_NAME,\n",
|
||||
" \"description\": \"Glove 100 ANN index\",\n",
|
||||
" \"description\": \"Glove 100 Vertex AI Matching Engine Index\",\n",
|
||||
" \"metadata\": struct_pb2.Value(struct_value=metadata),\n",
|
||||
"}"
|
||||
]
|
||||
@@ -879,7 +1033,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ann_index = index_client.update_index(index=ann_index)"
|
||||
"matching_engine_index = index_client.update_index(index=matching_engine_index)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -894,7 +1048,7 @@
|
||||
"# This will take ~45 min.\n",
|
||||
"\n",
|
||||
"while True:\n",
|
||||
" if ann_index.done():\n",
|
||||
" if matching_engine_index.done():\n",
|
||||
" break\n",
|
||||
" print(\"Poll the operation to update index...\")\n",
|
||||
" time.sleep(60)"
|
||||
@@ -908,17 +1062,18 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"INDEX_RESOURCE_NAME = ann_index.result().name\n",
|
||||
"INDEX_RESOURCE_NAME = matching_engine_index.result().name\n",
|
||||
"INDEX_RESOURCE_NAME"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "qV2xjAnDDObD"
|
||||
},
|
||||
"source": [
|
||||
"## Create an IndexEndpoint with VPC Network"
|
||||
"## Create an index endpoint with VPC network"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -997,21 +1152,23 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "np2cgVuuIe9k"
|
||||
},
|
||||
"source": [
|
||||
"## Deploy Indexes"
|
||||
"## Deploy the indexes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8Ew1UgcIIiJG"
|
||||
},
|
||||
"source": [
|
||||
"### Deploy ANN Index"
|
||||
"### Deploy a Vertex AI Matching Engine index"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1022,7 +1179,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"DEPLOYED_INDEX_ID = \"ann_glove_deployed\""
|
||||
"DEPLOYED_INDEX_ID = \"matching_engine_glove_deployed\""
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1033,13 +1190,23 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"deploy_ann_index = {\n",
|
||||
"deploy_matching_engine_index = {\n",
|
||||
" \"id\": DEPLOYED_INDEX_ID,\n",
|
||||
" \"display_name\": DEPLOYED_INDEX_ID,\n",
|
||||
" \"index\": INDEX_RESOURCE_NAME,\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "cb6d956d7419"
|
||||
},
|
||||
"source": [
|
||||
"If errors occur with the next command wait some minutes for the index endpoint to be created and retry."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
@@ -1049,7 +1216,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"r = index_endpoint_client.deploy_index(\n",
|
||||
" index_endpoint=INDEX_ENDPOINT_NAME, deployed_index=deploy_ann_index\n",
|
||||
" index_endpoint=INDEX_ENDPOINT_NAME, deployed_index=deploy_matching_engine_index\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
@@ -1082,12 +1249,13 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "RNZnXmO5AhDO"
|
||||
},
|
||||
"source": [
|
||||
"### Deploy Brute Force Index"
|
||||
"### Deploy brute force index"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1158,12 +1326,13 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6LCGvBNvBd8D"
|
||||
},
|
||||
"source": [
|
||||
"## Create Online Queries\n",
|
||||
"## Create online queries\n",
|
||||
"\n",
|
||||
"After you built your indexes, you may query against the deployed index through the online querying gRPC API (Match service) within the virtual machine instances from the same region (for example 'us-central1' in this tutorial). \n",
|
||||
"\n",
|
||||
@@ -1178,7 +1347,15 @@
|
||||
"\n",
|
||||
"* Compile the protocal buffer (see below)\n",
|
||||
"* Obtain the index endpoint\n",
|
||||
"* Use a code-generated stub to make the call, passing the parameter values"
|
||||
"* Use a code-generated stub to make the call, passing the parameter values\n",
|
||||
"\n",
|
||||
"### Troubleshooting connectivity issues\n",
|
||||
"\n",
|
||||
"In case you have connectivity errors please perform the following:\n",
|
||||
"\n",
|
||||
"* Verify that the index endpoint, index, and VPC are all in the same Google Cloud project\n",
|
||||
"* Verify that the index endpoint, index, and VPC are all in the same region and it is a valid (e.g. us-central1)\n",
|
||||
"* Verify the Network does not have a firewall rule which denies all egress connections. Else, disable this rule or overwrite it with another rule that allows connection to the index endpoint IP"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1351,12 +1528,13 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8wXTSgz1Bl0x"
|
||||
},
|
||||
"source": [
|
||||
"Obtain the Private Endpoint: "
|
||||
"Obtain the private endpoint: "
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1521,12 +1699,13 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "_mNwdU9_B_Ez"
|
||||
},
|
||||
"source": [
|
||||
"### Batch Query\n",
|
||||
"## Submit a batch query\n",
|
||||
"\n",
|
||||
"You can run multiple queries in a single RPC call using the BatchMatch API:"
|
||||
]
|
||||
@@ -1764,18 +1943,20 @@
|
||||
"]\n",
|
||||
"\n",
|
||||
"batch_request = match_service_pb2.BatchMatchRequest()\n",
|
||||
"batch_request_ann = match_service_pb2.BatchMatchRequest.BatchMatchRequestPerIndex()\n",
|
||||
"batch_request_matching_engine = (\n",
|
||||
" match_service_pb2.BatchMatchRequest.BatchMatchRequestPerIndex()\n",
|
||||
")\n",
|
||||
"batch_request_brute_force = (\n",
|
||||
" match_service_pb2.BatchMatchRequest.BatchMatchRequestPerIndex()\n",
|
||||
")\n",
|
||||
"batch_request_ann.deployed_index_id = DEPLOYED_INDEX_ID\n",
|
||||
"batch_request_matching_engine.deployed_index_id = DEPLOYED_INDEX_ID\n",
|
||||
"batch_request_brute_force.deployed_index_id = DEPLOYED_BRUTE_FORCE_INDEX_ID\n",
|
||||
"for query in queries:\n",
|
||||
" batch_request_ann.requests.append(get_request(query, DEPLOYED_INDEX_ID))\n",
|
||||
" batch_request_matching_engine.requests.append(get_request(query, DEPLOYED_INDEX_ID))\n",
|
||||
" batch_request_brute_force.requests.append(\n",
|
||||
" get_request(query, DEPLOYED_BRUTE_FORCE_INDEX_ID)\n",
|
||||
" )\n",
|
||||
"batch_request.requests.append(batch_request_ann)\n",
|
||||
"batch_request.requests.append(batch_request_matching_engine)\n",
|
||||
"batch_request.requests.append(batch_request_brute_force)\n",
|
||||
"\n",
|
||||
"response = stub.BatchMatch(batch_request)\n",
|
||||
@@ -1783,14 +1964,15 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "_mNwdU9_B_Ez"
|
||||
},
|
||||
"source": [
|
||||
"### Compute Recall\n",
|
||||
"### Compute the recall metric\n",
|
||||
"\n",
|
||||
"Use deployed brute force Index as the ground truth to calculate the recall of ANN Index:"
|
||||
"Use the deployed brute force index as the ground truth to calculate the recall of the Vertex AI Matching Engine index:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1835,6 +2017,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "TpV-iwP9qw9c"
|
||||
@@ -1844,7 +2027,18 @@
|
||||
"\n",
|
||||
"To clean up all Google Cloud resources used in this project, you can [delete the Google Cloud\n",
|
||||
"project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#shutting_down_projects) you used for the tutorial.\n",
|
||||
"You can also manually delete resources that you created by running the following code."
|
||||
"\n",
|
||||
"Otherwise, you can delete the individual resources you created in this tutorial:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "390c331dc7d9"
|
||||
},
|
||||
"source": [
|
||||
"### Delete the Vertex AI Matching Engine resources"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1869,6 +2063,31 @@
|
||||
"source": [
|
||||
"index_endpoint_client.delete_index_endpoint(name=INDEX_ENDPOINT_NAME)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ff14a85c85fb"
|
||||
},
|
||||
"source": [
|
||||
"### Delete the Google Cloud Storage bucket"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "68d4781faac4"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"delete_bucket = False\n",
|
||||
"if delete_bucket or os.getenv(\"IS_TESTING\"):\n",
|
||||
" ! gsutil -m rm -r $BUCKET_NAME"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/master/notebooks/community/matching_engine/stream_update_matching_engine.ipynb\">\n",
|
||||
" Run in Google Cloud Notebooks\n",
|
||||
" Run in Workbench AI Notebooks\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
@@ -53,7 +53,7 @@
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This example demonstrates how to use the GCP matching engine Stream Update Service. \n",
|
||||
"This example demonstrates how to use the Vertex AI Matching Engine Stream Update Service. \n",
|
||||
"\n",
|
||||
"### Dataset\n",
|
||||
"\n",
|
||||
@@ -150,7 +150,7 @@
|
||||
"source": [
|
||||
"### Installation\n",
|
||||
"\n",
|
||||
"Download and install the latest (preview) version of the Vertex SDK for Python."
|
||||
"Download and install the latest (preview) version of the Vertex AI SDK for Python."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -442,7 +442,7 @@
|
||||
"id": "8292bcedab58"
|
||||
},
|
||||
"source": [
|
||||
"## Prepare the Data\n",
|
||||
"## Prepare the data\n",
|
||||
"\n",
|
||||
"The GloVe dataset consists of a set of pre-trained embeddings. The embeddings are split into a \"train\" split, and a \"test\" split.\n",
|
||||
"We will create a vector search index from the \"train\" split, and use the embedding vectors in the \"test\" split as query vectors to test the vector search index.\n",
|
||||
@@ -525,7 +525,7 @@
|
||||
" f.write('{\"id\":\"' + str(i) + '\",')\n",
|
||||
" f.write('\"embedding\":[' + \",\".join(str(x) for x in train[i]) + \"],\")\n",
|
||||
" f.write(\n",
|
||||
" '\"restricts\":[{\"namespace\": \"class\", \"allow_list\": [\"' + str(i) + '\"]}],'\n",
|
||||
" '\"restricts\":[{\"namespace\": \"class\", \"allow\": [\"' + str(i) + '\"]}],'\n",
|
||||
" )\n",
|
||||
" f.write('\"crowding_tag\":' + ('\"a\"' if i % 2 == 0 else '\"b\"') + \"}\")\n",
|
||||
" f.write(\"\\n\")\n",
|
||||
@@ -854,7 +854,7 @@
|
||||
"id": "00c606bc97b5"
|
||||
},
|
||||
"source": [
|
||||
"## Create Online Queries\n",
|
||||
"## Create online queries\n",
|
||||
"\n",
|
||||
"After you built your indexes, you may query against the deployed index through the online querying gRPC API (Match service) within the virtual machine instances from the same region (for example 'us-central1' in this tutorial). \n",
|
||||
"\n",
|
||||
|
||||
@@ -28,9 +28,11 @@ The first stage in MLOps is the collection and preparation for the purpose of de
|
||||
|
||||
### Get Started
|
||||
|
||||
[Get started with Dataflow](community/ml_ops/stage1/get_started_dataflow.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Dataflow` for training with `Vertex AI`.
|
||||
[Get started with Dataflow](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage1/get_started_dataflow.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Dataflow` for training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -40,10 +42,13 @@ The steps performed include:
|
||||
- Upstream preprocessing of data:
|
||||
- tabular data
|
||||
- image data
|
||||
```
|
||||
|
||||
[Get started with Vertex AI datasets](community/ml_ops/stage1/get_started_vertex_datasets.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Dataset` for training with `Vertex AI`.
|
||||
[Get started with Vertex AI datasets](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage1/get_started_vertex_datasets.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Dataset` for training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -61,10 +66,13 @@ The steps performed include:
|
||||
- Detect anomalies in new data using TensorFlow Data Validation.
|
||||
- Generate a TFRecord feature specification using TensorFlow Transform from the data schema.
|
||||
- Export a dataset and convert to TFRecords.
|
||||
```
|
||||
|
||||
[Get started with BigQuery datasets](community/ml_ops/stage1/get_started_bq_datasets.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `BigQuery` as a dataset for training with `Vertex AI`.
|
||||
[Get started with BigQuery datasets](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage1/get_started_bq_datasets.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `BigQuery` as a dataset for training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -75,10 +83,13 @@ The steps performed include:
|
||||
- Select rows from extracted CSV files into a `tf.data.Dataset` -- compatible for custom training `TensorFlow` models.
|
||||
- Create a `BigQuery` dataset from CSV files.
|
||||
- Extract data from `BigQuery` table into a `DMatrix` -- compatible for custom training `XGBoost` models.
|
||||
```
|
||||
|
||||
[Get started with Vertex AI Data Labeling](community/ml_ops/stage1/get_started_with_data_labeling.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use the `Vertex AI Data Labeling` service.
|
||||
[Get started with Vertex AI Data Labeling](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage1/get_started_with_data_labeling.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use the `Vertex AI Data Labeling` service/
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -87,28 +98,31 @@ The steps performed include:
|
||||
- Submit the data labeling job.
|
||||
- List data labeling jobs.
|
||||
- Cancel a data labeling job.
|
||||
```
|
||||
|
||||
|
||||
[Create an unlabelled Vertex AI AutoML text entity extraction dataset from PDFs using Vision API](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage1/get_started_with_visionapi_and_vertex_datasets.ipynb)
|
||||
|
||||
[Create an unlabelled Vertex AI AutoML text entity extraction dataset from PDFs using Vision API](community/ml_ops/stage1/get_started_with_visionapi_and_vertex_datasets.ipynb)
|
||||
|
||||
In this tutorial, you learn to use `Vision API` to extract text from PDF files stored on a Cloud Storage bucket. You then process the results and create an unlabelled `Vertex AI Dataset`, compatible with `AutoML`, for text entity extraction.
|
||||
```
|
||||
Learn to use `Vision API` to extract text from PDF files stored on a Cloud Storage bucket.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
1. Using `Vision API` to perform Optical Character Recognition (OCR) to extract text from PDF files.
|
||||
2. Processing the results and saving them to text files.
|
||||
3. Generating a `Vertex AI Dataset` import file.
|
||||
4. Creating a new unlabelled text entity extraction `Vertex AI Dataset` resource in `Vertex AI`.
|
||||
4. Cr
|
||||
|
||||
|
||||
### E2E Stage Example
|
||||
|
||||
[Stage 1: Data Management](mlops_data_management.ipynb)
|
||||
|
||||
[Data management](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage1/mlops_data_management.ipynb)
|
||||
|
||||
```
|
||||
In this tutorial, you create a MLOps stage 1: data management process.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Explore and visualize the data.
|
||||
- Create a Vertex AI `Dataset` resource from `BigQuery` table -- for AutoML training.
|
||||
- Extract a copy of the dataset to a CSV file in Cloud Storage.
|
||||
@@ -117,4 +131,4 @@ The steps performed include:
|
||||
- Generate statistics and data schema using TensorFlow Data Validation from the samples in the dataframe.
|
||||
- Generate a TFRecord feature specification using TensorFlow Data Validation from the data schema.
|
||||
- Preprocess a portion of the BigQuery data using `Dataflow` -- for custom training.
|
||||
```
|
||||
```
|
||||
@@ -35,9 +35,10 @@ The second stage in MLOps is experimenting in developing one or more baseline mo
|
||||
|
||||
### Get Started
|
||||
|
||||
[Get started with Vertex AI Training for R](community/ml_ops/stage2/get_started_vertex_training_r.ipynb)
|
||||
[Get started with Vertex AI Training for R](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_training_r.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Training` for training a R custom model.
|
||||
```
|
||||
Learn how to use `Vertex AI Training` for training a R custom model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -51,18 +52,26 @@ The steps performed include:
|
||||
- Create a training image for training the model.
|
||||
- Train a R model using `Vertex AI Trainingh` service with the R-to-Python training package.
|
||||
|
||||
[Get started with Logging](community/ml_ops/stage2/get_started_with_logging.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use Python and Cloud logging awhen training with `Vertex AI`.
|
||||
|
||||
[Get started with Logging](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_with_logging.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use Python and Cloud logging when training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Use Python logging to log training configuration/results locally.
|
||||
- Use Google Cloud Logging to log training configuration/results in cloud storage.
|
||||
|
||||
[Get started with Vertex AI Hyperparameter Tuning for XGBoost] (community/ml_ops/stage2/get_started_vertex_hpt_xgboost.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Hyperparameter Tuning` for training a XGBoost custom model.
|
||||
|
||||
[Get started with Vertex AI Hyperparameter Tuning for XGBoost](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_hpt_xgboost.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Hyperparameter Tuning` for training a XGBoost custom model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -71,9 +80,13 @@ The steps performed include:
|
||||
- Save the model artifacts to Cloud Storage using GCSFuse.
|
||||
- Create a `Vertex AI Model` resource.
|
||||
|
||||
[Get started with Vertex AI Training for XGBoost](community/ml_ops/stage2/get_started_vertex_training_xgboost.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Training` for training a XGBoost custom model.
|
||||
|
||||
[Get started with Vertex AI Training for XGBoost](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_training_xgboost.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Training` for training a XGBoost custom model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -82,9 +95,13 @@ The steps performed include:
|
||||
- Save the model artifacts to Cloud Storage using GCSFuse.
|
||||
- Create a `Vertex AI Model` resource.
|
||||
|
||||
[Get started with TabNet builtin algorithm for training tabular models](community/ml_ops/stage2/get_started_with_tabnet.ipynb)
|
||||
```
|
||||
|
||||
In this notebook, you learn how to run `Vertex AI TabNet` built algorithm for training custom tabular models.
|
||||
|
||||
[Get started with TabNet builtin algorithm for training tabular models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_with_tabnet.ipynb)
|
||||
|
||||
```
|
||||
Learn how to run `Vertex AI TabNet` built algorithm for training custom tabular models.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -97,9 +114,13 @@ The steps performed include:
|
||||
- Hyperparameter tuning the `Vertex AI TabNet` model.
|
||||
- Train the model using `Vertex AI Training` using BigQuery table.
|
||||
|
||||
[Get started with prebuilt TFHub models](community/ml_ops/stage2/get_started_with_tfhub_models.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Training` with prebuilt models from TensorFlow Hub.
|
||||
|
||||
[Get started with prebuilt TFHub models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_with_tfhub_models.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Training` with prebuilt models from TensorFlow Hub.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -112,23 +133,31 @@ The steps performed include:
|
||||
- Train then model
|
||||
- Save model artifacts and upload as Vertex AI Model resource.
|
||||
|
||||
[Get started with BigQuery ML Training](community/ml_ops/stage2/get_started_bqml_training.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `BigQueryML` (BQML) for training with `Vertex AI`.
|
||||
|
||||
[Get started with BigQuery ML Training](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_bqml_training.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `BigQueryML` for training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Create a local BigQuery table in your project
|
||||
- Train a BQML model
|
||||
- Evaluate the BQML model
|
||||
- Export the BQML model as a cloud model
|
||||
- Train a BigQuery ML model
|
||||
- Evaluate the BigQuery ML model
|
||||
- Export the BigQuery ML model as a cloud model
|
||||
- Upload the exported model as a `Vertex AI Model` resource
|
||||
- Hyperparameter tune a BQML model with `Vertex AI Vizier`
|
||||
- Automatically register a BQML model to `Vertex AI Model Registry`
|
||||
- Hyperparameter tune a BigQuery ML model with `Vertex AI Vizier`
|
||||
- Automatically register a BigQuery ML model to `Vertex AI Model Registry`
|
||||
|
||||
[Get started with Vertex AI Vizier](community/ml_ops/stage2/get_started_vertex_vizier.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Vizier` for when training with `Vertex AI`.
|
||||
|
||||
[Get started with Vertex AI Vizier](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_vizier.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Vizier` for when training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -136,9 +165,13 @@ The steps performed include:
|
||||
- Hyperparameter tuning with Vizier (Bayesian) algorithm.
|
||||
- Suggesting trials and updating results for Vizier study
|
||||
|
||||
[Get started with distributed training using DASK](community/ml_ops/stage2/get_started_with_distributed_training_xgboost.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Training` for distributed training of XGBoost model using the OSS package DASK. Additionally, you learn to construct and deploy a custom serving container using a Flask web server.
|
||||
|
||||
[Get started with distributed training using DASK](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_with_distributed_training_xgboost.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Training` for distributed training of XGBoost model using the OSS package DASK.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -152,9 +185,13 @@ The steps performed include:
|
||||
- Deploy the `Vertex AI Model` resource to `Vertex AI Endpoint` resource.
|
||||
- Make a prediction.
|
||||
|
||||
[Get started with Vertex AI TensorBoard](community/ml_ops/stage2/get_started_vertex_tensorboard.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI TensorBoard` when training with `Vertex AI`.
|
||||
|
||||
[Get started with Vertex AI TensorBoard](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_tensorboard.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI TensorBoard` when training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -162,9 +199,13 @@ The steps performed include:
|
||||
- Using TensorBoard with locally trained model.
|
||||
- Using Vertex AI TensorBoard with Vertex AI Training.
|
||||
|
||||
[Get started with Vertex AI Training for R using R Kernel](community/ml_ops/stage2/get_started_vertex_training_r_using_r_kernel.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI`, using an R kernel, for training and deploying an R custom model.
|
||||
|
||||
[Get started with Vertex AI Training for R using R Kernel](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_training_r_using_r_kernel.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI`, using an R kernel, for training and deploying an R custom model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -176,10 +217,13 @@ The steps performed include:
|
||||
- Deploy the `Model` resource (trained R model) to the `Endpoint` resource.
|
||||
- Make an online prediction.
|
||||
|
||||
```
|
||||
|
||||
[Get started Vision API test preprocessing and AutoML text model generation](community/ml_ops/stage2/get_started_with_visionapi_and_automl.ipynb)
|
||||
|
||||
In this tutorial, you create an `AutoML` text entity extraction model pre-existing extracted data by generating a custom import file. You deploy this mode for online prediction from a Python script using the `BigQuery`, `Vision AI`, Cloud Storage and `Vertex AI SDK` for Python.
|
||||
[Get started Vision API test preprocessing and AutoML text model generation](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_with_visionapi_and_automl.ipynb)
|
||||
|
||||
```
|
||||
In this tutorial, you create an `AutoML` text entity extraction model pre-existing extracted data by generating a custom import file.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -192,9 +236,13 @@ The steps performed include:
|
||||
- Make a prediction.
|
||||
- Undeploy the `Model`.
|
||||
|
||||
[Get started with Vertex AI Experiments](community/ml_ops/stage2/get_started_vertex_experiments.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Experiments` when training with `Vertex AI`.
|
||||
|
||||
[Get started with Vertex AI Experiments](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_experiments.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Experiments` when training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -215,9 +263,13 @@ The steps performed include:
|
||||
- Execute the custom job
|
||||
- Visualize the experiment results
|
||||
|
||||
[AutoML Image Classfication Training with Customer Managed Encryption Keys (CMEK)](community/ml_ops/stage2/get_started_with_cmek_training.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use a customer managed encryption key (CMEK) for `Vertex AI AutoML` training.
|
||||
|
||||
[AutoML Image Classfication Training with Customer Managed Encryption Keys (CMEK)](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_with_cmek_training.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use a customer managed encryption key (CMEK) for `Vertex AI AutoML` training.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -225,9 +277,13 @@ The steps performed include:
|
||||
- Creating an image dataset with CMEK encryption.
|
||||
- Train an AutoML model with CMEK encryption.
|
||||
|
||||
[Get started with Vertex AI Feature Store](community/ml_ops/stage2/get_started_vertex_feature_store.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Feature Store` when training and predicting with `Vertex AI`.
|
||||
|
||||
[Get started with Vertex AI Feature Store](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_feature_store.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Feature Store` when training and predicting with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -240,9 +296,13 @@ The steps performed include:
|
||||
- Perform online serving from a `Featurestore` resource.
|
||||
- Perform batch serving from a `Featurestore` resource.
|
||||
|
||||
[Get started with AutoML Training](community/ml_ops/stage2/get_started_automl_training.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `AutoML` for training with `Vertex AI`.
|
||||
|
||||
[Get started with AutoML Training](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_automl_training.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `AutoML` for training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -253,9 +313,29 @@ The steps performed include:
|
||||
- Train a text model
|
||||
- Train a video model
|
||||
|
||||
[Get started with Vertex AI Training for LightGBM](community/ml_ops/stage2/get_started_vertex_training_lightgbm.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Training` for training a LightGBM custom model.
|
||||
|
||||
[Get started with autologging using Vertex AI Experiments for XGBoost models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_with_vertex_experiments_autologging_xgboost.ipynb)
|
||||
|
||||
```
|
||||
Learn how to create an experiment for training an XGBoost model, and automatically log parameters and metrics using the enclosed do-it-yourself (DIY) code.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Construct the DIY autologging code.
|
||||
- Construct training package with call to autologging.
|
||||
- Train a model.
|
||||
- View the experiment
|
||||
- Delete the experiment.
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Get started with Vertex AI Training for LightGBM](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_training_lightgbm.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Training` for training a LightGBM custom model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -266,9 +346,26 @@ The steps performed include:
|
||||
- Test the deployment image locally.
|
||||
- Create a `Vertex AI Model` resource.
|
||||
|
||||
[Get started with Vertex AI Training for Scikit-Learn](community/ml_ops/stage2/get_started_vertex_training_sklearn.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Training` for training a Scikit-Learn custom model.
|
||||
|
||||
[Vertex AI Hyperparameter Tuning with R kernel](None)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI`, using an R kernel, for tuning hyperparameters of a R custom model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Create a custom R training script
|
||||
- Create a custom R deployment container.
|
||||
- Perform hyperparameter tuning using `Vertex AI`.
|
||||
|
||||
```
|
||||
|
||||
[Get started with Vertex AI Training for Scikit-Learn](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_training_sklearn.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Training` for training a Scikit-Learn custom model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -277,9 +374,13 @@ The steps performed include:
|
||||
- Save the model artifacts to Cloud Storage using GCSFuse.
|
||||
- Create a `Vertex AI Model` resource.
|
||||
|
||||
[Get started with Vertex AI Training](community/ml_ops/stage2/get_started_vertex_training.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Training` for custom models when training with `Vertex AI`.
|
||||
|
||||
[Get started with Vertex AI Training](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_training.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Training` for custom models when training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -288,10 +389,13 @@ The steps performed include:
|
||||
- Training using a custom training image.
|
||||
- Laying out a training package.
|
||||
|
||||
```
|
||||
|
||||
[Get started with Vertex AI Training for Pytorch](community/ml_ops/stage2/get_started_vertex_training_pytorch.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Training` for training a Pytorch custom model.
|
||||
[Get started with Vertex AI Training for PyTorch](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_training_pytorch.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Training` for training a PyTorch custom model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -300,9 +404,31 @@ The steps performed include:
|
||||
- Save the model artifacts to Cloud Storage using GCSFuse.
|
||||
- Create a `Vertex AI Model` resource.
|
||||
|
||||
[Get started with Vertex AI Distributed Training](community/ml_ops/stage2/get_started_vertex_distributed_training.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Distributed Training` for when training with `Vertex AI`.
|
||||
|
||||
[Get started with autologging using Vertex AI Experiments for TensorFlow models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_with_vertex_experiments_autologging_tf.ipynb)
|
||||
|
||||
```
|
||||
Learn how to create an experiment for training a TensorFlow model, and automatically log parameters and metrics using the enclosed do-it-yourself (DIY) code.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Construct the DIY autologging code.
|
||||
- Construct training package for TensorFlow Sequential model with call to autologging.
|
||||
- Train a model.
|
||||
- View the experiment
|
||||
- Construct training package for TensorFlow Functional model with call to autologging.
|
||||
- Compare the experiment runs.
|
||||
- Delete the experiment.
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Get started with Vertex AI Distributed Training](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/get_started_vertex_distributed_training.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Distributed Training` for when training with `Vertex AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -312,12 +438,17 @@ The steps performed include:
|
||||
- `ReductionServer`: Train on multiple VMS and sync updates across VMS with `Vertex AI Reduction Server`.
|
||||
- `TPUTraining`: Train with multiple Cloud TPUs.
|
||||
|
||||
```
|
||||
|
||||
### E2E Stage Example
|
||||
|
||||
[Stage 2: Experimentation](mlops_experimentation.ipynb)
|
||||
[Experimentation](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage2/mlops_experimentation.ipynb)
|
||||
|
||||
```
|
||||
In this tutorial, you create a MLOps stage 2: experimentation process.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Review the `Dataset` resource created during stage 1.
|
||||
- Train an AutoML tabular binary classifier model in the background.
|
||||
- Build the experimental model architecture.
|
||||
@@ -334,4 +465,5 @@ The steps performed include:
|
||||
- Set the evaluation results of the AutoML model as the baseline.
|
||||
- If the evaluation of the custom model is below baseline, continue to experiment with the custom model.
|
||||
- If the evaluation of the custom model is above baseline, save the model as the first best model.
|
||||
|
||||
```
|
||||
|
||||
@@ -34,9 +34,10 @@ The third stage in MLOps is formalization to develop an automated pipeline proce
|
||||
### Get Started
|
||||
|
||||
|
||||
[Get started with Vertex AI Model Registry](community/ml_ops/stage3/get_started_with_model_registry.ipynb)
|
||||
[Get started with Vertex AI Model Registry](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_model_registry.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Model Registry` to create and register multiple versions of a model.
|
||||
```
|
||||
Learn how to use `Vertex AI Model Registry` to create and register multiple versions of a model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -46,9 +47,13 @@ The steps performed include:
|
||||
- Deleting a model version.
|
||||
- Retraining the next model version.
|
||||
|
||||
[Get started with Dataflow pipeline components](community/ml_ops/stage3/get_started_with_dataflow_pipeline_components.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `Dataflow`.
|
||||
|
||||
[Get started with Dataflow pipeline components](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_dataflow_pipeline_components.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use prebuilt `Google Cloud Pipeline Components` for `Dataflow`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -56,9 +61,13 @@ The steps performed include:
|
||||
- Encapsulate the Apache Beam data pipeline with a Dataflow component in a Vertex AI pipeline.
|
||||
- Execute a Vertex AI pipeline.
|
||||
|
||||
[Get started with Apache Airflow and Vertex AI Pipelines](community/ml_ops/stage3/get_started_with_airflow_and_vertex_pipelines.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use Apache Airflow with `Vertex AI Pipelines`.
|
||||
|
||||
[Get started with Apache Airflow and Vertex AI Pipelines](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_airflow_and_vertex_pipelines.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use Apache Airflow with `Vertex AI Pipelines`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -67,9 +76,13 @@ The steps performed include:
|
||||
- Create a `Vertex AI Pipeline` that triggers the Airflow DAG.
|
||||
- Execute the `Vertex AI Pipeline`.
|
||||
|
||||
[Get started with Kubeflow Pipelines](community/ml_ops/stage3/get_started_with_kubeflow_pipelines.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Kubeflow Pipelines`(KFP).
|
||||
|
||||
[Get started with Kubeflow Pipelines](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_kubeflow_pipelines.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Kubeflow Pipelines`(KFP).
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -80,9 +93,13 @@ The steps performed include:
|
||||
- Building sequential, parallel, multiple output components.
|
||||
- Building control flow into pipelines.
|
||||
|
||||
[Get started with Vertex AI custom training pipeline components](community/ml_ops/stage3/get_started_with_custom_training_pipeline_components.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `Vertex AI Training`.
|
||||
|
||||
[Get started with Vertex AI custom training pipeline components](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_custom_training_pipeline_components.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use prebuilt `Google Cloud Pipeline Components` for `Vertex AI Training`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -98,11 +115,13 @@ The steps performed include:
|
||||
- Deploying a Vertex AI custom trained model.
|
||||
- Execute a Vertex AI pipeline.
|
||||
|
||||
[Get started with Dataproc Serverless pipeline components](community/ml_ops/stage3/get_started_with_dataproc_serverless_pipeline_components.ipynb)
|
||||
```
|
||||
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `Dataproc Serverless` service.
|
||||
[Get started with Dataproc Serverless pipeline components](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_dataproc_serverless_pipeline_components.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use prebuilt `Google Cloud Pipeline Components` for `Dataproc Serverless` service.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -111,9 +130,13 @@ The steps performed include:
|
||||
- `DataprocSparkSqlBatchOp` for running Spark SQL batch workloads.
|
||||
- `DataprocSparkRBatchOp` for running SparkR batch workloads.
|
||||
|
||||
[Get started with Vertex AI Hyperparameter Tuning pipeline components](community/ml_ops/stage3/get_started_with_hpt_pipeline_components.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `Vertex AI Hyperparameter Tuning`.
|
||||
|
||||
[Get started with Vertex AI Hyperparameter Tuning pipeline components](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_hpt_pipeline_components.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use prebuilt `Google Cloud Pipeline Components` for `Vertex AI Hyperparameter Tuning`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -125,23 +148,28 @@ The steps performed include:
|
||||
- Upload the model artifacts to a `Vertex AI Model` resource.
|
||||
- Execute a Vertex AI pipeline.
|
||||
|
||||
[Get started with machine management for Vertex AI Pipelines](community/ml_ops/stage3/get_started_with_machine_management.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you convert a self-contained custom training component into a `Vertex AI CustomJob`, whereby:
|
||||
|
||||
- The training job and artifacts are trackable.
|
||||
- Set machine resources, such as machine-type, cpu/gpu, memory, disk, etc.
|
||||
[Get started with machine management for Vertex AI Pipelines](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_machine_management.ipynb)
|
||||
|
||||
```
|
||||
Learn how to convert a self-contained custom training component into a `Vertex AI CustomJob`, whereby:
|
||||
|
||||
The steps performed in this tutorial include:
|
||||
|
||||
- Create a custom component with a self-contained training job.
|
||||
- Execute pipeline using component-level settings for machine resources
|
||||
- Convert the self-contained training component into a `Vertex AI CustomJob`.
|
||||
- Execute pipeline using customjob-level settings for machine resources
|
||||
- Execute pipeline using customjob-level settings for machine resources
|
||||
|
||||
[Get started with TFX pipelines](community/ml_ops/stage3/get_started_with_tfx_pipeline.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use TensorFlow Extended (TFX) with `Vertex AI Pipelines`.
|
||||
|
||||
[Get started with TFX pipelines](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_tfx_pipeline.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use TensorFlow Extended (TFX) with `Vertex AI Pipelines`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -150,9 +178,28 @@ The steps performed include:
|
||||
- Execute the pipeline on Google Cloud using `Vertex AI Training`
|
||||
- Execute the pipeline using `Vertex AI Pipelines`.
|
||||
|
||||
[Get started with BigQuery ML pipeline components](community/ml_ops/stage3/get_started_with_bqml_pipeline_components.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `BigQuery ML`.
|
||||
|
||||
[Orchestrating a workflow to train and deploy an scikit-learn model using Vertex AI Pipelines with online prediction](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_vertex_pipelines_sklearn_with_prediction.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use prebuilt components in `Vertex AI Pipelines` for training and deploying a scikit-Learn custom model, and then using `Vertex AI Prediction` to make an online prediction.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Construct a scikit-learn training package.
|
||||
- Construct a pipeline to train and deploy a scikit-learn model.
|
||||
- Execute the pipeline.
|
||||
- Make an online prediction.
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Get started with BigQuery ML pipeline components](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_bqml_pipeline_components.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use prebuilt `Google Cloud Pipeline Components` for `BigQuery ML`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -165,9 +212,28 @@ The steps performed include:
|
||||
- Execute a Vertex AI pipeline.
|
||||
- Make a prediction with the deployed Vertex AI model.
|
||||
|
||||
[Get started with AutoML tabular pipeline workflows](community/ml_ops/stage3/get_started_with_automl_tabular_pipeline_workflow.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `AutoML Tabular Pipeline Template` for training, exporting and tuning an AutoML tabular model.
|
||||
|
||||
[Orchestrating a workflow to train and deploy an XGBoost model using Vertex AI Pipelines with Vertex AI Experiments](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_vertex_pipelines_xgboost_with_experiments.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use prebuilt components in `Vertex AI Pipelines` for training and deploying a XGBoost custom model, and using `Vertex AI Experiments` to log the corresponding training parameters and metrics, from within the training package.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Construct a XGBoost training package.
|
||||
- Add tracking the experiment
|
||||
- Construct a pipeline to train and deploy a XGBoost model.
|
||||
- Execute the pipeline.
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Get started with AutoML tabular pipeline workflows](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_automl_tabular_pipeline_workflow.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `AutoML Tabular Pipeline Template` for training, exporting and tuning an AutoML tabular model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -183,9 +249,13 @@ The steps performed include:
|
||||
- Deploy exported OSS TF model.
|
||||
- Make a prediction.
|
||||
|
||||
[Get started with rapid prototyping with AutoML and BigQuery ML](community/ml_ops/stage3/get_started_with_rapid_prototyping_bqml_automl.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Predictions` for rapid prototyping a model.
|
||||
|
||||
[Get started with rapid prototyping with AutoML and BigQuery ML](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_rapid_prototyping_bqml_automl.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Predictions` for rapid prototyping a model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -196,9 +266,13 @@ The steps performed include:
|
||||
- Deploying the best trained model.
|
||||
- Testing the deployed model infrastructure.
|
||||
|
||||
[Get started with AutoML pipeline components](community/ml_ops/stage3/get_started_with_automl_pipeline_components.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `Vertex AI AutoML`.
|
||||
|
||||
[Get started with AutoML pipeline components](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_automl_pipeline_components.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use prebuilt `Google Cloud Pipeline Components` for `Vertex AI AutoML`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -208,10 +282,28 @@ The steps performed include:
|
||||
- Deploying a Vertex AI AutoML trained model.
|
||||
- Execute a Vertex AI pipeline.
|
||||
|
||||
```
|
||||
|
||||
[Get started with BigQuery and TFDV pipeline components](community/ml_ops/stage3/get_started_with_bq_tfdv_pipeline_components.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use build lightweight Python components for BigQuery and TensorFlow Data Validation.
|
||||
[Orchestrating a workflow to train and deploy an XGBoost model using Vertex AI Pipelines with online prediction](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_vertex_pipelines_xgboost_with_prediction.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use prebuilt components in `Vertex AI Pipelines` for training and deploying a XGBoost custom model, and then using `Vertex AI Prediction` to make an online prediction.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Construct a XGBoost training package.
|
||||
- Construct a pipeline to train and deploy a XGBoost model.
|
||||
- Execute the pipeline.
|
||||
- Make an online prediction.
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Get started with BigQuery and TFDV pipeline components](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/get_started_with_bq_tfdv_pipeline_components.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use build lightweight Python components for BigQuery and TensorFlow Data Validation.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -219,22 +311,28 @@ The steps performed include:
|
||||
- Build and execute a pipeline component for generating TFDV statistics and schema from a Vertex AI Tabular Dataset.
|
||||
- Execute a Vertex AI pipeline.
|
||||
|
||||
```
|
||||
|
||||
### E2E Stage Example
|
||||
|
||||
[Stage 3: Formalization](mlops_formalization.ipynb)
|
||||
[Formalization](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage3/mlops_formalization.ipynb)
|
||||
|
||||
```
|
||||
In this tutorial, you create a MLOps stage 3: formalization process.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Obtain resources from the experimentation stage.
|
||||
- Baseline model.
|
||||
- Dataset schema/statistics for baseline model.
|
||||
- Formalize a data preprocessing pipeline.
|
||||
- Extract columns/rows from BigQuery table to local BigQuery table.
|
||||
- Use Tensorflow Data Validation library to determine statistics, schema, and features.
|
||||
- Use TensorFlow Data Validation library to determine statistics, schema, and features.
|
||||
- Use Dataflow to preprocess the data.
|
||||
- Create a Vertex AI Dataset.
|
||||
- Formalize a build model architecture pipeline.
|
||||
- Create the Vertex AI Model base model.
|
||||
- Formalize a training pipeline.
|
||||
|
||||
```
|
||||
|
||||
|
||||
+24
@@ -560,6 +560,30 @@
|
||||
" print(\"Service Account:\", SERVICE_ACCOUNT)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "set_service_account:pipelines"
|
||||
},
|
||||
"source": [
|
||||
"#### Set service account access for Vertex AI Pipelines\n",
|
||||
"\n",
|
||||
"Run the following commands to grant your service account access to read and write pipeline artifacts in the bucket that you created in the previous step -- you only need to run these once per service account."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "set_service_account:pipelines"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectCreator $BUCKET_URI\n",
|
||||
"\n",
|
||||
"! gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectViewer $BUCKET_URI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
|
||||
+24
@@ -557,6 +557,30 @@
|
||||
" print(\"Service Account:\", SERVICE_ACCOUNT)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "set_service_account:pipelines"
|
||||
},
|
||||
"source": [
|
||||
"#### Set service account access for Vertex AI Pipelines\n",
|
||||
"\n",
|
||||
"Run the following commands to grant your service account access to read and write pipeline artifacts in the bucket that you created in the previous step -- you only need to run these once per service account."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"id": "set_service_account:pipelines"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectCreator $BUCKET_URI\n",
|
||||
"\n",
|
||||
"! gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectViewer $BUCKET_URI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
|
||||
+24
@@ -557,6 +557,30 @@
|
||||
" print(\"Service Account:\", SERVICE_ACCOUNT)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "set_service_account:pipelines"
|
||||
},
|
||||
"source": [
|
||||
"#### Set service account access for Vertex AI Pipelines\n",
|
||||
"\n",
|
||||
"Run the following commands to grant your service account access to read and write pipeline artifacts in the bucket that you created in the previous step -- you only need to run these once per service account."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"id": "set_service_account:pipelines"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectCreator $BUCKET_URI\n",
|
||||
"\n",
|
||||
"! gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectViewer $BUCKET_URI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
|
||||
@@ -1333,7 +1333,6 @@
|
||||
"Next, you compile the pipeline and then exeute it. The pipeline takes the following parameters, which are passed as the dictionary `parameter_values`:\n",
|
||||
"\n",
|
||||
"- `display_name`: A human readable name for the pipeline job.\n",
|
||||
"- `import_file`: The Cloud Storage location to the dataset.\n",
|
||||
"- `worker_pool_specs`: The the machine and container, and auto-scaling requirements, as well as command line arguments.\n",
|
||||
"- `study_spec_metrics`: The metrics to optimize in the study trials.\n",
|
||||
"- `study_spec_parameters`: The parameters to tune."
|
||||
|
||||
@@ -43,191 +43,104 @@ This stage may be done entirely by MLOps. We recommend:
|
||||
### Get Started
|
||||
|
||||
|
||||
[Get started with Vertex AI Model Registry](community/ml_ops/stage3/get_started_with_model_registry.ipynb)
|
||||
[Get started with Vertex ML Metadata](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage4/get_started_with_vertex_ml_metadata.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Model Registry` to create and register multiple versions of a model.
|
||||
```
|
||||
Learn how to use `Vertex ML Metadata`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Create and register a first version of a model to `Vertex AI Model Registry`.
|
||||
- Create and register a second version of a model to `Vertex AI Model Registry`.
|
||||
- Updating the model version which is the default (blessed).
|
||||
- Deleting a model version.
|
||||
- Retraining the next model version.
|
||||
- Create a `Metadatastore` resource.
|
||||
- Create (record)/List an `Artifact`, with artifacts and metadata.
|
||||
- Create (record)/List an `Execution`.
|
||||
- Create (record)/List a `Context`.
|
||||
- Add `Artifact` to `Execution` as events.
|
||||
- Add `Execution` and `Artifact` into the `Context`
|
||||
- Delete `Artifact`, `Execution` and `Context`.
|
||||
- Create and run a `Vertex AI Pipeline` ML workflow to train and deploy a scikit-learn model.
|
||||
- Create custom pipeline components that generate artifacts and metadata.
|
||||
- Compare Vertex AI Pipelines runs.
|
||||
- Trace the lineage for pipeline-generated artifacts.
|
||||
- Query your pipeline run metadata.
|
||||
|
||||
[Get started with Dataflow pipeline components](community/ml_ops/stage3/get_started_with_dataflow_pipeline_components.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `Dataflow`.
|
||||
|
||||
[Get started with Google Artifact Registry](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage4/get_started_with_google_artifact_registry.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Google Artifact Registry`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Build an Apache Beam data pipeline.
|
||||
- Encapsulate the Apache Beam data pipeline with a Dataflow component in a Vertex AI pipeline.
|
||||
- Execute a Vertex AI pipeline.
|
||||
- Creating a private Docker repository.
|
||||
- Tagging a container image, specific to the private Docker repository.
|
||||
- Pushing a container image to the private Docker repository.
|
||||
- Pulling a container image from the private Docker repository.
|
||||
- Deleting a private Docker repository.
|
||||
|
||||
[Get started with Apache Airflow and Vertex AI Pipelines](community/ml_ops/stage3/get_started_with_airflow_and_vertex_pipelines.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use Apache Airflow with `Vertex AI Pipelines`.
|
||||
|
||||
[Get started with Vertex AI Model Evaluation](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage4/get_started_with_model_evaluation.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Model Evaluation`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Create Cloud Composer environment.
|
||||
- Upload Airflow DAG to Composer environment that performs data processing -- i.e., creates a BigQuery table from a CSV file.
|
||||
- Create a `Vertex AI Pipeline` that triggers the Airflow DAG.
|
||||
- Execute the `Vertex AI Pipeline`.
|
||||
```
|
||||
|
||||
[Get started with Kubeflow Pipelines](community/ml_ops/stage3/get_started_with_kubeflow_pipelines.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Kubeflow Pipelines`(KFP).
|
||||
[Get started with Vertex Explainable AI](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage4/get_started_with_vertex_xai.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Explainable AI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Building KFP lightweight Python function components.
|
||||
- Assembling and compiling KFP components into a pipeline.
|
||||
- Executing a KFP pipeline using Vertex AI Pipelines.
|
||||
- Loading component and pipeline definitions from a source code repository.
|
||||
- Building sequential, parallel, multiple output components.
|
||||
- Building control flow into pipelines.
|
||||
- Train an AutoML tabular model.
|
||||
- Do a batch prediction with explanations.
|
||||
- Do an online prediction with explanations.
|
||||
- Train an custom TensorFlow tabular model.
|
||||
- Manually set configuration metadata.
|
||||
- Do a batch prediction with explanations.
|
||||
- Do an online prediction with explanations.
|
||||
- Automatically set configuration metadata.
|
||||
- Train an custom TensorFlow image model.
|
||||
- Manually set configuration metadata.
|
||||
- Do a batch prediction with explanations.
|
||||
- Do an online prediction with explanations.
|
||||
- Train an custom XGBoost tabular model.
|
||||
- Manually set configuration metadata.
|
||||
- Do an online prediction with explanations.
|
||||
- Train an custom scikit-learn tabular model.
|
||||
- Manually set configuration metadata.
|
||||
- Do an online prediction with explanations.
|
||||
|
||||
[Get started with Vertex AI custom training pipeline components](community/ml_ops/stage3/get_started_with_custom_training_pipeline_components.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `Vertex AI Training`.
|
||||
|
||||
[Get started with AutoML Training and ML Metadata](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage4/get_started_with_vertex_ml_metadata_and_automl.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `AutoML` for training and assemble the corresponding artifact linkage for `Vertex ML Metadata`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Construct a pipeline for:
|
||||
- Training a Vertex AI custom trained model.
|
||||
- Test the serving binary with a batch prediction job.
|
||||
- Deploying a Vertex AI custom trained model.
|
||||
- Execute a Vertex AI pipeline.
|
||||
- Construct a pipeline for:
|
||||
- Construct a custom training component.
|
||||
- Convert custom training component to CustomTrainingJobOp.
|
||||
- Training a Vertex AI custom trained model using the converted component.
|
||||
- Deploying a Vertex AI custom trained model.
|
||||
- Execute a Vertex AI pipeline.
|
||||
- Create a `Dataset` resource.
|
||||
- Create a corresponding `google.VertexDataset` artifact.
|
||||
- Train a model using `AutoML`.
|
||||
- Create a corresponding `google.VertexModel` artifact.
|
||||
- Create an `Endpoint` resource.
|
||||
- Create a corresponding `google.Endpoint` artifact.
|
||||
- Deploy the train model to the `Endpoint`.
|
||||
- Create an execution and context for the `AutoML` training job and deployment.
|
||||
- Add the corresponding artifacts and context to the execution.
|
||||
- Add artifact links (event) to the execution.
|
||||
- Display the execution graph.
|
||||
|
||||
[Get started with Dataproc Serverless pipeline components](community/ml_ops/stage3/get_started_with_dataproc_serverless_pipeline_components.ipynb)
|
||||
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `Dataproc Serverless` service.
|
||||
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- `DataprocPySparkBatchOp` for running PySpark batch workloads.
|
||||
- `DataprocSparkBatchOp` for running Spark batch workloads.
|
||||
- `DataprocSparkSqlBatchOp` for running Spark SQL batch workloads.
|
||||
- `DataprocSparkRBatchOp` for running SparkR batch workloads.
|
||||
|
||||
[Get started with Vertex AI Hyperparameter Tuning pipeline components](community/ml_ops/stage3/get_started_with_hpt_pipeline_components.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `Vertex AI Hyperparameter Tuning`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Construct a pipeline for:
|
||||
- Hyperparameter tune/train a custom model.
|
||||
- Retrieve the tuned hyperparameter values and metrics to optimize.
|
||||
- If the metrics exceed a specified threshold.
|
||||
- Get the location of the model artifacts for the best tuned model.
|
||||
- Upload the model artifacts to a `Vertex AI Model` resource.
|
||||
- Execute a Vertex AI pipeline.
|
||||
|
||||
[Get started with machine management for Vertex AI Pipelines](community/ml_ops/stage3/get_started_with_machine_management.ipynb)
|
||||
|
||||
In this tutorial, you convert a self-contained custom training component into a `Vertex AI CustomJob`, whereby:
|
||||
|
||||
- The training job and artifacts are trackable.
|
||||
- Set machine resources, such as machine-type, cpu/gpu, memory, disk, etc.
|
||||
|
||||
The steps performed in this tutorial include:
|
||||
|
||||
- Create a custom component with a self-contained training job.
|
||||
- Execute pipeline using component-level settings for machine resources
|
||||
- Convert the self-contained training component into a `Vertex AI CustomJob`.
|
||||
- Execute pipeline using customjob-level settings for machine resources
|
||||
|
||||
[Get started with TFX pipelines](community/ml_ops/stage3/get_started_with_tfx_pipeline.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use TensorFlow Extended (TFX) with `Vertex AI Pipelines`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Create a TFX e2e pipeline.
|
||||
- Execute the pipeline locally.
|
||||
- Execute the pipeline on Google Cloud using `Vertex AI Training`
|
||||
- Execute the pipeline using `Vertex AI Pipelines`.
|
||||
|
||||
[Get started with BigQuery ML pipeline components](community/ml_ops/stage3/get_started_with_bqml_pipeline_components.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `BigQuery ML`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Construct a pipeline for:
|
||||
- Training BigQuery ML model.
|
||||
- Evaluating the BigQuery ML model.
|
||||
- Exporting the BigQuery ML model.
|
||||
- Importing the BigQuery ML model to a Vertex AI model.
|
||||
- Deploy the Vertex AI model.
|
||||
- Execute a Vertex AI pipeline.
|
||||
- Make a prediction with the deployed Vertex AI model.
|
||||
|
||||
[Get started with AutoML tabular pipeline workflows](community/ml_ops/stage3/get_started_with_automl_tabular_pipeline_workflow.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `AutoML Tabular Pipeline Template` for training, exporting and tuning an AutoML tabular model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Define training specification.
|
||||
- Dataset specification
|
||||
- Hyperparameter overide specification
|
||||
- machine specifications
|
||||
- Construct tabular workflow pipeline.
|
||||
- Compile and execute pipeline.
|
||||
- View evaluation metrics artifact.
|
||||
- Export AutoML model as an OSS TF model.
|
||||
- Create `Endpoint` resource.
|
||||
- Deploy exported OSS TF model.
|
||||
- Make a prediction.
|
||||
|
||||
[Get started with rapid prototyping with AutoML and BigQuery ML](community/ml_ops/stage3/get_started_with_rapid_prototyping_bqml_automl.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Predictions` for rapid prototyping a model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Creating a BigQuery and Vertex AI training dataset.
|
||||
- Training a BigQuery ML and AutoML model.
|
||||
- Extracting evaluation metrics from the BigQueryML and AutoML models.
|
||||
- Selecting the best trained model.
|
||||
- Deploying the best trained model.
|
||||
- Testing the deployed model infrastructure.
|
||||
|
||||
[Get started with AutoML pipeline components](community/ml_ops/stage3/get_started_with_automl_pipeline_components.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use prebuilt `Google Cloud Pipeline Components` for `Vertex AI AutoML`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Construct a pipeline for:
|
||||
- Training a Vertex AI AutoML trained model.
|
||||
- Test the serving binary with a batch prediction job.
|
||||
- Deploying a Vertex AI AutoML trained model.
|
||||
- Execute a Vertex AI pipeline.
|
||||
|
||||
|
||||
[Get started with BigQuery and TFDV pipeline components](community/ml_ops/stage3/get_started_with_bq_tfdv_pipeline_components.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use build lightweight Python components for BigQuery and TensorFlow Data Validation.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Build and execute a pipeline component for creating a Vertex AI Tabular Dataset from a BigQuery table.
|
||||
- Build and execute a pipeline component for generating TFDV statistics and schema from a Vertex AI Tabular Dataset.
|
||||
- Execute a Vertex AI pipeline.
|
||||
```
|
||||
|
||||
### E2E Stage Example
|
||||
|
||||
Stage 4: Evaluation
|
||||
|
||||
@@ -29,22 +29,22 @@
|
||||
"id": "title:generic,gcp"
|
||||
},
|
||||
"source": [
|
||||
"# E2E ML on GCP: MLOps stage 4 : formalization: get started with Vertex ML Metadata\n",
|
||||
"# Get started with Vertex ML Metadata\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage4/get_started_with_vertex_ml_metadata.ipynb\">\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/official/ml_metadata/get_started_with_vertex_ml_metadata.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage4/get_started_with_vertex_ml_metadata.ipynb\">\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/official/ml_metadata/get_started_with_vertex_ml_metadata.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/ml_ops/stage4/get_started_with_vertex_ml_metadata.ipynb\">\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/official/ml_metadata/get_started_with_vertex_ml_metadata.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
" Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
@@ -62,7 +62,9 @@
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"This tutorial demonstrates how to use Vertex AI for E2E MLOps on Google Cloud in production. This tutorial covers stage 4 : formalization: get started with Vertex ML Metadata."
|
||||
"This tutorial demonstrates how to use Vertex ML Metadata.\n",
|
||||
"\n",
|
||||
"Learn more about [Vertex ML Metadata](https://cloud.google.com/vertex-ai/docs/ml-metadata)."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -144,19 +146,32 @@
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"# The Vertex AI Workbench Notebook product has specific requirements\n",
|
||||
"IS_WORKBENCH_NOTEBOOK = os.getenv(\"DL_ANACONDA_HOME\")\n",
|
||||
"IS_USER_MANAGED_WORKBENCH_NOTEBOOK = os.path.exists(\n",
|
||||
" \"/opt/deeplearning/metadata/env_version\"\n",
|
||||
")\n",
|
||||
"! pip3 install --upgrade google-cloud-aiplatform[tensorboard] \\\n",
|
||||
" google-cloud-pipeline-components --quiet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "restart"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only: Uncomment the following cell to restart the kernel"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "D-ZBOjErv5mM"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Automatically restart kernel after installs so that your environment can access the new packages\n",
|
||||
"# import IPython\n",
|
||||
"\n",
|
||||
"# Vertex AI Notebook requires dependencies to be installed with '--user'\n",
|
||||
"USER_FLAG = \"\"\n",
|
||||
"if IS_WORKBENCH_NOTEBOOK:\n",
|
||||
" USER_FLAG = \"--user\"\n",
|
||||
"\n",
|
||||
"! pip3 install --upgrade google-cloud-aiplatform[tensorboard] $USER_FLAG -q\n",
|
||||
"! pip3 install --upgrade google-cloud-pipeline-components $USER_FLAG -q"
|
||||
"# app = IPython.Application.instance()\n",
|
||||
"# app.kernel.do_shutdown(True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -170,63 +185,27 @@
|
||||
"Once you've installed the additional packages, you need to restart the notebook kernel so it can find the packages."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "restart"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"if not os.getenv(\"IS_TESTING\"):\n",
|
||||
" # Automatically restart kernel after installs\n",
|
||||
" import IPython\n",
|
||||
"\n",
|
||||
" app = IPython.Application.instance()\n",
|
||||
" app.kernel.do_shutdown(True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "before_you_begin"
|
||||
},
|
||||
"source": [
|
||||
"## Before you begin\n",
|
||||
"\n",
|
||||
"### GPU runtime\n",
|
||||
"\n",
|
||||
"*Make sure you're running this notebook in a GPU runtime if you have that option. In Colab, select* **Runtime > Change Runtime Type > GPU**\n",
|
||||
"\n",
|
||||
"### Set up your Google Cloud project\n",
|
||||
"\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"2. [Make sure that billing is enabled for your project.](https://cloud.google.com/billing/docs/how-to/modify-project)\n",
|
||||
"\n",
|
||||
"3. [Enable the following APIs: Vertex AI APIs, Compute Engine APIs, and Cloud Storage.](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component,storage-component.googleapis.com)\n",
|
||||
"\n",
|
||||
"4. If you are running this notebook locally, you need to install the [Cloud SDK]((https://cloud.google.com/sdk)).\n",
|
||||
"\n",
|
||||
"5. Enter your project ID in the cell below. Then run the cell to make sure the\n",
|
||||
"Cloud SDK uses the right project for all the commands in this notebook.\n",
|
||||
"\n",
|
||||
"**Note**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$`."
|
||||
"## Before you begin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "project_id"
|
||||
"id": "before_you_begin:nogpu"
|
||||
},
|
||||
"source": [
|
||||
"#### Set your project ID\n",
|
||||
"### Set your project ID\n",
|
||||
"\n",
|
||||
"**If you don't know your project ID**, you may be able to get your project ID using `gcloud`."
|
||||
"**If you don't know your project ID**, try the following:\n",
|
||||
"* Run `gcloud config list`.\n",
|
||||
"* Run `gcloud projects list`.\n",
|
||||
"* See the support page: [Locate the project ID](https://support.google.com/googleapi/answer/7014113)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -237,33 +216,10 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "autoset_project_id"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if PROJECT_ID == \"\" or PROJECT_ID is None or PROJECT_ID == \"[your-project-id]\":\n",
|
||||
" # Get your GCP project id from gcloud\n",
|
||||
" shell_output = ! gcloud config list --format 'value(core.project)' 2>/dev/null\n",
|
||||
" PROJECT_ID = shell_output[0]\n",
|
||||
" print(\"Project ID:\", PROJECT_ID)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "set_gcloud_project_id"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! gcloud config set project $PROJECT_ID"
|
||||
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# Set the project id\n",
|
||||
"! gcloud config set project {PROJECT_ID}"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -274,16 +230,7 @@
|
||||
"source": [
|
||||
"#### Region\n",
|
||||
"\n",
|
||||
"You can also change the `REGION` variable, which is used for operations\n",
|
||||
"throughout the rest of this notebook. Below are regions supported for Vertex AI. We recommend that you choose the region closest to you.\n",
|
||||
"\n",
|
||||
"- Americas: `us-central1`\n",
|
||||
"- Europe: `europe-west4`\n",
|
||||
"- Asia Pacific: `asia-east1`\n",
|
||||
"\n",
|
||||
"You may not use a multi-regional bucket for training with Vertex AI. Not all regions provide support for all Vertex AI services.\n",
|
||||
"\n",
|
||||
"Learn more about [Vertex AI regions](https://cloud.google.com/vertex-ai/docs/general/locations)."
|
||||
"You can also change the `REGION` variable used by Vertex AI. Learn more about [Vertex AI regions](https://cloud.google.com/vertex-ai/docs/general/locations)."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -294,34 +241,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"REGION = \"[your-region]\" # @param {type: \"string\"}\n",
|
||||
"\n",
|
||||
"if REGION == \"[your-region]\":\n",
|
||||
" REGION = \"us-central1\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "timestamp"
|
||||
},
|
||||
"source": [
|
||||
"#### Timestamp\n",
|
||||
"\n",
|
||||
"If you are in a live tutorial session, you might be using a shared test account or project. To avoid name collisions between users on resources created, you create a timestamp for each instance session, and append the timestamp onto the name of resources you create in this tutorial."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "timestamp"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from datetime import datetime\n",
|
||||
"\n",
|
||||
"TIMESTAMP = datetime.now().strftime(\"%Y%m%d%H%M%S\")"
|
||||
"REGION = \"us-central1\" # @param {type: \"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -332,57 +252,70 @@
|
||||
"source": [
|
||||
"### Authenticate your Google Cloud account\n",
|
||||
"\n",
|
||||
"**If you are using Vertex AI Workbench Notebooks**, your environment is already authenticated. Skip this step.\n",
|
||||
"\n",
|
||||
"**If you are using Colab**, run the cell below and follow the instructions when prompted to authenticate your account via oAuth.\n",
|
||||
"\n",
|
||||
"**Otherwise**, follow these steps:\n",
|
||||
"\n",
|
||||
"In the Cloud Console, go to the [Create service account key](https://console.cloud.google.com/apis/credentials/serviceaccountkey) page.\n",
|
||||
"\n",
|
||||
"**Click Create service account**.\n",
|
||||
"\n",
|
||||
"In the **Service account name** field, enter a name, and click **Create**.\n",
|
||||
"\n",
|
||||
"In the **Grant this service account access to project** section, click the Role drop-down list. Type \"Vertex\" into the filter box, and select **Vertex Administrator**. Type \"Storage Object Admin\" into the filter box, and select **Storage Object Admin**.\n",
|
||||
"\n",
|
||||
"Click Create. A JSON file that contains your key downloads to your local environment.\n",
|
||||
"\n",
|
||||
"Enter the path to your service account key as the GOOGLE_APPLICATION_CREDENTIALS variable in the cell below and run the cell."
|
||||
"Depending on your Jupyter environment, you may have to manually authenticate. Follow the relevant instructions below."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "FvQeFm3Gv5mR"
|
||||
},
|
||||
"source": [
|
||||
"**1. Vertex AI Workbench**\n",
|
||||
"* Do nothing as you are already authenticated."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ad1138a125ea"
|
||||
},
|
||||
"source": [
|
||||
"**2. Local JupyterLab instance, uncomment and run:**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "gcp_authenticate"
|
||||
"id": "ce6043da7b33"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# ! gcloud auth login"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0367eac06a10"
|
||||
},
|
||||
"source": [
|
||||
"**3. Colab, uncomment and run:**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "21ad4dbb4a61"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# If you are running this notebook in Colab, run this cell and follow the\n",
|
||||
"# instructions to authenticate your GCP account. This provides access to your\n",
|
||||
"# Cloud Storage bucket and lets you submit training jobs and prediction\n",
|
||||
"# requests.\n",
|
||||
"\n",
|
||||
"import os\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"# If on Vertex AI Workbench, then don't execute this code\n",
|
||||
"IS_COLAB = False\n",
|
||||
"if not os.path.exists(\"/opt/deeplearning/metadata/env_version\") and not os.getenv(\n",
|
||||
" \"DL_ANACONDA_HOME\"\n",
|
||||
"):\n",
|
||||
" if \"google.colab\" in sys.modules:\n",
|
||||
" IS_COLAB = True\n",
|
||||
" from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
" google_auth.authenticate_user()\n",
|
||||
"\n",
|
||||
" # If you are running this notebook locally, replace the string below with the\n",
|
||||
" # path to your service account key and run this cell to authenticate your GCP\n",
|
||||
" # account.\n",
|
||||
" elif not os.getenv(\"IS_TESTING\"):\n",
|
||||
" %env GOOGLE_APPLICATION_CREDENTIALS ''"
|
||||
"# from google.colab import auth\n",
|
||||
"# auth.authenticate_user()\n",
|
||||
"# IS_COLAB = True"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "c13224697bfb"
|
||||
},
|
||||
"source": [
|
||||
"**4. Service account or other**\n",
|
||||
"* See how to grant Cloud Storage permissions to your service account at https://cloud.google.com/storage/docs/gsutil/commands/iam#ch-examples."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -393,11 +326,7 @@
|
||||
"source": [
|
||||
"### Create a Cloud Storage bucket\n",
|
||||
"\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"When you initialize the Vertex SDK for Python, you specify a Cloud Storage staging bucket. The staging bucket is where all the data associated with your dataset and model resources are retained across sessions.\n",
|
||||
"\n",
|
||||
"Set the name of your Cloud Storage bucket below. Bucket names must be globally unique across all Google Cloud projects, including those outside of your organization."
|
||||
"Create a storage bucket to store intermediate artifacts such as datasets."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -408,21 +337,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"BUCKET_NAME = \"[your-bucket-name]\" # @param {type:\"string\"}\n",
|
||||
"BUCKET_URI = f\"gs://{BUCKET_NAME}\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "autoset_bucket"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if BUCKET_NAME == \"\" or BUCKET_NAME is None or BUCKET_NAME == \"[your-bucket-name]\":\n",
|
||||
" BUCKET_NAME = PROJECT_ID + \"aip-\" + TIMESTAMP\n",
|
||||
" BUCKET_URI = \"gs://\" + BUCKET_NAME"
|
||||
"BUCKET_URI = f\"gs://your-bucket-name-{PROJECT_ID}-unique\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -445,26 +360,6 @@
|
||||
"! gsutil mb -l $REGION $BUCKET_URI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "validate_bucket"
|
||||
},
|
||||
"source": [
|
||||
"Finally, validate access to your Cloud Storage bucket by examining its contents:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "validate_bucket"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! gsutil ls -al $BUCKET_URI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
@@ -545,19 +440,7 @@
|
||||
"source": [
|
||||
"### Set up variables\n",
|
||||
"\n",
|
||||
"Next, set up some variables used throughout the tutorial.\n",
|
||||
"### Import libraries and define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "import_aip:mbsdk"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import google.cloud.aiplatform as aip"
|
||||
"Next, set up some variables used throughout the tutorial."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -579,7 +462,10 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import google.cloud.aiplatform_v1beta1 as aip_beta"
|
||||
"from datetime import datetime\n",
|
||||
"\n",
|
||||
"import google.cloud.aiplatform_v1beta1 as aip_beta\n",
|
||||
"from google.cloud import aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -707,7 +593,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"metadata_store = clients[\"metadata\"].create_metadata_store(\n",
|
||||
" parent=PARENT, metadata_store_id=\"my-metadata-store\"\n",
|
||||
" parent=PARENT, metadata_store_id=\"my-metadata-store-unique\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"metadata_store_id = str(metadata_store.result())[7:-2]\n",
|
||||
@@ -1144,7 +1030,7 @@
|
||||
"source": [
|
||||
"from kfp.v2 import compiler, dsl\n",
|
||||
"from kfp.v2.dsl import (Artifact, Dataset, Input, Metrics, Model, Output,\n",
|
||||
" OutputPath, component, pipeline)"
|
||||
" OutputPath, component)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1196,7 +1082,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"@component(\n",
|
||||
" packages_to_install=[\"google-cloud-bigquery\", \"pandas\", \"pyarrow\"],\n",
|
||||
" packages_to_install=[\"google-cloud-bigquery\", \"pandas\", \"pyarrow\", \"db-dtypes\"],\n",
|
||||
" base_image=\"python:3.9\",\n",
|
||||
" output_component_file=\"create_dataset.yaml\",\n",
|
||||
")\n",
|
||||
@@ -1214,7 +1100,7 @@
|
||||
"\n",
|
||||
"\n",
|
||||
"@component(\n",
|
||||
" packages_to_install=[\"sklearn\", \"pandas\", \"joblib\"],\n",
|
||||
" packages_to_install=[\"scikit-learn\", \"pandas\", \"joblib\"],\n",
|
||||
" base_image=\"python:3.9\",\n",
|
||||
" output_component_file=\"beans_model_component.yaml\",\n",
|
||||
")\n",
|
||||
@@ -1298,7 +1184,7 @@
|
||||
" # A name for the pipeline.\n",
|
||||
" name=\"mlmd-pipeline\",\n",
|
||||
")\n",
|
||||
"def pipeline(\n",
|
||||
"def my_pipeline(\n",
|
||||
" bq_table: str = \"\",\n",
|
||||
" output_data_path: str = \"data.csv\",\n",
|
||||
" project: str = PROJECT_ID,\n",
|
||||
@@ -1332,20 +1218,22 @@
|
||||
"source": [
|
||||
"NOW = datetime.now().isoformat().replace(\".\", \":\")[:-7]\n",
|
||||
"\n",
|
||||
"compiler.Compiler().compile(pipeline_func=pipeline, package_path=\"mlmd_pipeline.json\")\n",
|
||||
"compiler.Compiler().compile(\n",
|
||||
" pipeline_func=my_pipeline, package_path=\"mlmd_pipeline.json\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"run1 = aip.PipelineJob(\n",
|
||||
"run1 = aiplatform.PipelineJob(\n",
|
||||
" display_name=\"mlmd-pipeline\",\n",
|
||||
" template_path=\"mlmd_pipeline.json\",\n",
|
||||
" job_id=\"mlmd-pipeline-small-{}\".format(TIMESTAMP),\n",
|
||||
" job_id=\"mlmd-pipeline-small-unique\",\n",
|
||||
" parameter_values={\"bq_table\": \"sara-vertex-demos.beans_demo.small_dataset\"},\n",
|
||||
" enable_caching=True,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"run2 = aip.PipelineJob(\n",
|
||||
"run2 = aiplatform.PipelineJob(\n",
|
||||
" display_name=\"mlmd-pipeline\",\n",
|
||||
" template_path=\"mlmd_pipeline.json\",\n",
|
||||
" job_id=\"mlmd-pipeline-large-{}\".format(TIMESTAMP),\n",
|
||||
" job_id=\"mlmd-pipeline-large-unique\",\n",
|
||||
" parameter_values={\"bq_table\": \"sara-vertex-demos.beans_demo.large_dataset\"},\n",
|
||||
" enable_caching=True,\n",
|
||||
")\n",
|
||||
@@ -1382,7 +1270,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df = aip.get_pipeline_df(pipeline=\"mlmd-pipeline\")\n",
|
||||
"df = aiplatform.get_pipeline_df(pipeline=\"mlmd-pipeline\")\n",
|
||||
"print(df)"
|
||||
]
|
||||
},
|
||||
@@ -1466,6 +1354,10 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"metadata_store_id = (\n",
|
||||
" f\"projects/{PROJECT_ID}/locations/{REGION}/metadataStores/my-metadata-store-unique\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"clients[\"metadata\"].delete_metadata_store(name=metadata_store_id)"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -25,9 +25,10 @@ The fifth stage in MLOps is deployment to production of the blessed model, which
|
||||
### Get Started
|
||||
|
||||
|
||||
[Get started with Vertex AI Endpoints](community/ml_ops/stage5/get_started_with_vertex_endpoints.ipynb)
|
||||
[Get started with Vertex AI Endpoints](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage5/get_started_with_vertex_endpoints.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Endpoint` resources.
|
||||
```
|
||||
Learn how to use `Vertex AI Endpoint` resources.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -46,9 +47,13 @@ The steps performed include:
|
||||
- In pipeline: Create an `Endpoint` resource and deploy an existing `Model` resource to the `Endpoint` resource.
|
||||
- In pipeline: Deploy an existing `Model` resource to an existing `Endpoint` resource.
|
||||
|
||||
[Get started with Vertex AI Endpoint and shared VM](community/ml_ops/stage5/get_started_with_vertex_endpoint_and_shared_vm.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use deployment resource pools for deploying models. A deployment resouce pool provides one with the ability to co-host more than one model on the same (shared) VM.
|
||||
|
||||
[Get started with Vertex AI Endpoint and shared VM](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage5/get_started_with_vertex_endpoint_and_shared_vm.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use deployment resource pools for deploying models.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -62,9 +67,13 @@ The steps performed include:
|
||||
- Make a prediction request with first deployed model (model A).
|
||||
- Make a prediction request with second deployed model (model B).
|
||||
|
||||
[Get started with configuring autoscaling for Vertex AI Endpoint deployment](community/ml_ops/stage5/get_started_with_autoscaling.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use fine-tune control auto-scaling configuration when deploying a `Model` resource to an `Endpoint` resource.
|
||||
|
||||
[Get started with configuring autoscaling for Vertex AI Endpoint deployment](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage5/get_started_with_autoscaling.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use fine-tune control auto-scaling configuration when deploying a `Model` resource to an `Endpoint` resource.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -78,9 +87,13 @@ The steps performed include:
|
||||
- Fine-tune scaling thresholds for GPU utilization.
|
||||
- Deploy mix of CPU and GPU model instances with auto-scaling to an `Endpoint` resource.
|
||||
|
||||
[Get started with Vertex AI Private Endpoints](community/ml_ops/stage5/get_started_with_vertex_private_endpoints.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Private Endpoint` resources.
|
||||
|
||||
[Get started with Vertex AI Private Endpoints](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage5/get_started_with_vertex_private_endpoints.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Private Endpoint` resources.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -89,8 +102,5 @@ The steps performed include:
|
||||
- Configuring the serving binary of a `Model` resource for deployment to a `Private Endpoint` resource.
|
||||
- Deploying a `Model` resource to a `Private Endpoint` resource.
|
||||
- Send a prediction request to a `Private Endpoint`
|
||||
- Enable two additional APIs: Service Networking and Cloud DNS.
|
||||
- Add Compute Admin Network role to your (default) service account.
|
||||
- Issue two gcloud commands to setup the VPC peering for your service account.
|
||||
- There is *currently* no SDK support yet, so private endpoint is created with GAPIC client and has an extra argument for the peering network.
|
||||
- To send a request, you can't use SDK/GAPIC since they do a HTTP internet request. Instead, you use curl to send a peer-to-peer request.
|
||||
|
||||
```
|
||||
+89
-115
@@ -159,9 +159,9 @@
|
||||
"\n",
|
||||
"# Install the packages\n",
|
||||
"\n",
|
||||
"! pip3 install --upgrade google-cloud-aiplatform $USER_FLAG -q\n",
|
||||
"! pip3 install --upgrade tensorflow $USER_FLAG -q\n",
|
||||
"! pip3 install --upgrade tensorflow-hub $USER_FLAG -q"
|
||||
"! pip3 install --upgrade google-cloud-aiplatform \\\n",
|
||||
" tensorflow \\\n",
|
||||
" tensorflow-hub $USER_FLAG -q"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -307,22 +307,29 @@
|
||||
"id": "timestamp"
|
||||
},
|
||||
"source": [
|
||||
"#### Timestamp\n",
|
||||
"#### UUID\n",
|
||||
"\n",
|
||||
"If you are in a live tutorial session, you might be using a shared test account or project. To avoid name collisions between users on resources created, you create a timestamp for each instance session, and append the timestamp onto the name of resources you create in this tutorial."
|
||||
"If you are in a live tutorial session, you might be using a shared test account or project. To avoid name collisions between users on resources created, you create a uuid for each instance session, and append it onto the name of resources you create in this tutorial."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "timestamp"
|
||||
"id": "84Vdv7R-QEH6"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from datetime import datetime\n",
|
||||
"import random\n",
|
||||
"import string\n",
|
||||
"\n",
|
||||
"TIMESTAMP = datetime.now().strftime(\"%Y%m%d%H%M%S\")"
|
||||
"\n",
|
||||
"# Generate a uuid of a specifed length(default=8)\n",
|
||||
"def generate_uuid(length: int = 8) -> str:\n",
|
||||
" return \"\".join(random.choices(string.ascii_lowercase + string.digits, k=length))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"UUID = generate_uuid()"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -421,7 +428,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if BUCKET_URI == \"\" or BUCKET_URI is None or BUCKET_URI == \"gs://[your-bucket-name]\":\n",
|
||||
" BUCKET_NAME = PROJECT_ID + \"aip-\" + TIMESTAMP\n",
|
||||
" BUCKET_NAME = PROJECT_ID + \"aip-\" + UUID\n",
|
||||
" BUCKET_URI = \"gs://\" + BUCKET_NAME"
|
||||
]
|
||||
},
|
||||
@@ -523,7 +530,7 @@
|
||||
"\n",
|
||||
"Setup up the following constants for Vertex AI:\n",
|
||||
"\n",
|
||||
"- `API_ENDPOINT`: The Vertex AI API service endpoint for `Endpoint` services."
|
||||
"- `API_ENDPOINT`: The Vertex AI API service endpoint."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -538,46 +545,10 @@
|
||||
"API_ENDPOINT = \"{}-aiplatform.googleapis.com\".format(REGION)\n",
|
||||
"\n",
|
||||
"# Vertex location root path for your dataset, model and endpoint resources\n",
|
||||
"PARENT = \"projects/\" + PROJECT_ID + \"/locations/\" + REGION"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "clients:metadata"
|
||||
},
|
||||
"source": [
|
||||
"## Set up clients\n",
|
||||
"PARENT = \"projects/\" + PROJECT_ID + \"/locations/\" + REGION\n",
|
||||
"\n",
|
||||
"The Vertex works as a client/server model. On your side (the Python script) you will create a client that sends requests and receives responses from the Vertex AI server.\n",
|
||||
"\n",
|
||||
"You will use different clients in this tutorial for different steps in the workflow. So set them all up upfront.\n",
|
||||
"\n",
|
||||
"- Endpoint Service for creating endpoints, and deploying models to endpoints."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "clients:metadata"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# client options same for all services\n",
|
||||
"client_options = {\"api_endpoint\": API_ENDPOINT}\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_endpoint_client():\n",
|
||||
" client = aip_beta.EndpointServiceClient(client_options=client_options)\n",
|
||||
" return client\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"clients = {}\n",
|
||||
"clients[\"endpoint\"] = create_endpoint_client()\n",
|
||||
"\n",
|
||||
"for client in clients.items():\n",
|
||||
" print(client)"
|
||||
"client_options = {\"api_endpoint\": API_ENDPOINT}"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -592,7 +563,7 @@
|
||||
"\n",
|
||||
"Set the variables `DEPLOY_GPU/DEPLOY_NGPU` to use a container image supporting a GPU and the number of GPUs allocated to the virtual machine (VM) instance. For example, to use a GPU container image with 4 Nvidia Telsa K80 GPUs allocated to each VM, you would specify:\n",
|
||||
"\n",
|
||||
" (aip.AcceleratorType.NVIDIA_TESLA_K80, 4)\n",
|
||||
" (aip.gapic.AcceleratorType.NVIDIA_TESLA_K80, 4)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Otherwise specify `(None, None)` to use a container image to run on a CPU.\n",
|
||||
@@ -902,7 +873,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model_icn = aiplatform.Model.upload(\n",
|
||||
" display_name=\"icn_\" + TIMESTAMP,\n",
|
||||
" display_name=\"icn_\" + UUID,\n",
|
||||
" artifact_uri=MODEL_ICN_DIR,\n",
|
||||
" serving_container_image_uri=DEPLOY_IMAGE,\n",
|
||||
")\n",
|
||||
@@ -1013,7 +984,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model_use = aiplatform.Model.upload(\n",
|
||||
" display_name=\"icn_\" + TIMESTAMP,\n",
|
||||
" display_name=\"icn_\" + UUID,\n",
|
||||
" artifact_uri=MODEL_USE_DIR,\n",
|
||||
" serving_container_image_uri=DEPLOY_IMAGE,\n",
|
||||
")\n",
|
||||
@@ -1029,64 +1000,55 @@
|
||||
"source": [
|
||||
"## Creating a deployment resource pool\n",
|
||||
"\n",
|
||||
"Currently, creating deploynent resource pools is only supported via the REST-based API (e.g., CURL).\n",
|
||||
"Currently, creating deploynent resource pools is only supported via the REST-based API (e.g., CURL) and GAPIC APIs (Python).\n",
|
||||
"\n",
|
||||
"Use `CreateDeploymentResourcePool` API to create a resource pool, with the following configuration:\n",
|
||||
"Use `create_deployment_resource_pool` API to create a resource pool, with the following configuration:\n",
|
||||
"\n",
|
||||
"- `dedicated_resources`: Compute (HW) resources to allocate for the shared vm.\n",
|
||||
"- `min_replica_count`: Auto-scaling, the minimum number of compute nodes.\n",
|
||||
"- `max_replica_count`: Auto-scaling, the maximum number of compute nodes.\n",
|
||||
"\n",
|
||||
"Learn more about [Deployment Resource Pools]()."
|
||||
"Learn more about [Deployment Resource Pools](https://googleapis.dev/python/aiplatform/latest/aiplatform_v1beta1/deployment_resource_pool_service.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "YiBmoiWYcMQt"
|
||||
"id": "90c51b6cf34a"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"DEPLOYMENT_RESOURCE_POOL_ID = \"shared-vm\" # @param {type: \"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "0CHPJ4h-Slgs"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import json\n",
|
||||
"import pprint\n",
|
||||
"pp = pprint.PrettyPrinter(indent=4)\n",
|
||||
"\n",
|
||||
"DEPLOYMENT_RESOURCE_POOL_ID = f\"shared-vm-{UUID}\" # @param {type: \"string\"}\n",
|
||||
"MIN_NODES = 1\n",
|
||||
"MAX_NODES = 2\n",
|
||||
"\n",
|
||||
"CREATE_RP_PAYLOAD = {\n",
|
||||
" \"deployment_resource_pool\":{\n",
|
||||
" \"dedicated_resources\":{\n",
|
||||
" \"machine_spec\":{\n",
|
||||
" \"machine_type\": DEPLOY_COMPUTE\n",
|
||||
" },\n",
|
||||
" \"min_replica_count\": MIN_NODES, \n",
|
||||
" \"max_replica_count\": MAX_NODES\n",
|
||||
" }\n",
|
||||
" },\n",
|
||||
" \"deployment_resource_pool_id\":DEPLOYMENT_RESOURCE_POOL_ID\n",
|
||||
"}\n",
|
||||
"CREATE_RP_REQUEST=json.dumps(CREATE_RP_PAYLOAD)\n",
|
||||
"pp.pprint(\"CREATE_RP_REQUEST: \" + CREATE_RP_REQUEST)\n",
|
||||
"# Initialize request argument(s)\n",
|
||||
"deployment_resource_pool = aip_beta.DeploymentResourcePool()\n",
|
||||
"deployment_resource_pool.dedicated_resources.min_replica_count = MIN_NODES\n",
|
||||
"deployment_resource_pool.dedicated_resources.max_replica_count = MAX_NODES\n",
|
||||
"deployment_resource_pool.dedicated_resources.machine_spec.machine_type = DEPLOY_COMPUTE\n",
|
||||
"if DEPLOY_NGPU:\n",
|
||||
" deployment_resource_pool.dedicated_resources.machine_spec.accelerator_type = DEPLOY_GPU\n",
|
||||
" deployment_resource_pool.dedicated_resources.machine_spec.accelerator_count = DEPLOY_NGPU\n",
|
||||
"\n",
|
||||
"! curl \\\n",
|
||||
"-X POST \\\n",
|
||||
"-H \"Authorization: Bearer $(gcloud auth print-access-token)\" \\\n",
|
||||
"-H \"Content-Type: application/json\" \\\n",
|
||||
"https://{REGION}-aiplatform.googleapis.com/v1beta1/projects/{PROJECT_ID}/locations/{REGION}/deploymentResourcePools \\\n",
|
||||
"-d '{CREATE_RP_REQUEST}'"
|
||||
"request = aip_beta.CreateDeploymentResourcePoolRequest(\n",
|
||||
" parent=f\"projects/{PROJECT_ID}/locations/{REGION}\",\n",
|
||||
" deployment_resource_pool=deployment_resource_pool,\n",
|
||||
" deployment_resource_pool_id=DEPLOYMENT_RESOURCE_POOL_ID,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"pool_client = aip_beta.services.deployment_resource_pool_service.DeploymentResourcePoolServiceClient(\n",
|
||||
" client_options=client_options\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"op = pool_client.create_deployment_resource_pool(request=request)\n",
|
||||
"print(op)\n",
|
||||
"\n",
|
||||
"result = op.result()\n",
|
||||
"print(result)\n",
|
||||
"\n",
|
||||
"deployment_pool_id = result.name"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1099,21 +1061,19 @@
|
||||
"\n",
|
||||
"Use `GetDeploymentResourcePool` API to check out the deploynent resource pool that you created. \n",
|
||||
"\n",
|
||||
"Learn more about [Get Deployment Resource Pool](https://source.corp.google.com/piper///depot/google3/google/cloud/aiplatform/master/deployment_resource_pool_service.proto;l=75?q=deployment_resource_pool&sq=package:piper%20file:%2F%2Fdepot%2Fgoogle3%20-file:google3%2Fexperimental)."
|
||||
"Learn more about [Get Deployment Resource Pool](https://googleapis.dev/python/aiplatform/latest/aiplatform_v1beta1/deployment_resource_pool_service.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "6wTLyhPraFah"
|
||||
"id": "b740253903c0"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! curl -X GET \\\n",
|
||||
"-H \"Authorization: Bearer $(gcloud auth print-access-token)\" \\\n",
|
||||
"-H \"Content-Type: application/json\" \\\n",
|
||||
"https://{REGION}-aiplatform.googleapis.com/v1beta1/projects/{PROJECT_ID}/locations/{REGION}/deploymentResourcePools/{DEPLOYMENT_RESOURCE_POOL_ID}"
|
||||
"response = pool_client.get_deployment_resource_pool(name=deployment_pool_id)\n",
|
||||
"print(response)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1126,21 +1086,22 @@
|
||||
"\n",
|
||||
"Use `ListDeploymentResourcePools` API to list all the deployment resource pools. \n",
|
||||
"\n",
|
||||
"Learn more about [Listing Deployment Resource Pools](https://source.corp.google.com/piper///depot/google3/google/cloud/aiplatform/master/deployment_resource_pool_service.proto;l=101?q=deployment_resource_pool&sq=package:piper%20file:%2F%2Fdepot%2Fgoogle3%20-file:google3%2Fexperimental)."
|
||||
"Learn more about [Listing Deployment Resource Pools](https://googleapis.dev/python/aiplatform/latest/aiplatform_v1beta1/deployment_resource_pool_service.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Pxls4sNnaltU"
|
||||
"id": "3ebfd007bff2"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! curl -X GET \\\n",
|
||||
"-H \"Authorization: Bearer $(gcloud auth print-access-token)\" \\\n",
|
||||
"-H \"Content-Type: application/json\" \\\n",
|
||||
"https://{REGION}-aiplatform.googleapis.com/v1beta1/projects/{PROJECT_ID}/locations/{REGION}/deploymentResourcePools"
|
||||
"pools = pool_client.list_deployment_resource_pools(\n",
|
||||
" parent=f\"projects/{PROJECT_ID}/locations/{REGION}\"\n",
|
||||
")\n",
|
||||
"for pool in pools:\n",
|
||||
" print(pool)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1170,11 +1131,11 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"endpoint_icn = aiplatform.Endpoint.create(display_name=\"icn_\" + TIMESTAMP)\n",
|
||||
"endpoint_icn = aiplatform.Endpoint.create(display_name=\"icn_\" + UUID)\n",
|
||||
"\n",
|
||||
"print(endpoint_icn)\n",
|
||||
"\n",
|
||||
"endpoint_use = aiplatform.Endpoint.create(display_name=\"use_\" + TIMESTAMP)\n",
|
||||
"endpoint_use = aiplatform.Endpoint.create(display_name=\"use_\" + UUID)\n",
|
||||
"\n",
|
||||
"print(endpoint_use)"
|
||||
]
|
||||
@@ -1204,6 +1165,12 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import json\n",
|
||||
"import pprint\n",
|
||||
"\n",
|
||||
"pp = pprint.PrettyPrinter(indent=4)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"SHARED_RESOURCE = \"projects/{project_id}/locations/{region}/deploymentResourcePools/{deployment_resource_pool_id}\".format(\n",
|
||||
" project_id=PROJECT_ID,\n",
|
||||
" region=REGION,\n",
|
||||
@@ -1363,18 +1330,27 @@
|
||||
" time.sleep(30)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "52248c450776"
|
||||
},
|
||||
"source": [
|
||||
"### Get deployment details for the endpoint\n",
|
||||
"\n",
|
||||
"List the deployed models on the endpoint."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "86a659bf60f0"
|
||||
"id": "3b768614e7c6"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! curl -X GET \\\n",
|
||||
" -H \"Authorization: Bearer $(gcloud auth print-access-token)\" \\\n",
|
||||
" -H \"Content-Type: application/json\" \\\n",
|
||||
"https://{REGION}-aiplatform.googleapis.com/v1/projects/759209241365/locations/us-central1/endpoints/2259566763823857664"
|
||||
"print(endpoint_icn.list_models())\n",
|
||||
"print(endpoint_use.list_models())"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1557,21 +1533,19 @@
|
||||
"source": [
|
||||
"#### Delete the `DeploymentResourcePool`\n",
|
||||
"\n",
|
||||
"The method 'delete()' will delete your deployment resource pool."
|
||||
"The method 'delete_deployment_resource_pool()' will delete your deployment resource pool."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ac40cc1d594a"
|
||||
"id": "b76a4de1e57e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! curl -X DELETE \\\n",
|
||||
"-H \"Authorization: Bearer $(gcloud auth print-access-token)\" \\\n",
|
||||
"-H \"Content-Type: application/json\" \\\n",
|
||||
"https://{REGION}-aiplatform.googleapis.com/v1beta1/projects/{PROJECT_ID}/locations/{REGION}/deploymentResourcePools/{DEPLOYMENT_RESOURCE_POOL_ID}"
|
||||
"response = pool_client.delete_deployment_resource_pool(name=deployment_pool_id)\n",
|
||||
"print(response)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -30,19 +30,23 @@ This stage may be done entirely by MLOps. We recommend:
|
||||
### Get Started
|
||||
|
||||
|
||||
[Get started with Vertex AI Batch Prediction for AutoML image models](community/ml_ops/stage6/get_started_with_automl_image_model_batch.ipynb)
|
||||
[Get started with Vertex AI Batch Prediction for AutoML image models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_automl_image_model_batch.ipynb)
|
||||
|
||||
In this tutorial, you create an AutoML image classification model from a Python script, and then do a batch prediction using the Vertex AI SDK.
|
||||
```
|
||||
Learn how to create an AutoML image classification model from a Python script, and then do a batch prediction using the Vertex AI SDK.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Create a Vertex `Dataset` resource.
|
||||
- Train an `AutoML` image classification model.
|
||||
- Make a batch prediction with JSONL input.
|
||||
```
|
||||
|
||||
[Get started with Vertex AI Matching Engine and Swivel builtin algorithm](community/ml_ops/stage6/get_started_with_matching_engine_swivel.ipynb)
|
||||
|
||||
In this notebook, you learn how to train custom embeddings using Vertex AI Pipelines and subsequently train and deploy a matching engine index using the embeddings.
|
||||
[Get started with Vertex AI Matching Engine and Swivel builtin algorithm](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_matching_engine_swivel.ipynb)
|
||||
|
||||
```
|
||||
Learn how to train custom embeddings using Vertex AI Pipelines and subsequently train and deploy a matching engine index using the embeddings.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -54,9 +58,13 @@ The steps performed include:
|
||||
6. Deploy the `Matching Engine Index` to a `Index Endpoint`.
|
||||
7. Make a matching engine prediction request.
|
||||
|
||||
[Get started with Vertex AI Matching Engine](community/ml_ops/stage6/get_started_with_matching_engine.ipynb)
|
||||
```
|
||||
|
||||
In this notebook, you learn how to create Approximate Nearest Neighbor (ANN) Index, query against indexes.
|
||||
|
||||
[Get started with Vertex AI Matching Engine](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_matching_engine.ipynb)
|
||||
|
||||
```
|
||||
Learn how to create Approximate Nearest Neighbor (ANN) Index, query against indexes.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -67,10 +75,13 @@ The steps performed include:
|
||||
- Deploy brute force Index.
|
||||
- Perform calibration between ANN and brute force index.
|
||||
|
||||
[Get started with Vertex AI Matching Engine and Two Towers builtin algorithm](community/ml_ops/stage6/get_started_with_matching_engine_twotowers.ipynb)
|
||||
```
|
||||
|
||||
|
||||
In this notebook, you learn how to use the `Two-Tower` builtin algorithms for generating embeddings for a dataset, for use with generating an `Matching Engine Index`, with the `Vertex AI Matching Engine` service.
|
||||
[Get started with Vertex AI Matching Engine and Two Towers builtin algorithm](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_matching_engine_twotowers.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use the `Two-Tower` builtin algorithms for generating embeddings for a dataset, for use with generating an `Matching Engine Index`, with the `Vertex AI Matching Engine` service.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -83,9 +94,30 @@ The steps performed include:
|
||||
7. Deploy the `Matching Engine Index` to a `Index Endpoint`.
|
||||
8. Make a matching engine prediction request.
|
||||
|
||||
[Get started with Vertex AI Batch Prediction for custom tabular models](community/ml_ops/stage6/get_started_with_custom_tabular_model_batch.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Batch Prediction` with a custom tabular model.
|
||||
|
||||
[Get started with TensorFlow Serving with Vertex AI Prediction](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_tf_serving_tabular.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Prediction` on a `Vertex AI Endpoint` resource with `TensorFlow Serving` serving binary.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Download a pretrained TensorFlow tabular model.
|
||||
- Upload the TensorFlow model as a `Vertex AI Model` resource.
|
||||
- Creating an `Endpoint` resource.
|
||||
- Deploying the `Model` resource to an `Endpoint` resource with `TensorFlow Serving` serving binary.
|
||||
- Make an online prediction to the `Model` resource instance deployed to the `Endpoint` resource.
|
||||
- Make a batch prediction to the `Model` resource instance.
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Get started with Vertex AI Batch Prediction for custom tabular models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_custom_tabular_model_batch.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Batch Prediction` with a custom tabular model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -93,10 +125,13 @@ The steps performed include:
|
||||
- Make batch prediction to the `Model` resource, in JSONL format.
|
||||
- Make batch prediction to the `Model` resource, in CSV format.
|
||||
- Make batch prediction to the `Model` resource, in BigQuery format.
|
||||
```
|
||||
|
||||
[Get started with Optimized TensorFlow Enterprise container with Vertex AI Prediction / text models](community/ml_ops/stage6/get_started_with_optimized_tfe_bert.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `TensorFlow Enterprise Optimized` container for TensorFlow models deployed to a `Vertex AI Endpoint` resource.
|
||||
[Get started with Optimized TensorFlow Enterprise container with Vertex AI Prediction / text models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_optimized_tfe_bert.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `TensorFlow Enterprise Optimized` container for TensorFlow models deployed to a `Vertex AI Endpoint` resource.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -113,9 +148,13 @@ The steps performed include:
|
||||
- Deploy the `Model` resoure with then `TensorFlow Enterprise Optimized` to the `Private Endpoint` resource.
|
||||
- Make an online prediction request to the `Private Endpoint` resource.
|
||||
|
||||
[Get started with Vertex AI Batch Prediction and Explainable AI for AutoML tabular models](community/ml_ops/stage6/get_started_with_automl_tabular_model_batch.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you create an AutoML tabular binary classification model from a Python script, and then do a batch prediction with Explainable AI using the Vertex AI SDK. You can alternatively create and deploy models using the `gcloud` command-line tool or online using the Cloud Console.
|
||||
|
||||
[Get started with Vertex AI Batch Prediction and Explainable AI for AutoML tabular models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_automl_tabular_model_batch.ipynb)
|
||||
|
||||
```
|
||||
In this tutorial, you create an AutoML tabular binary classification model from a Python script, and then do a batch prediction with Explainable AI using the Vertex AI SDK.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -126,10 +165,13 @@ The steps performed include:
|
||||
- Make a batch prediction with JSONL list input.
|
||||
- Make a batch prediction with BigQuery table input.
|
||||
- Make a batch prediction with explanations.
|
||||
```
|
||||
|
||||
[Get started with re-importing AutoML tabular models](community/ml_ops/stage6/get_started_with_automl_tabular_exported_deploy.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `AutoML Tabular` for re-importing exported model artifacts as a `Model` resource. This is useful for example, if one wants to move the exported model across projects.
|
||||
[Get started with re-importing AutoML tabular models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_automl_tabular_exported_deploy.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `AutoML Tabular` for re-importing exported model artifacts as a `Model` resource.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -138,19 +180,44 @@ The steps performed include:
|
||||
- Deploy the `Model` resource to the `Endpoint` resource.
|
||||
- Make a prediction.
|
||||
|
||||
[Get started with Vertex AI Batch Prediction for AutoML text models](community/ml_ops/stage6/get_started_with_automl_text_model_batch.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Batch Prediction` with a `AutoML` text model.
|
||||
|
||||
[Get started with Vertex AI Online Prediction for XGBoost custom models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_xgboost_model_online.ipynb)
|
||||
|
||||
```
|
||||
In this tutorial, you deploy an XGBoost model, and then do an online prediction using the Vertex AI SDK.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Upload an XGBoost model as a Vertex AI Model resource.
|
||||
- Deploy the model to a Vertex AI Endpoint resource.
|
||||
- Make an online prediction.
|
||||
- Construct a Vertex AI Pipeline:
|
||||
- Upload an XGBoost model as a Vertex AI Model resource.
|
||||
- Deploy the model to a Vertex AI Endpoint resource.
|
||||
- Make an online prediction
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Get started with Vertex AI Batch Prediction for AutoML text models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_automl_text_model_batch.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Batch Prediction` with a `AutoML` text model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Create a Vertex `Dataset` resource.
|
||||
- Train an `AutoML` model.
|
||||
- Make a batch prediction with JSONL input
|
||||
```
|
||||
|
||||
[Get started with Vertex AI Prediction for AutoML text models](community/ml_ops/stage6/get_started_with_automl_text_model_online.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Prediction` with a `AutoML` text model.
|
||||
[Get started with Vertex AI Prediction for AutoML text models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_automl_text_model_online.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Prediction` with a `AutoML` text model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -159,9 +226,13 @@ The steps performed include:
|
||||
- Deploy the model to an `Endpoint` resource.
|
||||
- Make an online prediction.
|
||||
|
||||
[Get started with TensorFlow serving functions with Vertex AI Raw Prediction](community/ml_ops/stage6/get_started_with_raw_predict.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Raw Prediction` on a `Vertex AI Endpoint` resource.
|
||||
|
||||
[Get started with TensorFlow serving functions with Vertex AI Raw Prediction](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_raw_predict.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Raw Prediction` on a `Vertex AI Endpoint` resource.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -171,9 +242,13 @@ The steps performed include:
|
||||
- Deploying the `Model` resource to an `Endpoint` resource.
|
||||
- Make an online raw prediction to the `Model` resource instance deployed to the `Endpoint` resource.
|
||||
|
||||
[Get started with TensorFlow serving functions with Vertex AI Prediction](community/ml_ops/stage6/get_started_with_tf_serving_function.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Prediction` on a `Vertex AI Endpoint` resource with a serving function.
|
||||
|
||||
[Get started with TensorFlow serving functions with Vertex AI Prediction](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_tf_serving_function.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Prediction` on a `Vertex AI Endpoint` resource with a serving function.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -184,13 +259,17 @@ The steps performed include:
|
||||
- Deploying the `Model` resource to an `Endpoint` resource.
|
||||
- Make an online prediction to the `Model` resource instance deployed to the `Endpoint` resource.
|
||||
|
||||
[Get started with Vertex Explainable AI using custom deployment container](community/ml_ops/stage6/get_started_with_xai_and_custom_server.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn to build a custom container to serve a PyTorch model on `Vertex AI Endpoint`.
|
||||
|
||||
[Get started with Vertex Explainable AI using custom deployment container](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_xai_and_custom_server.ipynb)
|
||||
|
||||
```
|
||||
Learn to build a custom container to serve a PyTorch model on `Vertex AI Endpoint`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Locally train a Pytorch tabular classifier.
|
||||
- Locally train a PyTorch tabular classifier.
|
||||
- Locally test the trained model.
|
||||
- Build a HTTP server using FastAPI.
|
||||
- Create a custom serving container with the trained model and FastAPI server.
|
||||
@@ -201,9 +280,13 @@ The steps performed include:
|
||||
- Make a prediction request to the deployed custom serving container.
|
||||
- Make an explanation request to the deployed custom serving container.
|
||||
|
||||
[Get started with Vertex AI Online Prediction for AutoML image models](community/ml_ops/stage6/get_started_with_automl_image_model_online.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you create an AutoML image classification model from a Python script, and then do an online prediction using the Vertex AI SDK.
|
||||
|
||||
[Get started with Vertex AI Online Prediction for AutoML image models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_automl_image_model_online.ipynb)
|
||||
|
||||
```
|
||||
In this tutorial, you create an AutoML image classification model from a Python script, and then do an online prediction using the Vertex AI SDK.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -211,9 +294,13 @@ The steps performed include:
|
||||
- Train an `AutoML` image classification model.
|
||||
- Make an online prediction.
|
||||
|
||||
[Get started with FastAPI with Vertex AI Prediction](community/ml_ops/stage6/get_started_with_fastapi.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Prediction` on a `Vertex AI Endpoint` with a custom serving binary using `FastAPI`.
|
||||
|
||||
[Get started with FastAPI with Vertex AI Prediction](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_fastapi.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Prediction` on a `Vertex AI Endpoint` with a custom serving binary using `FastAPI`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -224,9 +311,13 @@ The steps performed include:
|
||||
- Deploying the `Model` resource to an `Endpoint` resource with `FastAPI` custom serving binary.
|
||||
- Make an online prediction to the `Model` resource instance deployed to the `Endpoint` resource.
|
||||
|
||||
[Get started with Vertex AI Online Prediction for AutoML tabular models](community/ml_ops/stage6/get_started_with_automl_tabular_model_online.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you create an AutoML tabular binary classification model from a Python script, and then do an online prediction using the Vertex AI SDK.
|
||||
|
||||
[Get started with Vertex AI Online Prediction for AutoML tabular models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_automl_tabular_model_online.ipynb)
|
||||
|
||||
```
|
||||
In this tutorial, you create an AutoML tabular binary classification model from a Python script, and then do an online prediction using the Vertex AI SDK.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -236,9 +327,13 @@ The steps performed include:
|
||||
- Make an online prediction.
|
||||
- Make an online prediction with explanations.
|
||||
|
||||
[Get started with TensorFlow Serving with Vertex AI Prediction](community/ml_ops/stage6/get_started_with_tf_serving.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Prediction` on a `Vertex AI Endpoint` resource with `TensorFlow Serving` serving binary.
|
||||
|
||||
[Get started with TensorFlow Serving with Vertex AI Prediction](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_tf_serving.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Prediction` on a `Vertex AI Endpoint` resource with `TensorFlow Serving` serving binary.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -250,9 +345,13 @@ The steps performed include:
|
||||
- Make an online prediction to the `Model` resource instance deployed to the `Endpoint` resource.
|
||||
- Make a batch prediction to the `Model` resource instance.
|
||||
|
||||
[Get started with Custom Prediction Routine (CPR)](community/ml_ops/stage6/get_started_with_cpr.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use Custom Prediction Routine (CPR) for `Vertex AI Predictions`.
|
||||
|
||||
[Get started with Custom Prediction Routine (CPR)](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_cpr.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use Custom Prediction Routine (CPR) for `Vertex AI Predictions`.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -278,19 +377,26 @@ The steps performed include:
|
||||
- Upload and deploy the model serving container to Vertex AI Endpoint.
|
||||
- Make a prediction request.
|
||||
|
||||
[Get started with Vertex AI Batch Prediction for custom text models](community/ml_ops/stage6/get_started_with_custom_text_model_batch.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Batch Prediction` with a custom text model.
|
||||
|
||||
[Get started with Vertex AI Batch Prediction for custom text models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_custom_text_model_batch.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Batch Prediction` with a custom text model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Download a pretrained TensorFlow RNN model.
|
||||
- Upload the pretrained model as a `Vertex AI Model` resource.
|
||||
- Make batch prediction to the `Model` resource, in JSONL format.
|
||||
```
|
||||
|
||||
[Get started with NVIDIA Triton server](community/ml_ops/stage6/get_started_with_nvidia_triton_serving.ipynb)
|
||||
|
||||
In this tutorial, you deploy a container running Nvidia Triton Server with a `Vertex AI Model` resource to a `Vertex AI Endpoint` for making online predictions.
|
||||
[Get started with NVIDIA Triton server](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_nvidia_triton_serving.ipynb)
|
||||
|
||||
```
|
||||
Learn how to deploy a container running Nvidia Triton Server with a `Vertex AI Model` resource to a `Vertex AI Endpoint` for making online predictions.
|
||||
|
||||
The steps performed in this tutorial include:
|
||||
|
||||
@@ -302,9 +408,13 @@ The steps performed in this tutorial include:
|
||||
- Make a prediction request
|
||||
- Undeploy the `Model` resource and delete the `Endpoint`
|
||||
|
||||
[Get started with Vertex AI Batch Prediction for custom image models](community/ml_ops/stage6/get_started_with_custom_image_model_batch.ipynb)
|
||||
```
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Batch Prediction` with a custom image model.
|
||||
|
||||
[Get started with Vertex AI Batch Prediction for custom image models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_custom_image_model_batch.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Batch Prediction` with a custom image model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -314,13 +424,17 @@ The steps performed include:
|
||||
- Create a serving function to receive compressed image data, and output decomopressed preprocessed data for the model input.
|
||||
- Upload the TensorFlow Hub model and serving function as a `Vertex AI Model` resource.
|
||||
- Make batch prediction with compressed image data to the `Model` resource, in File-List format.
|
||||
```
|
||||
|
||||
[Get started with Vertex AI Batch Prediction for AutoML video models](community/ml_ops/stage6/get_started_with_automl_video_model_batch.ipynb)
|
||||
|
||||
In this tutorial, you learn how to use `Vertex AI Batch Prediction` with a `AutoML` video model.
|
||||
[Get started with Vertex AI Batch Prediction for AutoML video models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage6/get_started_with_automl_video_model_batch.ipynb)
|
||||
|
||||
```
|
||||
Learn how to use `Vertex AI Batch Prediction` with a `AutoML` video model.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Create a Vertex `Dataset` resource.
|
||||
- Train an `AutoML` model.
|
||||
- Make a batch prediction with JSONL input.
|
||||
- Make a batch prediction with JSONL input
|
||||
```
|
||||
|
||||
@@ -35,9 +35,28 @@ This stage may be done entirely by MLOps. We recommend:
|
||||
|
||||
### Get Started
|
||||
|
||||
[Vertex AI Model Monitoring for custom tabular models with TensorFlow Serving container](community/ml_ops/stage7/get_started_with_model_monitoring_custom_tf_serving.ipynb)
|
||||
[Vertex AI Model Monitoring for XGBoost models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage7/get_started_with_model_monitoring_xgboost.ipynb)
|
||||
|
||||
In this notebook, you learn to use the `Vertex AI Model Monitoring` service to detect feature skew and drift in the input predict requests, for custom tabular models, using a custom deployment container.
|
||||
```
|
||||
Learn to use the `Vertex AI Model Monitoring` service to detect feature skew and drift in the input predict requests for XGBoost models.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
- Download a pre-trained XGBoost model.
|
||||
- Upload the pre-trained model as a `Model` resource.
|
||||
- Deploy the `Model` resource to the `Endpoint` resource.
|
||||
- Configure the `Endpoint` resource for model monitoring:
|
||||
- drift detection only -- no access to training data.
|
||||
- predefine the input schema to map feature alias names to the unnamed array input to the model.
|
||||
- Generate synthetic prediction requests for drift.
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Vertex AI Model Monitoring for custom tabular models with TensorFlow Serving container](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage7/get_started_with_model_monitoring_custom_tf_serving.ipynb)
|
||||
|
||||
```
|
||||
Learn to use the `Vertex AI Model Monitoring` service to detect feature skew and drift in the input predict requests, for custom tabular models, using a custom deployment container.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -50,11 +69,13 @@ The steps performed include:
|
||||
- Generate synthetic prediction requests for drift.
|
||||
- Wait for email alert notification.
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Vertex AI Model Monitoring for AutoML tabular models](community/ml_ops/stage7/get_started_with_model_monitoring_automl.ipynb)
|
||||
[Vertex AI Model Monitoring for AutoML tabular models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage7/get_started_with_model_monitoring_automl.ipynb)
|
||||
|
||||
In this notebook, you learn to use the `Vertex AI Model Monitoring` service to detect feature skew and drift in the input predict requests, for AutoML tabular models.
|
||||
```
|
||||
Learn to use the `Vertex AI Model Monitoring` service to detect feature skew and drift in the input predict requests, for AutoML tabular models.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -66,10 +87,13 @@ The steps performed include:
|
||||
- Generate synthetic prediction requests for drift.
|
||||
- Wait for email alert notification.
|
||||
|
||||
```
|
||||
|
||||
[Vertex AI Model Monitoring for custom tabular models](community/ml_ops/stage7/get_started_with_model_monitoring_custom.ipynb)
|
||||
|
||||
In this notebook, you learn to use the `Vertex AI Model Monitoring` service to detect feature skew and drift in the input predict requests, for custom tabular models.
|
||||
[Vertex AI Model Monitoring for custom tabular models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage7/get_started_with_model_monitoring_custom.ipynb)
|
||||
|
||||
```
|
||||
Learn to use the `Vertex AI Model Monitoring` service to detect feature skew and drift in the input predict requests, for custom tabular models.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -82,11 +106,13 @@ The steps performed include:
|
||||
- Generate synthetic prediction requests for drift.
|
||||
- Wait for email alert notification.
|
||||
|
||||
```
|
||||
|
||||
|
||||
[Vertex AI Model Monitoring for setup for tabular models](community/ml_ops/stage7/get_started_with_model_monitoring_setup.ipynb)
|
||||
[Vertex AI Model Monitoring for setup for tabular models](https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/ml_ops/stage7/get_started_with_model_monitoring_setup.ipynb)
|
||||
|
||||
In this notebook, you learn to setup the `Vertex AI Model Monitoring` service to detect feature skew and drift in the input predict requests.
|
||||
```
|
||||
Learn to setup the `Vertex AI Model Monitoring` service to detect feature skew and drift in the input predict requests.
|
||||
|
||||
The steps performed include:
|
||||
|
||||
@@ -100,3 +126,5 @@ The steps performed include:
|
||||
- List, pause, resume and delete monitoring jobs.
|
||||
- Restart monitoring job with predefined `input schema`.
|
||||
- View logged monitored data.
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,468 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2bd716bf3e39"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - BLIP2\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_blip2.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_blip2.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_blip2.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d8cd12648da4"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates deploying the pre-trained [BLIP2](https://huggingface.co/Salesforce/blip2-opt-2.7b) model on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for image captioning.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0f826ff482a2"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8958ebc71868"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9db30f827a65"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "92f16e22c20b"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1680c257acfb"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6ca48b699d17"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "de9882ea89ea"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built serving docker image.\n",
|
||||
"# The model artifacts are embedded within the container, except for model weights which will be downloaded during deployment.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-transformers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "10188266a5cd"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "cac4478ae098"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"blip-image-captioning\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/transformers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_T4\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d2d72ecdb8c9"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "9448c5f545fa"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the pre-trained model to Model Registry and deploys it on the Endpoint with 1 T4 GPU.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send images to get descriptions."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "19e8aeec969c"
|
||||
},
|
||||
"source": [
|
||||
"### Image captioning"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b4b46c28d8b1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"Salesforce/blip2-opt-2.7b\", task=\"image-to-text\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "12893aa2c5af"
|
||||
},
|
||||
"source": [
|
||||
"NOTE: The model weights will be downloaded after the deployment succeeds. When the model is very large it could add 5~15mins additional time before the endpoint is ready for prediction."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "6be655247cb1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"image = download_image(\"http://images.cocodataset.org/val2017/000000039769.jpg\")\n",
|
||||
"display(image)\n",
|
||||
"\n",
|
||||
"instances = [\n",
|
||||
" {\"image\": image_to_base64(image)},\n",
|
||||
"]\n",
|
||||
"preds = endpoint.predict(instances=instances).predictions\n",
|
||||
"print(preds)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2ccf3714dbe9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "01e11d85d504"
|
||||
},
|
||||
"source": [
|
||||
"### VQA (Visual-Question-Answering)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "26018d961cf9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"Salesforce/blip2-opt-2.7b\", task=\"visual-question-answering\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0ac7f8d945e3"
|
||||
},
|
||||
"source": [
|
||||
"NOTE: The model weights will be downloaded after the deployment succeeds. When the model is very large it could add 5~15mins additional time before the endpoint is ready for prediction."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "f19c342829fd"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"image = download_image(\n",
|
||||
" \"https://media.newyorker.com/cartoons/63dc6847be24a6a76d90eb99/master/w_1160,c_limit/230213_a26611_838.jpg\"\n",
|
||||
")\n",
|
||||
"display(image)\n",
|
||||
"\n",
|
||||
"question = \"Question: What are they doing? Answer:\"\n",
|
||||
"instances = [\n",
|
||||
" {\"image\": image_to_base64(image), \"text\": question},\n",
|
||||
"]\n",
|
||||
"preds = endpoint.predict(instances=instances).predictions\n",
|
||||
"print(question)\n",
|
||||
"print(preds)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "712eb9d0b336"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_blip2.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2bd716bf3e39"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - BLIP Image Captioning\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_blip_image_captioning.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_blip_image_captioning.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_blip_image_captioning.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d8cd12648da4"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates deploying the pre-trained [BLIP Image Captioning](https://huggingface.co/Salesforce/blip-image-captioning-base) model on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for image captioning.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0f826ff482a2"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8958ebc71868"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9db30f827a65"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "92f16e22c20b"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1680c257acfb"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6ca48b699d17"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "de9882ea89ea"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-transformers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "10188266a5cd"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "cac4478ae098"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"blip-image-captioning\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/transformers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_T4\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d2d72ecdb8c9"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "9448c5f545fa"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the pre-trained model to Model Registry and deploys it on the Endpoint with 1 T4 GPU.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send images to get descriptions."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b4b46c28d8b1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"Salesforce/blip-image-captioning-base\", task=\"image-to-text\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "6be655247cb1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"image = download_image(\"http://images.cocodataset.org/val2017/000000039769.jpg\")\n",
|
||||
"display(image)\n",
|
||||
"\n",
|
||||
"instances = [\n",
|
||||
" {\"image\": image_to_base64(image)},\n",
|
||||
"]\n",
|
||||
"preds = endpoint.predict(instances=instances).predictions\n",
|
||||
"print(preds)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "db7ffebdb4be"
|
||||
},
|
||||
"source": [
|
||||
"### Clean up resources"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2ccf3714dbe9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_blip_image_captioning.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2bd716bf3e39"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - BLIP VQA\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_blip_vqa.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_blip_vqa.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_blip_vqa.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d8cd12648da4"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates deploying the pre-trained [BLIP VQA](https://huggingface.co/Salesforce/blip-vqa-base) model on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for image captioning.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0f826ff482a2"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8958ebc71868"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9db30f827a65"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "92f16e22c20b"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1680c257acfb"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6ca48b699d17"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "de9882ea89ea"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-transformers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "10188266a5cd"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "cac4478ae098"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"blip-vqa\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/transformers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_T4\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d2d72ecdb8c9"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "9448c5f545fa"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the pre-trained model to Model Registry and deploys it on the Endpoint with 1 T4 GPU.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send images and questions to get answers."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b4b46c28d8b1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"Salesforce/blip-vqa-base\", task=\"visual-question-answering\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "6be655247cb1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"image = download_image(\"http://images.cocodataset.org/val2017/000000039769.jpg\")\n",
|
||||
"display(image)\n",
|
||||
"\n",
|
||||
"question = \"Which cat is bigger?\"\n",
|
||||
"instances = [\n",
|
||||
" {\"image\": image_to_base64(image), \"text\": question},\n",
|
||||
"]\n",
|
||||
"preds = endpoint.predict(instances=instances).predictions\n",
|
||||
"print(question)\n",
|
||||
"print(preds)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "db7ffebdb4be"
|
||||
},
|
||||
"source": [
|
||||
"### Clean up resources"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2ccf3714dbe9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_blip_vqa.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2bd716bf3e39"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - CLIP\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_clip.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_clip.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_clip.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d8cd12648da4"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates deploying the pre-trained [CLIP](https://huggingface.co/openai/clip-vit-base-patch32) model on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for image captioning.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0f826ff482a2"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8958ebc71868"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9db30f827a65"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "92f16e22c20b"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1680c257acfb"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6ca48b699d17"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "de9882ea89ea"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-transformers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "10188266a5cd"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "cac4478ae098"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"clip\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/transformers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_T4\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d2d72ecdb8c9"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "9448c5f545fa"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the pre-trained model to Model Registry and deploys it on the Endpoint with 1 T4 GPU.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send images and object texts to get classification results."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b4b46c28d8b1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"openai/clip-vit-base-patch32\", task=\"zero-shot-image-classification\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "6be655247cb1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"image1 = download_image(\"http://images.cocodataset.org/val2017/000000039769.jpg\")\n",
|
||||
"image2 = download_image(\"http://images.cocodataset.org/val2017/000000000285.jpg\")\n",
|
||||
"grid = image_grid([image1, image2], 1, 2)\n",
|
||||
"display(grid)\n",
|
||||
"\n",
|
||||
"instances = [\n",
|
||||
" {\"image\": image_to_base64(image1), \"text\": \"two cats\"},\n",
|
||||
" {\"image\": image_to_base64(image2), \"text\": \"a bear\"},\n",
|
||||
"]\n",
|
||||
"preds = endpoint.predict(instances=instances).predictions\n",
|
||||
"print(preds)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "db7ffebdb4be"
|
||||
},
|
||||
"source": [
|
||||
"### Clean up resources"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2ccf3714dbe9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_clip.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,622 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "99c1c3fc2ca5"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - ControlNet\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_controlnet.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_controlnet.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_controlnet.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "3de7470326a2"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates finetuning the [ControlNet](https://huggingface.co/lllyasviel/ControlNet) with the [fusing/fill50k](https://huggingface.co/datasets/fusing/fill50k) dataset and deploying the model on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Finetune the ControlNet model.\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for text-guided-image-to-image.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "fb671e75ca7b"
|
||||
},
|
||||
"source": [
|
||||
"### Install dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "dc8ee367fb42"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Install gdown for downloading example training images.\n",
|
||||
"!pip install gdown\n",
|
||||
"# Install libs for generating conditioning images for ControlNet.\n",
|
||||
"!pip install opencv-python"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "5244aac3d929"
|
||||
},
|
||||
"source": [
|
||||
"Restart the notebook kernel after installs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "567212ff53a6"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import IPython\n",
|
||||
"\n",
|
||||
"app = IPython.Application.instance()\n",
|
||||
"app.kernel.do_shutdown(True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "bb7adab99e41"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6c460088b873"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "855d6b96f291"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "e828eb320337"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "12cd25839741"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2cc825514deb"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b42bd4fa2b2d"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built training docker image. It contains training scripts and models.\n",
|
||||
"TRAIN_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-diffusers-train:latest\"\n",
|
||||
"\n",
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-diffusers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0c250872074f"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"id": "354da31189dc"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import cv2\n",
|
||||
"import numpy as np\n",
|
||||
"import requests\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def canny(image):\n",
|
||||
" image = np.array(image)\n",
|
||||
" image = cv2.Canny(image, 100, 200)\n",
|
||||
" image = image[:, :, None]\n",
|
||||
" image = np.concatenate([image, image, image], axis=2)\n",
|
||||
" image = Image.fromarray(image)\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"controlnet\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/diffusers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_V100\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "e70e3519ff8b"
|
||||
},
|
||||
"source": [
|
||||
"## Finetune with fill50k dataset"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0dc65d8f0689"
|
||||
},
|
||||
"source": [
|
||||
"This section uses the [fusing/fill50k](https://huggingface.co/datasets/fusing/fill50k) dataset to finetune the ControlNet model.\n",
|
||||
"\n",
|
||||
"The job will run on 1 A100 GPU and take ~7 hours to finish 1 epoch of training.\n",
|
||||
"\n",
|
||||
"The ControlNet model will be saved after the finetuning job finishs and it can be loaded to run inference later."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "65467b361315"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-trained stable diffusion model to be loaded.\n",
|
||||
"stable_diffusion_model_id = \"runwayml/stable-diffusion-v1-5\"\n",
|
||||
"# The datase id to be loaded.\n",
|
||||
"dataset_id = \"fusing/fill50k\"\n",
|
||||
"# The output path.\n",
|
||||
"output_dir = f\"/gcs/{GCS_BUCKET}/controlnet/output\"\n",
|
||||
"\n",
|
||||
"# Worker pool spec.\n",
|
||||
"machine_type = \"a2-highgpu-1g\"\n",
|
||||
"num_nodes = 1\n",
|
||||
"gpu_type = \"NVIDIA_TESLA_A100\"\n",
|
||||
"num_gpus = 1\n",
|
||||
"\n",
|
||||
"# Setup training job.\n",
|
||||
"job_name = create_job_name(\"controlnet\")\n",
|
||||
"job = aiplatform.CustomContainerTrainingJob(\n",
|
||||
" display_name=job_name,\n",
|
||||
" container_uri=TRAIN_DOCKER_URI,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# Pass training arguments and launch job.\n",
|
||||
"# See https://github.com/huggingface/diffusers/blob/main/examples/controlnet/train_controlnet.py\n",
|
||||
"# for a full list of training arguments.\n",
|
||||
"model = job.run(\n",
|
||||
" args=[\n",
|
||||
" \"controlnet/train_controlnet.py\",\n",
|
||||
" \"--tracker_project_name=train_controlnet\",\n",
|
||||
" f\"--pretrained_model_name_or_path={stable_diffusion_model_id}\",\n",
|
||||
" f\"--output_dir={output_dir}\",\n",
|
||||
" f\"--dataset_name={dataset_id}\",\n",
|
||||
" \"--resolution=512\",\n",
|
||||
" \"--learning_rate=1e-5\",\n",
|
||||
" \"--train_batch_size=2\",\n",
|
||||
" ],\n",
|
||||
" replica_count=num_nodes,\n",
|
||||
" machine_type=machine_type,\n",
|
||||
" accelerator_type=gpu_type,\n",
|
||||
" accelerator_count=num_gpus,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "bf7f82732e61"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and Deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "1cc26e68d7b0"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the model to Model Registry and deploys it on the Endpoint.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "cd7b56421392"
|
||||
},
|
||||
"source": [
|
||||
"### Pre-trained canny model"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6d331b1ea337"
|
||||
},
|
||||
"source": [
|
||||
"Deploy the pre-trained [lllyasviel/sd-controlnet-canny](https://huggingface.co/lllyasviel/sd-controlnet-canny) model for the text-guided image-to-image task. When deployed on one V100 GPU, the average inference time of a request is ~15 seconds."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "bf55e38815dc"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"lllyasviel/sd-controlnet-canny\", task=\"controlnet\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "4ab04da3ec9a"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"init_image = download_image(\n",
|
||||
" \"https://huggingface.co/takuma104/controlnet_dev/resolve/main/gen_compare/output_images/diffusers/output_bird_canny_1.png\"\n",
|
||||
")\n",
|
||||
"display(init_image)\n",
|
||||
"image = canny(init_image)\n",
|
||||
"display(image)\n",
|
||||
"\n",
|
||||
"instances = [\n",
|
||||
" {\n",
|
||||
" \"prompt\": \"bird\",\n",
|
||||
" \"image\": image_to_base64(image),\n",
|
||||
" },\n",
|
||||
"]\n",
|
||||
"response = endpoint.predict(instances=instances)\n",
|
||||
"images = [base64_to_image(image) for image in response.predictions]\n",
|
||||
"display(images[0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "af21a3cff1e0"
|
||||
},
|
||||
"source": [
|
||||
"Clean up resources:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "911406c1561e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Delete models.\n",
|
||||
"model.delete()\n",
|
||||
"\n",
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "c1e51f764a60"
|
||||
},
|
||||
"source": [
|
||||
"### Custom finetuned fill50k model"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "fa686a54047c"
|
||||
},
|
||||
"source": [
|
||||
"Deploy the finetuned fill50k model above for the text-guided image-to-image task. When deployed on one V100 GPU, the averaged inference time of a request is ~15 seconds."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "65e32356fbd1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=f\"gs://{GCS_BUCKET}/controlnet/output\", task=\"image-to-image\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "83a50fd4a1ed"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"init_image = download_image(\n",
|
||||
" \"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/controlnet_training/conditioning_image_1.png\"\n",
|
||||
")\n",
|
||||
"display(init_image)\n",
|
||||
"\n",
|
||||
"instances = [\n",
|
||||
" {\n",
|
||||
" \"prompt\": \"red circle with green background\",\n",
|
||||
" \"image\": image_to_base64(init_image, format=\"PNG\"),\n",
|
||||
" },\n",
|
||||
"]\n",
|
||||
"response = endpoint.predict(instances=instances)\n",
|
||||
"images = [base64_to_image(image) for image in response.predictions]\n",
|
||||
"display(images[0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ed3795d474b9"
|
||||
},
|
||||
"source": [
|
||||
"Clean up resources:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b53b883257b4"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_controlnet.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2bd716bf3e39"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - InstructPix2Pix\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_instructpix2pix.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_instructpix2pix.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_instructpix2pix.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d8cd12648da4"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates deploying the pre-trained [InstructPix2Pix](https://huggingface.co/timbrooks/instruct-pix2pix) model on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for text-guided image-to-image.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0f826ff482a2"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8958ebc71868"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9db30f827a65"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "92f16e22c20b"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1680c257acfb"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6ca48b699d17"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "de9882ea89ea"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-diffusers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "10188266a5cd"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "cac4478ae098"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"instruct-pix2pix\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/diffusers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_V100\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d2d72ecdb8c9"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "9448c5f545fa"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the pre-trained model to Model Registry and deploys it on the Endpoint.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "c277da31bde6"
|
||||
},
|
||||
"source": [
|
||||
"### Text-guided image-to-image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "a5a86996222c"
|
||||
},
|
||||
"source": [
|
||||
"Deploy the InstructPix2Pix model for the text-guided image-to-image task.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send prompts to the endpoint to generated images.\n",
|
||||
"\n",
|
||||
"When deployed on one V100 GPU, the averaged inference time of a request is ~15 seconds."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b4b46c28d8b1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"timbrooks/instruct-pix2pix\", task=\"instruct-pix2pix\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "6be655247cb1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"init_image = download_image(\n",
|
||||
" \"https://huggingface.co/datasets/diffusers/diffusers-images-docs/resolve/main/mountain.png\"\n",
|
||||
")\n",
|
||||
"display(init_image)\n",
|
||||
"instances = [\n",
|
||||
" {\n",
|
||||
" \"prompt\": \"Add fire to the mountain\",\n",
|
||||
" \"image\": image_to_base64(init_image),\n",
|
||||
" },\n",
|
||||
"]\n",
|
||||
"response = endpoint.predict(instances=instances)\n",
|
||||
"images = [base64_to_image(image) for image in response.predictions]\n",
|
||||
"display(images[0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "db7ffebdb4be"
|
||||
},
|
||||
"source": [
|
||||
"### Clean up resources"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2ccf3714dbe9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_instructpix2pix.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2bd716bf3e39"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - LayoutML Document QA\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_layoutml_document_qa.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_layoutml_document_qa.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_layoutml_document_qa.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d8cd12648da4"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates deploying the pre-trained [LayoutML](https://huggingface.co/impira/layoutlm-document-qa) model on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for image captioning.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0f826ff482a2"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8958ebc71868"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9db30f827a65"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "92f16e22c20b"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1680c257acfb"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6ca48b699d17"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "de9882ea89ea"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-transformers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "10188266a5cd"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "cac4478ae098"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content)).convert(\"RGB\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"layoutml\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/transformers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_T4\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d2d72ecdb8c9"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "9448c5f545fa"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the pre-trained model to Model Registry and deploys it on the Endpoint with 1 T4 GPU.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send document images and questions to get answers."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b4b46c28d8b1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"impira/layoutlm-document-qa\", task=\"document-question-answering\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "6be655247cb1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"image = download_image(\n",
|
||||
" \"https://huggingface.co/spaces/impira/docquery/resolve/2359223c1837a7587402bda0f2643382a6eefeab/invoice.png\"\n",
|
||||
")\n",
|
||||
"display(image)\n",
|
||||
"\n",
|
||||
"question = \"What is the name of the signer?\"\n",
|
||||
"instances = [\n",
|
||||
" {\"image\": image_to_base64(image), \"text\": \"\"},\n",
|
||||
"]\n",
|
||||
"preds = endpoint.predict(instances=instances).predictions\n",
|
||||
"print(question)\n",
|
||||
"print(preds)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "db7ffebdb4be"
|
||||
},
|
||||
"source": [
|
||||
"### Clean up resources"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2ccf3714dbe9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_layoutml_document_qa.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,409 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2bd716bf3e39"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - OWL-ViT\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_owlvit.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_owlvit.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_owlvit.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d8cd12648da4"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates deploying the pre-trained [OWL-ViT](https://huggingface.co/google/owlvit-base-patch32) model on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for image captioning.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0f826ff482a2"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8958ebc71868"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9db30f827a65"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "92f16e22c20b"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1680c257acfb"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6ca48b699d17"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "de9882ea89ea"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-transformers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "10188266a5cd"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "cac4478ae098"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import matplotlib.patches as patches\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def draw_image_with_boxes(image, boxes):\n",
|
||||
" fig, ax = plt.subplots()\n",
|
||||
" plt.axis(\"off\")\n",
|
||||
" ax.imshow(image)\n",
|
||||
" if len(boxes) == 0:\n",
|
||||
" return\n",
|
||||
" boxes = boxes[\"boxes\"]\n",
|
||||
" for box in boxes:\n",
|
||||
" x, y = box[\"xmin\"], box[\"ymin\"]\n",
|
||||
" width, height = box[\"xmax\"] - x, box[\"ymax\"] - y\n",
|
||||
" rect = patches.Rectangle(\n",
|
||||
" (x, y), width, height, linewidth=2, edgecolor=\"yellow\", facecolor=\"none\"\n",
|
||||
" )\n",
|
||||
" ax.add_patch(rect)\n",
|
||||
" plt.show()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"owl-vit\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/transformers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_T4\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d2d72ecdb8c9"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "9448c5f545fa"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the pre-trained model to Model Registry and deploys it on the Endpoint with 1 T4 GPU.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send images and object texts to get bounding boxes."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b4b46c28d8b1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"google/owlvit-base-patch32\", task=\"zero-shot-object-detection\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "6be655247cb1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"image = download_image(\"http://images.cocodataset.org/val2017/000000039769.jpg\")\n",
|
||||
"\n",
|
||||
"instances = [\n",
|
||||
" {\"image\": image_to_base64(image), \"text\": \"cat\"},\n",
|
||||
"]\n",
|
||||
"preds = endpoint.predict(instances=instances).predictions\n",
|
||||
"draw_image_with_boxes(image, preds[0])\n",
|
||||
"print(preds)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "db7ffebdb4be"
|
||||
},
|
||||
"source": [
|
||||
"### Clean up resources"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2ccf3714dbe9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_owlvit.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,648 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "99c1c3fc2ca5"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - Stable Diffusion V1.5\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_stable_diffusion.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_stable_diffusion.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_stable_diffusion.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "3de7470326a2"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates finetuning [runwayml/stable-diffusion-v1-5](https://huggingface.co/runwayml/stable-diffusion-v1-5) with [Dreambooth](https://huggingface.co/docs/diffusers/training/dreambooth) and deploying it on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Finetune the stable-diffusion-v1.5 model with [Dreambooth](https://huggingface.co/docs/diffusers/training/dreambooth).\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for text-to-image and text-guided-image-to-image.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "fb671e75ca7b"
|
||||
},
|
||||
"source": [
|
||||
"### Install dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "dc8ee367fb42"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Install gdown for downloading example training images.\n",
|
||||
"!pip install gdown\n",
|
||||
"# Install gsutil for downloading/uploading data from/to Cloud Storage buckets.\n",
|
||||
"!pip install gsutil"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "5244aac3d929"
|
||||
},
|
||||
"source": [
|
||||
"Restart the notebook kernel after installs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "567212ff53a6"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import IPython\n",
|
||||
"\n",
|
||||
"app = IPython.Application.instance()\n",
|
||||
"app.kernel.do_shutdown(True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "bb7adab99e41"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6c460088b873"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "855d6b96f291"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "e828eb320337"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex-AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "12cd25839741"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2cc825514deb"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b42bd4fa2b2d"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built training docker image. It contains training scripts and models.\n",
|
||||
"TRAIN_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-diffusers-train:latest\"\n",
|
||||
"\n",
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-diffusers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0c250872074f"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "354da31189dc"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"stable-diffusion-v1\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-{task}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/diffusers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_V100\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "e70e3519ff8b"
|
||||
},
|
||||
"source": [
|
||||
"## Finetune with Dreambooth"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0dc65d8f0689"
|
||||
},
|
||||
"source": [
|
||||
"This section uses [dreambooth](https://dreambooth.github.io/) to finetune the [stable-diffusion-v1.5](https://huggingface.co/runwayml/stable-diffusion-v1-5) model with [5 dog images](https://drive.google.com/drive/folders/1BO_dyz-p65qhBRRMRA4TbZ8qW4rB99JZ) to personalize the text-to-image model.\n",
|
||||
"\n",
|
||||
"It finetunes both text encoder and unet of the stable diffusion model up to 800 steps. The whole finetuning job takes 30 minutes to finish using 1 A100 GPU.\n",
|
||||
"\n",
|
||||
"The full model will be saved after the finetuning job finishs and it can be loaded by the [StableDiffusionPipeline](https://huggingface.co/docs/diffusers/api/pipelines/stable_diffusion/text2img) to run inference."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "34048707df5c"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Download example training images.\n",
|
||||
"!gdown --folder https://drive.google.com/drive/folders/1BO_dyz-p65qhBRRMRA4TbZ8qW4rB99JZ\n",
|
||||
"\n",
|
||||
"# Upload data to Cloud Storage bucket.\n",
|
||||
"!gsutil -m cp -r dog/* gs://{GCS_BUCKET}/dreambooth/dog/\n",
|
||||
"!gsutil -m cp -r dog/* gs://{GCS_BUCKET}/dreambooth/dog_class/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "969cfeb79317"
|
||||
},
|
||||
"source": [
|
||||
"**NOTE**: If the upload step fails due to lacking of permission, you need to [grant the Storage Object Admin role](https://cloud.google.com/storage/docs/access-control/using-iam-permissions) for the Cloud account of the notebook."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "65467b361315"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-trained model to be loaded.\n",
|
||||
"model_id = \"runwayml/stable-diffusion-v1-5\"\n",
|
||||
"\n",
|
||||
"# Input and output path.\n",
|
||||
"instance_dir = f\"/gcs/{GCS_BUCKET}/dreambooth/dog\"\n",
|
||||
"class_dir = f\"/gcs/{GCS_BUCKET}/dreambooth/dog_class\"\n",
|
||||
"output_dir = f\"/gcs/{GCS_BUCKET}/dreambooth/output\"\n",
|
||||
"\n",
|
||||
"# Worker pool spec.\n",
|
||||
"machine_type = \"a2-highgpu-1g\"\n",
|
||||
"num_nodes = 1\n",
|
||||
"gpu_type = \"NVIDIA_TESLA_A100\"\n",
|
||||
"num_gpus = 1\n",
|
||||
"\n",
|
||||
"# Setup training job.\n",
|
||||
"job_name = create_job_name(\"dreambooth-stable-diffusion\")\n",
|
||||
"job = aiplatform.CustomContainerTrainingJob(\n",
|
||||
" display_name=job_name,\n",
|
||||
" container_uri=TRAIN_DOCKER_URI,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# Pass training arguments and launch job.\n",
|
||||
"# See https://github.com/huggingface/diffusers/blob/v0.14.0/examples/dreambooth/train_dreambooth.py#L75\n",
|
||||
"# for a full list of training arguments.\n",
|
||||
"model = job.run(\n",
|
||||
" args=[\n",
|
||||
" \"dreambooth/train_dreambooth.py\",\n",
|
||||
" f\"--pretrained_model_name_or_path={model_id}\",\n",
|
||||
" \"--train_text_encoder\",\n",
|
||||
" f\"--instance_data_dir={instance_dir}\",\n",
|
||||
" f\"--class_data_dir={class_dir}\",\n",
|
||||
" f\"--output_dir={output_dir}\",\n",
|
||||
" \"--with_prior_preservation\",\n",
|
||||
" \"--prior_loss_weight=1.0\",\n",
|
||||
" \"--instance_prompt='a photo of sks dog'\",\n",
|
||||
" \"--class_prompt='a photo of dog'\",\n",
|
||||
" \"--resolution=512\",\n",
|
||||
" \"--train_batch_size=1\",\n",
|
||||
" \"--gradient_checkpointing\",\n",
|
||||
" \"--learning_rate=2e-6\",\n",
|
||||
" \"--lr_scheduler=constant\",\n",
|
||||
" \"--lr_warmup_steps=0\",\n",
|
||||
" \"--num_class_images=200\",\n",
|
||||
" \"--max_train_steps=800\",\n",
|
||||
" ],\n",
|
||||
" replica_count=num_nodes,\n",
|
||||
" machine_type=machine_type,\n",
|
||||
" accelerator_type=gpu_type,\n",
|
||||
" accelerator_count=num_gpus,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "bf7f82732e61"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and Deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "1cc26e68d7b0"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the model to Model Registry and deploys it on the Endpoint.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "cd7b56421392"
|
||||
},
|
||||
"source": [
|
||||
"### Text-to-image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6d331b1ea337"
|
||||
},
|
||||
"source": [
|
||||
"Deploy the stable diffusion model for the text-to-image task.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send a batch of text prompts to the endpoint to generated images.\n",
|
||||
"\n",
|
||||
"When deployed on one V100 GPU, the averaged inference time of a request is ~15 seconds."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "bf55e38815dc"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Set the model_id to a GCS path, like \"gs://GCS_BUCKET/dreambooth/output\", to load the dreambooth finetuned model above.\n",
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"runwayml/stable-diffusion-v1-5\", task=\"text-to-image\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "4ab04da3ec9a"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"instances = [\n",
|
||||
" {\"prompt\": \"a squirrel in Picasso style\"},\n",
|
||||
" {\"prompt\": \"a dog in Picasso style\"},\n",
|
||||
" {\"prompt\": \"a cat in Picasso style\"},\n",
|
||||
" {\"prompt\": \"a deer in Picasso style\"},\n",
|
||||
"]\n",
|
||||
"response = endpoint.predict(instances=instances)\n",
|
||||
"images = [base64_to_image(image) for image in response.predictions]\n",
|
||||
"image_grid(images)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "af21a3cff1e0"
|
||||
},
|
||||
"source": [
|
||||
"Clean up resources:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "911406c1561e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "c1e51f764a60"
|
||||
},
|
||||
"source": [
|
||||
"### Text-guided image-to-image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "fa686a54047c"
|
||||
},
|
||||
"source": [
|
||||
"Deploy the stable diffusion model for the text-guided image-to-image task."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "65e32356fbd1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Set the model_id to a GCS path, like \"gs://GCS_BUCKET/dreambooth/output\", to load the dreambooth finetuned model above.\n",
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"runwayml/stable-diffusion-v1-5\", task=\"image-to-image\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "83a50fd4a1ed"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"init_image = download_image(\n",
|
||||
" \"https://raw.githubusercontent.com/CompVis/stable-diffusion/main/assets/stable-samples/img2img/sketch-mountains-input.jpg\"\n",
|
||||
")\n",
|
||||
"display(init_image)\n",
|
||||
"instances = [\n",
|
||||
" {\n",
|
||||
" \"prompt\": \"A fantasy landscape, trending on artstation\",\n",
|
||||
" \"image\": image_to_base64(init_image),\n",
|
||||
" },\n",
|
||||
"]\n",
|
||||
"response = endpoint.predict(instances=instances)\n",
|
||||
"images = [base64_to_image(image) for image in response.predictions]\n",
|
||||
"display(images[0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ed3795d474b9"
|
||||
},
|
||||
"source": [
|
||||
"Clean up resources:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b53b883257b4"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_stable_diffusion.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
+577
@@ -0,0 +1,577 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "1e9c07efb6ac"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - Stable Diffusion Inpainting\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_stable_diffusion_inpainting.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_stable_diffusion_inpainting.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_stable_diffusion_inpainting.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "cd8433ec804a"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates finetuning [runwayml/stable-diffusion-inpainting](https://huggingface.co/runwayml/stable-diffusion-inpainting) with [Dreambooth](https://huggingface.co/docs/diffusers/training/dreambooth) and deploying it on Vertex-AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Finetune the stable-diffusion-inpainting model with [Dreambooth](https://huggingface.co/docs/diffusers/training/dreambooth).\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for image-inpainting.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "fb671e75ca7b"
|
||||
},
|
||||
"source": [
|
||||
"### Install dependencies"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "dc8ee367fb42"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Install gdown for downloading example training images.\n",
|
||||
"!pip install gdown\n",
|
||||
"# Install gsutil for downloading/uploading data from/to Cloud Storage buckets.\n",
|
||||
"!pip install gsutil"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "5244aac3d929"
|
||||
},
|
||||
"source": [
|
||||
"Restart the notebook kernel after installs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "567212ff53a6"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import IPython\n",
|
||||
"\n",
|
||||
"app = IPython.Application.instance()\n",
|
||||
"app.kernel.do_shutdown(True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "bb7adab99e41"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6c460088b873"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "855d6b96f291"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "e828eb320337"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex-AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "12cd25839741"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2cc825514deb"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b42bd4fa2b2d"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built training docker image. It contains training scripts and models.\n",
|
||||
"TRAIN_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-diffusers-train:latest\"\n",
|
||||
"\n",
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-diffusers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0c250872074f"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"id": "8759e624ebc0"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"stable-diffusion-inpainting\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/diffusers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_V100\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "e70e3519ff8b"
|
||||
},
|
||||
"source": [
|
||||
"## Finetune with Dreambooth"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "f560edbf96c6"
|
||||
},
|
||||
"source": [
|
||||
"This section uses [dreambooth](https://dreambooth.github.io/) to finetune the [stable-diffusion-inpainting](https://huggingface.co/runwayml/stable-diffusion-inpainting) model with [5 dog images](https://drive.google.com/drive/folders/1BO_dyz-p65qhBRRMRA4TbZ8qW4rB99JZ) to personalize the model.\n",
|
||||
"\n",
|
||||
"It finetunes both text encoder and unet of the stable diffusion model up to 800 steps. The whole finetuning job takes 30 minutes to finish using 1 A100 GPU.\n",
|
||||
"\n",
|
||||
"The full model will be saved after the finetuning job finishs and it can be loaded by the [StableDiffusionInpaintPipeline](https://huggingface.co/docs/diffusers/api/pipelines/stable_diffusion/inpaint) to run inference."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "34048707df5c"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Download example training images.\n",
|
||||
"!gdown --folder https://drive.google.com/drive/folders/1BO_dyz-p65qhBRRMRA4TbZ8qW4rB99JZ\n",
|
||||
"\n",
|
||||
"# Upload data to Cloud Storage bucket.\n",
|
||||
"!gsutil -m cp -r dog/* gs://{GCS_BUCKET}/dreambooth/dog/\n",
|
||||
"!gsutil -m cp -r dog/* gs://{GCS_BUCKET}/dreambooth/dog_class/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "969cfeb79317"
|
||||
},
|
||||
"source": [
|
||||
"**NOTE**: If the upload step fails due to lacking of permission, you need to [grant the Storage Object Admin role](https://cloud.google.com/storage/docs/access-control/using-iam-permissions) for the Cloud account of the notebook."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "f6d5a05592e1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-trained model to be loaded.\n",
|
||||
"model_id = \"runwayml/stable-diffusion-inpainting\"\n",
|
||||
"\n",
|
||||
"# Input and output path.\n",
|
||||
"instance_dir = f\"/gcs/{GCS_BUCKET}/dreambooth/dog\"\n",
|
||||
"class_dir = f\"/gcs/{GCS_BUCKET}/dreambooth/dog_class\"\n",
|
||||
"output_dir = f\"/gcs/{GCS_BUCKET}/dreambooth/output\"\n",
|
||||
"\n",
|
||||
"# Worker pool spec.\n",
|
||||
"machine_type = \"a2-highgpu-1g\"\n",
|
||||
"num_nodes = 1\n",
|
||||
"gpu_type = \"NVIDIA_TESLA_A100\"\n",
|
||||
"num_gpus = 1\n",
|
||||
"\n",
|
||||
"# Setup training job.\n",
|
||||
"job_name = create_job_name(\"dreambooth-stable-diffusion-inpainting\")\n",
|
||||
"job = aiplatform.CustomContainerTrainingJob(\n",
|
||||
" display_name=job_name,\n",
|
||||
" container_uri=TRAIN_DOCKER_URI,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# Pass training arguments and launch job.\n",
|
||||
"# See https://github.com/huggingface/diffusers/blob/v0.14.0/examples/research_projects/dreambooth_inpaint/train_dreambooth_inpaint.py#L83\n",
|
||||
"# for a full list of training arguments.\n",
|
||||
"model = job.run(\n",
|
||||
" args=[\n",
|
||||
" \"research_projects/dreambooth_inpaint/train_dreambooth_inpaint.py\",\n",
|
||||
" f\"--pretrained_model_name_or_path={model_id}\",\n",
|
||||
" \"--train_text_encoder\",\n",
|
||||
" f\"--instance_data_dir={instance_dir}\",\n",
|
||||
" f\"--class_data_dir={class_dir}\",\n",
|
||||
" f\"--output_dir={output_dir}\",\n",
|
||||
" \"--with_prior_preservation\",\n",
|
||||
" \"--prior_loss_weight=1.0\",\n",
|
||||
" \"--instance_prompt='a photo of sks dog'\",\n",
|
||||
" \"--class_prompt='a photo of dog'\",\n",
|
||||
" \"--resolution=512\",\n",
|
||||
" \"--train_batch_size=1\",\n",
|
||||
" \"--gradient_checkpointing\",\n",
|
||||
" \"--learning_rate=2e-6\",\n",
|
||||
" \"--lr_scheduler=constant\",\n",
|
||||
" \"--lr_warmup_steps=0\",\n",
|
||||
" \"--num_class_images=200\",\n",
|
||||
" \"--max_train_steps=800\",\n",
|
||||
" ],\n",
|
||||
" replica_count=num_nodes,\n",
|
||||
" machine_type=machine_type,\n",
|
||||
" accelerator_type=gpu_type,\n",
|
||||
" accelerator_count=num_gpus,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "90d3c379090e"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "1cc26e68d7b0"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the model to Model Registry and deploys it on the Endpoint.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "b8bb7d198315"
|
||||
},
|
||||
"source": [
|
||||
"### Image-inpainting"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "79b66382f849"
|
||||
},
|
||||
"source": [
|
||||
"Deploy the stable diffusion model for the image-inpainting task.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send prompts to the endpoint to generated images.\n",
|
||||
"\n",
|
||||
"When deployed on one V100 GPU, the averaged inference time of a request is ~15 seconds."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "a881564da1d8"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Set the model_id to a GCS path, like \"gs://GCS_BUCKET/dreambooth/output\", to load the dreambooth finetuned model above.\n",
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"runwayml/stable-diffusion-inpainting\", task=\"image-inpainting\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ca1761afb66f"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"img_url = \"https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/bertrand-gabioud-CpuFzIsHYJ0.png\"\n",
|
||||
"mask_url = \"https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/bertrand-gabioud-CpuFzIsHYJ0_mask.png\"\n",
|
||||
"init_image = download_image(img_url).resize((512, 512))\n",
|
||||
"mask_image = download_image(mask_url).resize((512, 512))\n",
|
||||
"display(init_image)\n",
|
||||
"display(mask_image)\n",
|
||||
"\n",
|
||||
"instances = [\n",
|
||||
" {\n",
|
||||
" \"prompt\": \"a tree, high resolution, in front of high buildings\",\n",
|
||||
" \"image\": image_to_base64(init_image),\n",
|
||||
" \"mask_image\": image_to_base64(mask_image),\n",
|
||||
" },\n",
|
||||
"]\n",
|
||||
"response = endpoint.predict(instances=instances)\n",
|
||||
"images = [base64_to_image(image) for image in response.predictions]\n",
|
||||
"display(images[0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "f12f8d9c2786"
|
||||
},
|
||||
"source": [
|
||||
"### Clean up resources"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "911406c1561e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_stable_diffusion_inpainting.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2bd716bf3e39"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - ViLT VQA\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_vilt_vqa.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_vilt_vqa.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_vilt_vqa.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d8cd12648da4"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates deploying the pre-trained [ViLT VQA](https://huggingface.co/dandelin/vilt-b32-finetuned-vqa) model on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for image captioning.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0f826ff482a2"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8958ebc71868"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9db30f827a65"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "92f16e22c20b"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1680c257acfb"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6ca48b699d17"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "de9882ea89ea"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-transformers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "10188266a5cd"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "cac4478ae098"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"vilt-vqa\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/transformers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_T4\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d2d72ecdb8c9"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "9448c5f545fa"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the pre-trained model to Model Registry and deploys it on the Endpoint with 1 T4 GPU.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send images and questions to get answers."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b4b46c28d8b1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"dandelin/vilt-b32-finetuned-vqa\", task=\"visual-question-answering\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "6be655247cb1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"image = download_image(\"http://images.cocodataset.org/val2017/000000039769.jpg\")\n",
|
||||
"display(image)\n",
|
||||
"\n",
|
||||
"question = \"Which cat is bigger?\"\n",
|
||||
"instances = [\n",
|
||||
" {\"image\": image_to_base64(image), \"text\": question},\n",
|
||||
"]\n",
|
||||
"preds = endpoint.predict(instances=instances).predictions\n",
|
||||
"print(question)\n",
|
||||
"print(preds)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "db7ffebdb4be"
|
||||
},
|
||||
"source": [
|
||||
"### Clean up resources"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2ccf3714dbe9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_vilt_vqa.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
+390
@@ -0,0 +1,390 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7d9bbf86da5e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "2bd716bf3e39"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden - ViT-GPT2 Image Captioning\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_vit_gpt2_image_captioning.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_vit_gpt2_image_captioning.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td> <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_vit_gpt2_image_captioning.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" (a Python-3 CPU notebook is recommended)\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d8cd12648da4"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates deploying the pre-trained [ViT-GPT2 Image Captioning](https://huggingface.co/nlpconnect/vit-gpt2-image-captioning) model on Vertex AI for online prediction.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
|
||||
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
|
||||
"- Run online predictions for image captioning.\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "264c07757582"
|
||||
},
|
||||
"source": [
|
||||
"## Setup environment\n",
|
||||
"\n",
|
||||
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d73ffa0c0b83"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2707b02ef5df"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip3 install --upgrade google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b60a4d7100bf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
"google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0f826ff482a2"
|
||||
},
|
||||
"source": [
|
||||
"### Setup Google Cloud project\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"\n",
|
||||
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "8958ebc71868"
|
||||
},
|
||||
"source": [
|
||||
"Fill following variables for experiments environment:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9db30f827a65"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Cloud project id.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The region you want to launch jobs in.\n",
|
||||
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
|
||||
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "92f16e22c20b"
|
||||
},
|
||||
"source": [
|
||||
"Initialize Vertex AI API:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1680c257acfb"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=GCS_BUCKET)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6ca48b699d17"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "de9882ea89ea"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The pre-built serving docker image. It contains serving scripts and models.\n",
|
||||
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-transformers-serve\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "10188266a5cd"
|
||||
},
|
||||
"source": [
|
||||
"### Define common functions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "cac4478ae098"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import requests\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_job_name(prefix):\n",
|
||||
" user = os.environ.get(\"USER\")\n",
|
||||
" now = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
|
||||
" job_name = f\"{prefix}-{user}-{now}\"\n",
|
||||
" return job_name\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def download_image(url):\n",
|
||||
" response = requests.get(url)\n",
|
||||
" return Image.open(BytesIO(response.content))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_to_base64(image, format=\"JPEG\"):\n",
|
||||
" buffer = BytesIO()\n",
|
||||
" image.save(buffer, format=format)\n",
|
||||
" image_str = base64.b64encode(buffer.getvalue()).decode(\"utf-8\")\n",
|
||||
" return image_str\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def base64_to_image(image_str):\n",
|
||||
" image = Image.open(BytesIO(base64.b64decode(image_str)))\n",
|
||||
" return image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def image_grid(imgs, rows=2, cols=2):\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def deploy_model(model_id, task):\n",
|
||||
" model_name = \"vit-gpt2-image-captioning\"\n",
|
||||
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
|
||||
" serving_env = {\n",
|
||||
" \"MODEL_ID\": model_id,\n",
|
||||
" \"TASK\": task,\n",
|
||||
" }\n",
|
||||
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
|
||||
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
|
||||
" model = aiplatform.Model.upload(\n",
|
||||
" display_name=model_name,\n",
|
||||
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
|
||||
" serving_container_ports=[7080],\n",
|
||||
" serving_container_predict_route=\"/predictions/transformers_serving\",\n",
|
||||
" serving_container_health_route=\"/ping\",\n",
|
||||
" serving_container_environment_variables=serving_env,\n",
|
||||
" artifact_uri=artifact_uri,\n",
|
||||
" )\n",
|
||||
" model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_T4\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" deploy_request_timeout=1800,\n",
|
||||
" )\n",
|
||||
" return model, endpoint"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d2d72ecdb8c9"
|
||||
},
|
||||
"source": [
|
||||
"## Upload and deploy models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "9448c5f545fa"
|
||||
},
|
||||
"source": [
|
||||
"This section uploads the pre-trained model to Model Registry and deploys it on the Endpoint with 1 T4 GPU.\n",
|
||||
"\n",
|
||||
"The model deployment step will take ~15 minutes to complete.\n",
|
||||
"\n",
|
||||
"Once deployed, you can send images to get descriptions."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b4b46c28d8b1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model, endpoint = deploy_model(\n",
|
||||
" model_id=\"nlpconnect/vit-gpt2-image-captioning\", task=\"image-to-text\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "6be655247cb1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"image = download_image(\"http://images.cocodataset.org/val2017/000000039769.jpg\")\n",
|
||||
"display(image)\n",
|
||||
"\n",
|
||||
"instances = [\n",
|
||||
" {\"image\": image_to_base64(image)},\n",
|
||||
"]\n",
|
||||
"preds = endpoint.predict(instances=instances).predictions\n",
|
||||
"print(preds)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "db7ffebdb4be"
|
||||
},
|
||||
"source": [
|
||||
"### Clean up resources"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2ccf3714dbe9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_pytorch_vit_gpt2_image_captioning.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,901 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ur8xi4C7S06n"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "TirJ-SGQseby"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden TFVision With Image Classification\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_tfvision_image_classification.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
"\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_tfvision_image_classification.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td> <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_tfvision_image_classification.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "dwGLvtIeECLK"
|
||||
},
|
||||
"source": [
|
||||
"**_NOTE_**: This notebook has been tested in the following environment:\n",
|
||||
"\n",
|
||||
"* Python version = 3.9"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "tvgnzT1CKxrO"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates how to use [TFVision](https://github.com/tensorflow/models/blob/master/official/vision/MODEL_GARDEN.md) in Vertex AI Model Garden.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"* Train new models\n",
|
||||
" * Convert input data to training formats\n",
|
||||
" * Create [hyperparameter tuning jobs](https://cloud.google.com/vertex-ai/docs/training/hyperparameter-tuning-overview) to train new models\n",
|
||||
" * Find and export best models\n",
|
||||
"\n",
|
||||
"* Test trained models\n",
|
||||
" * Upload models to model registry\n",
|
||||
" * Deploy uploaded models\n",
|
||||
" * Run predictions\n",
|
||||
"\n",
|
||||
"* Cleanup resources\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI\n",
|
||||
"pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage\n",
|
||||
"pricing](https://cloud.google.com/storage/pricing), and use the [Pricing\n",
|
||||
"Calculator](https://cloud.google.com/products/calculator/)\n",
|
||||
"to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "KEukV6uRk_S3"
|
||||
},
|
||||
"source": [
|
||||
"## Before you begin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "z__i0w0lCAsW"
|
||||
},
|
||||
"source": [
|
||||
"### Colab Only\n",
|
||||
"Run the following commands for colab and skip this section if you use workbench."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Jvqs-ehKlaYh"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if \"google.colab\" in str(get_ipython()):\n",
|
||||
" ! pip3 install --upgrade google-cloud-aiplatform\n",
|
||||
"\n",
|
||||
" # Automatically restart kernel after installs\n",
|
||||
" import IPython\n",
|
||||
"\n",
|
||||
" app = IPython.Application.instance()\n",
|
||||
" app.kernel.do_shutdown(True)\n",
|
||||
"\n",
|
||||
" from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
" google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "BF1j6f9HApxa"
|
||||
},
|
||||
"source": [
|
||||
"### Set up your Google Cloud project\n",
|
||||
"\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"1. If you are running this notebook locally, you will need to install the [Cloud SDK](https://cloud.google.com/sdk).\n",
|
||||
"\n",
|
||||
"1. Enter your project ID in the cell below. Then run the cell to make sure the\n",
|
||||
"Cloud SDK uses the right project for all the commands in this notebook.\n",
|
||||
"\n",
|
||||
"**Note**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9wExiMUxFk91"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"# The project and bucket are for experiments below.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"BUCKET_URI = \"\" # @param {type:\"string\"}\n",
|
||||
"REGION = \"us-central1\"\n",
|
||||
"\n",
|
||||
"! gcloud config set project $PROJECT_ID\n",
|
||||
"\n",
|
||||
"STAGING_BUCKET = os.path.join(BUCKET_URI, \"temporal\")\n",
|
||||
"CHECKPOINT_BUCKET = os.path.join(BUCKET_URI, \"ckpt\")\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=STAGING_BUCKET)\n",
|
||||
"\n",
|
||||
"# Download config files.\n",
|
||||
"CONFIG_DIR = os.path.join(BUCKET_URI, \"config\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def upload_config_to_gcs(url):\n",
|
||||
" filename = os.path.basename(url)\n",
|
||||
" destination = os.path.join(CONFIG_DIR, filename)\n",
|
||||
" print(\"Copy\", url, \"to\", destination)\n",
|
||||
" ! wget \"$url\" -O \"$filename\"\n",
|
||||
" ! gsutil cp \"$filename\" \"$destination\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"upload_config_to_gcs(\n",
|
||||
" \"https://raw.githubusercontent.com/tensorflow/models/master/official/vision/configs/experiments/image_classification/imagenet_resnet50_gpu.yaml\"\n",
|
||||
")\n",
|
||||
"upload_config_to_gcs(\n",
|
||||
" \"https://raw.githubusercontent.com/tensorflow/models/master/official/vision/configs/experiments/image_classification/imagenet_resnetrs50_i160_gpu.yaml\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "n6IFz75WGCam"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "riG_qUokg0XZ"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"OBJECTIVE = \"icn\"\n",
|
||||
"\n",
|
||||
"# Data converter constants.\n",
|
||||
"DATA_CONVERTER_JOB_PREFIX = \"data_converter\"\n",
|
||||
"DATA_CONVERTER_CONTAINER = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/data-converter:latest\"\n",
|
||||
"DATA_CONVERTER_MACHINE_TYPE = \"n1-highmem-8\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Training constants.\n",
|
||||
"TRAINING_JOB_PREFIX = \"train\"\n",
|
||||
"TRAIN_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-oss:latest\"\n",
|
||||
"TRAIN_MACHINE_TYPE = \"n1-highmem-16\"\n",
|
||||
"TRAIN_ACCELERATOR_TYPE = \"NVIDIA_TESLA_P100\"\n",
|
||||
"TRAIN_NUM_GPU = 1\n",
|
||||
"\n",
|
||||
"# Evaluation constants.\n",
|
||||
"EVALUATION_METRIC = \"accuracy\"\n",
|
||||
"\n",
|
||||
"# Export constants.\n",
|
||||
"EXPORT_JOB_PREFIX = \"export\"\n",
|
||||
"EXPORT_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-serving:latest\"\n",
|
||||
"EXPORT_MACHINE_TYPE = \"n1-highmem-8\"\n",
|
||||
"\n",
|
||||
"# Prediction constants.\n",
|
||||
"# You can deploy models with\n",
|
||||
"# pre-build-dockers: https://cloud.google.com/vertex-ai/docs/predictions/pre-built-containers.\n",
|
||||
"# and optimized tensorflow runtime dockers: https://cloud.google.com/vertex-ai/docs/predictions/optimized-tensorflow-runtime.\n",
|
||||
"# The example in this notebook uses optimized tensorflow runtime dockers.\n",
|
||||
"# You can adjust accelerator types and machine types to get faster predictions.\n",
|
||||
"PREDICTION_CONTAINER_URI = (\n",
|
||||
" \"us-docker.pkg.dev/vertex-ai-restricted/prediction/tf_opt-gpu.2-11:latest\"\n",
|
||||
")\n",
|
||||
"SERVING_CONTAINER_ARGS = [\"--allow_precompilation\", \"--allow_compression\"]\n",
|
||||
"PREDICTION_ACCELERATOR_TYPE = \"NVIDIA_TESLA_T4\"\n",
|
||||
"PREDICTION_MACHINE_TYPE = \"n1-standard-4\"\n",
|
||||
"UPLOAD_JOB_PREFIX = \"upload\"\n",
|
||||
"DEPLOY_JOB_PREFIX = \"deploy\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ZZFPe_GezXg8"
|
||||
},
|
||||
"source": [
|
||||
"### Define common libraries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "XcYUGwr-AJGY"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import json\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"from typing import Dict, List, Union\n",
|
||||
"\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import numpy\n",
|
||||
"import tensorflow as tf\n",
|
||||
"import yaml\n",
|
||||
"from google.protobuf import json_format\n",
|
||||
"from google.protobuf.struct_pb2 import Value\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_job_name_with_datetime(prefix: str):\n",
|
||||
" return prefix + datetime.now().strftime(\"_%Y%m%d_%H%M%S\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def predict_custom_trained_model(\n",
|
||||
" project: str,\n",
|
||||
" endpoint_id: str,\n",
|
||||
" instances: Union[Dict, List[Dict]],\n",
|
||||
" location: str = \"us-central1\",\n",
|
||||
" api_endpoint: str = \"us-central1-aiplatform.googleapis.com\",\n",
|
||||
"):\n",
|
||||
" # The AI Platform services require regional API endpoints.\n",
|
||||
" client_options = {\"api_endpoint\": api_endpoint}\n",
|
||||
" # Initialize client that will be used to create and send requests.\n",
|
||||
" # This client only needs to be created once, and can be reused for multiple requests.\n",
|
||||
" client = aiplatform.gapic.PredictionServiceClient(client_options=client_options)\n",
|
||||
" parameters_dict = {}\n",
|
||||
" parameters = json_format.ParseDict(parameters_dict, Value())\n",
|
||||
" endpoint = client.endpoint_path(\n",
|
||||
" project=project, location=location, endpoint=endpoint_id\n",
|
||||
" )\n",
|
||||
" response = client.predict(\n",
|
||||
" endpoint=endpoint, instances=instances, parameters=parameters\n",
|
||||
" )\n",
|
||||
" return response.predictions, response.deployed_model_id\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def load_img(path):\n",
|
||||
" img = tf.io.read_file(path)\n",
|
||||
" img = tf.image.decode_jpeg(img, channels=3)\n",
|
||||
" return Image.fromarray(numpy.uint8(img)).convert(\"RGB\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def display_image(image):\n",
|
||||
" _ = plt.figure(figsize=(20, 15))\n",
|
||||
" plt.grid(False)\n",
|
||||
" plt.imshow(image)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_prediction_instances(test_filepath, new_width=-1):\n",
|
||||
" if new_width <= 0:\n",
|
||||
" with tf.io.gfile.GFile(test_filepath, \"rb\") as input_file:\n",
|
||||
" encoded_string = base64.b64encode(input_file.read()).decode(\"utf-8\")\n",
|
||||
" else:\n",
|
||||
" img = load_img(test_filepath)\n",
|
||||
" width, height = img.size\n",
|
||||
" print(\"original input image size: \", width, \" , \", height)\n",
|
||||
" new_height = int(height * new_width / width)\n",
|
||||
" new_img = img.resize((new_width, new_height))\n",
|
||||
" print(\"resized input image size: \", new_width, \" , \", new_height)\n",
|
||||
" buffered = BytesIO()\n",
|
||||
" new_img.save(buffered, format=\"JPEG\")\n",
|
||||
" encoded_string = base64.b64encode(buffered.getvalue()).decode(\"utf-8\")\n",
|
||||
"\n",
|
||||
" instances = [\n",
|
||||
" {\n",
|
||||
" \"encoded_image\": {\"b64\": encoded_string},\n",
|
||||
" }\n",
|
||||
" ]\n",
|
||||
" return instances\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_label_map(label_map_yaml_filepath):\n",
|
||||
" with tf.io.gfile.GFile(label_map_yaml_filepath, \"rb\") as input_file:\n",
|
||||
" label_map = yaml.safe_load(input_file.read())\n",
|
||||
" return label_map\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_best_trial(model_dir, max_trial_count, evaluation_metric):\n",
|
||||
" best_trial_dir = \"\"\n",
|
||||
" best_trial_evaluation_results = {}\n",
|
||||
" best_performance = -1\n",
|
||||
"\n",
|
||||
" for i in range(max_trial_count):\n",
|
||||
" current_trial = i + 1\n",
|
||||
" current_trial_dir = os.path.join(model_dir, \"trial_\" + str(current_trial))\n",
|
||||
" current_trial_best_ckpt_dir = os.path.join(current_trial_dir, \"best_ckpt\")\n",
|
||||
" current_trial_best_ckpt_evaluation_filepath = os.path.join(\n",
|
||||
" current_trial_best_ckpt_dir, \"info.json\"\n",
|
||||
" )\n",
|
||||
" with tf.io.gfile.GFile(current_trial_best_ckpt_evaluation_filepath, \"rb\") as f:\n",
|
||||
" eval_metric_results = json.load(f)\n",
|
||||
" current_performance = eval_metric_results[evaluation_metric]\n",
|
||||
" if current_performance > best_performance:\n",
|
||||
" best_performance = current_performance\n",
|
||||
" best_trial_dir = current_trial_dir\n",
|
||||
" best_trial_evaluation_results = eval_metric_results\n",
|
||||
" return best_trial_dir, best_trial_evaluation_results\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def upload_checkpoint_to_gcs(checkpoint_url):\n",
|
||||
" filename = os.path.basename(checkpoint_url)\n",
|
||||
" checkpoint_name = filename.replace(\".tar.gz\", \"\")\n",
|
||||
" print(\"Download checkpoint from\", checkpoint_url, \"and store to\", CHECKPOINT_BUCKET)\n",
|
||||
" ! wget $checkpoint_url -O $filename\n",
|
||||
" ! mkdir -p $checkpoint_name\n",
|
||||
" ! tar -xvzf $filename -C $checkpoint_name\n",
|
||||
"\n",
|
||||
" # Search for relative path to the checkpoint.\n",
|
||||
" checkpoint_path = None\n",
|
||||
" for root, dirs, files in os.walk(checkpoint_name):\n",
|
||||
" for file in files:\n",
|
||||
" if file.endswith(\".index\"):\n",
|
||||
" checkpoint_path = os.path.join(root, os.path.splitext(file)[0])\n",
|
||||
" checkpoint_path = os.path.relpath(checkpoint_path, checkpoint_name)\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
" ! gsutil cp -r $checkpoint_name $CHECKPOINT_BUCKET/\n",
|
||||
" checkpoint_uri = os.path.join(CHECKPOINT_BUCKET, checkpoint_name, checkpoint_path)\n",
|
||||
" print(\"Checkpoint uploaded to\", checkpoint_uri)\n",
|
||||
" return checkpoint_uri"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "RB_xY9ipr7ZU"
|
||||
},
|
||||
"source": [
|
||||
"## Train new models\n",
|
||||
"This section shows how to train new models.\n",
|
||||
"1. Convert input data to training formats\n",
|
||||
"2. Create hyperparameter tuning jobs to train new models\n",
|
||||
"3. Find and export best models\n",
|
||||
"\n",
|
||||
"If you already trained models, please go to the section `Test Trained models`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "zgPO1eR3CYjk"
|
||||
},
|
||||
"source": [
|
||||
"### Prepare input data for training\n",
|
||||
"\n",
|
||||
"Prepare data in the format as described [here](https://cloud.google.com/vertex-ai/docs/image-data/classification/prepare-data), and then convert them to the training formats as below:\n",
|
||||
"\n",
|
||||
"* `input_file_path`: The input file path for preparing data.\n",
|
||||
"* `input_file_type`: The input file type, such as csv or jsonl.\n",
|
||||
"* `split_ratio`: The proportion of data to split into train/validation/test.\n",
|
||||
"* `num_shard`: The number of shards for train/validation/test.\n",
|
||||
"* `output_dir`: The output directory, which will container prepared train/test/validation data."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "IndQ_m6ddUEM"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# This job will convert input data as training format, with given split ratios\n",
|
||||
"# and number of shards on train/test/validation.\n",
|
||||
"\n",
|
||||
"data_converter_job_name = get_job_name_with_datetime(\n",
|
||||
" DATA_CONVERTER_JOB_PREFIX + \"_\" + OBJECTIVE\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"input_file_path = \"\" # @param {type:\"string\"}\n",
|
||||
"input_file_type = \"csv\" # @param [\"csv\", \"jsonl\"]\n",
|
||||
"num_classes = 5 # @param {type:\"integer\"}\n",
|
||||
"split_ratio = \"0.8,0.1,0.1\"\n",
|
||||
"num_shard = \"10,10,10\"\n",
|
||||
"data_converter_output_dir = os.path.join(BUCKET_URI, data_converter_job_name)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"worker_pool_specs = [\n",
|
||||
" {\n",
|
||||
" \"machine_spec\": {\n",
|
||||
" \"machine_type\": DATA_CONVERTER_MACHINE_TYPE,\n",
|
||||
" },\n",
|
||||
" \"replica_count\": 1,\n",
|
||||
" \"container_spec\": {\n",
|
||||
" \"image_uri\": DATA_CONVERTER_CONTAINER,\n",
|
||||
" \"command\": [],\n",
|
||||
" \"args\": [\n",
|
||||
" \"--input_file_path=%s\" % input_file_path,\n",
|
||||
" \"--input_file_type=%s\" % input_file_type,\n",
|
||||
" \"--objective=%s\" % OBJECTIVE,\n",
|
||||
" \"--num_shard=%s\" % num_shard,\n",
|
||||
" \"--split_ratio=%s\" % split_ratio,\n",
|
||||
" \"--output_dir=%s\" % data_converter_output_dir,\n",
|
||||
" ],\n",
|
||||
" },\n",
|
||||
" }\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"data_converter_custom_job = aiplatform.CustomJob(\n",
|
||||
" display_name=data_converter_job_name,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" worker_pool_specs=worker_pool_specs,\n",
|
||||
" staging_bucket=STAGING_BUCKET,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"data_converter_custom_job.run()\n",
|
||||
"\n",
|
||||
"input_train_data_path = os.path.join(data_converter_output_dir, \"train.tfrecord*\")\n",
|
||||
"input_validation_data_path = os.path.join(data_converter_output_dir, \"val.tfrecord*\")\n",
|
||||
"label_map_path = os.path.join(data_converter_output_dir, \"label_map.yaml\")\n",
|
||||
"print(\"input_train_data_path for training: \", input_train_data_path)\n",
|
||||
"print(\"input_validation_data_path for training: \", input_validation_data_path)\n",
|
||||
"print(\"label_map_path for prediction: \", label_map_path)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "aaff6f5be7f6"
|
||||
},
|
||||
"source": [
|
||||
"### Create a Vertex AI custom job with hyperparameter tuning\n",
|
||||
"\n",
|
||||
"You use the Vertex AI SDK to create and run the hyperparameter tuning job with Vertex AI Model Garden Training Dockers.\n",
|
||||
"\n",
|
||||
"#### Define the following specifications\n",
|
||||
"* `worker_pool_specs`: Dictionary specifying the machine type and Docker image. This example defines a single node cluster with one `n1-standard-4` machine with two `NVIDIA_TESLA_T4` GPUs.\n",
|
||||
"* `parameter_spec`: Dictionary specifying the parameters to optimize. The dictionary key is the string assigned to the command line argument for each hyperparameter in your training application code, and the dictionary value is the parameter specification. The parameter specification includes the type, min/max values, and scale for the hyperparameter.\n",
|
||||
"* `metric_spec`: Dictionary specifying the metric to optimize. The dictionary key is the `hyperparameter_metric_tag` that you set in your training application code, and the value is the optimization goal."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "um_XKbmpTaHx"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud.aiplatform import hyperparameter_tuning as hpt\n",
|
||||
"\n",
|
||||
"# Input train and validation datasets can be found from the section above\n",
|
||||
"# `Convert input data for training`.\n",
|
||||
"# Set prepared datasets if exists.\n",
|
||||
"# input_train_data_path = ''\n",
|
||||
"# input_validation_data_path = ''\n",
|
||||
"\n",
|
||||
"experiment = \"ViT-s16\" # @param [\"ResNet-50\",\"ResNet-RS-50\",\"Efficientnetv2-m\",\"ViT-ti16\",\"ViT-s16\",\"ViT-b16\",\"ViT-l16\"]\n",
|
||||
"\n",
|
||||
"train_job_name = get_job_name_with_datetime(TRAINING_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"model_dir = os.path.join(BUCKET_URI, train_job_name)\n",
|
||||
"\n",
|
||||
"# The arguments here are mainly for test purposes. Please update them\n",
|
||||
"# to get better performances.\n",
|
||||
"common_args = {\n",
|
||||
" \"input_train_data_path\": input_train_data_path,\n",
|
||||
" \"input_validation_data_path\": input_validation_data_path,\n",
|
||||
" \"objective\": OBJECTIVE,\n",
|
||||
" \"model_dir\": model_dir,\n",
|
||||
" \"num_classes\": num_classes,\n",
|
||||
" \"global_batch_size\": 4,\n",
|
||||
" \"prefetch_buffer_size\": 32,\n",
|
||||
" \"train_steps\": 2000,\n",
|
||||
" \"input_size\": \"224,224\",\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# Arguments for different experiments.\n",
|
||||
"experiment_container_args_dict = {\n",
|
||||
" \"ResNet-50\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"resnet_imagenet\",\n",
|
||||
" \"config_file\": os.path.join(CONFIG_DIR, \"imagenet_resnet50_gpu.yaml\"),\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
" \"ResNet-RS-50\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"resnet_rs_imagenet\",\n",
|
||||
" \"config_file\": os.path.join(\n",
|
||||
" CONFIG_DIR, \"imagenet_resnetrs50_i160_gpu.yaml\"\n",
|
||||
" ),\n",
|
||||
" \"init_checkpoint\": \"https://storage.googleapis.com/tf_model_garden/vision/resnet-rs/resnet-rs-50-i160.tar.gz\",\n",
|
||||
" \"input_size\": \"160,160\",\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
" \"Efficientnetv2-m\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"hub_model\",\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
" \"ViT-ti16\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"deit_imagenet_pretrain\",\n",
|
||||
" \"model_name\": \"vit-ti16\",\n",
|
||||
" \"init_checkpoint\": \"https://storage.googleapis.com/tf_model_garden/vision/vit/vit-deit-imagenet-ti16.tar.gz\",\n",
|
||||
" \"input_size\": \"224,224\",\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
" \"ViT-s16\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"deit_imagenet_pretrain\",\n",
|
||||
" \"model_name\": \"vit-s16\",\n",
|
||||
" \"init_checkpoint\": \"https://storage.googleapis.com/tf_model_garden/vision/vit/vit-deit-imagenet-s16.tar.gz\",\n",
|
||||
" \"input_size\": \"224,224\",\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
" \"ViT-b16\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"deit_imagenet_pretrain\",\n",
|
||||
" \"model_name\": \"vit-b16\",\n",
|
||||
" \"init_checkpoint\": \"https://storage.googleapis.com/tf_model_garden/vision/vit/vit-deit-imagenet-b16.tar.gz\",\n",
|
||||
" \"input_size\": \"224,224\",\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
" \"ViT-l16\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"deit_imagenet_pretrain\",\n",
|
||||
" \"model_name\": \"vit-l16\",\n",
|
||||
" \"init_checkpoint\": \"https://storage.googleapis.com/tf_model_garden/vision/vit/vit-deit-imagenet-l16.tar.gz\",\n",
|
||||
" \"input_size\": \"224,224\",\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
"}\n",
|
||||
"experiment_container_args = experiment_container_args_dict[experiment]\n",
|
||||
"\n",
|
||||
"# Copy checkpoint to GCS bucket if specified.\n",
|
||||
"init_checkpoint = experiment_container_args.get(\"init_checkpoint\")\n",
|
||||
"if init_checkpoint:\n",
|
||||
" experiment_container_args[\"init_checkpoint\"] = upload_checkpoint_to_gcs(\n",
|
||||
" init_checkpoint\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"worker_pool_specs = [\n",
|
||||
" {\n",
|
||||
" \"machine_spec\": {\n",
|
||||
" \"machine_type\": TRAIN_MACHINE_TYPE,\n",
|
||||
" \"accelerator_type\": TRAIN_ACCELERATOR_TYPE,\n",
|
||||
" # Each training job uses TRAIN_NUM_GPU GPUs.\n",
|
||||
" \"accelerator_count\": TRAIN_NUM_GPU,\n",
|
||||
" },\n",
|
||||
" \"replica_count\": 1,\n",
|
||||
" \"container_spec\": {\n",
|
||||
" \"image_uri\": TRAIN_CONTAINER_URI,\n",
|
||||
" \"args\": [\n",
|
||||
" \"--mode=train_and_eval\",\n",
|
||||
" \"--params_override=runtime.num_gpus=%d\" % TRAIN_NUM_GPU,\n",
|
||||
" ]\n",
|
||||
" + [\"--{}={}\".format(k, v) for k, v in experiment_container_args.items()],\n",
|
||||
" },\n",
|
||||
" }\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"metric_spec = {\"model_performance\": \"maximize\"}\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"LEARNING_RATES = [5e-4, 1e-3]\n",
|
||||
"# Models will be trained with each learning rate separately and max trial count is the number of learning rates.\n",
|
||||
"MAX_TRIAL_COUNT = len(LEARNING_RATES)\n",
|
||||
"parameter_spec = {\n",
|
||||
" \"learning_rate\": hpt.DiscreteParameterSpec(values=LEARNING_RATES, scale=\"linear\"),\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"print(worker_pool_specs, metric_spec, parameter_spec)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "HwcCjwlBTQIz"
|
||||
},
|
||||
"source": [
|
||||
"#### Run the hyperparameter tuning job\n",
|
||||
"* `max_trial_count`: Sets an upper bound on the number of trials the service will run. The recommended practice is to start with a smaller number of trials and get a sense of how impactful your chosen hyperparameters are before scaling up.\n",
|
||||
"\n",
|
||||
"* `parallel_trial_count`: If you use parallel trials, the service provisions multiple training processing clusters. The worker pool spec that you specify when creating the job is used for each individual training cluster. Increasing the number of parallel trials reduces the amount of time the hyperparameter tuning job takes to run; however, it can reduce the effectiveness of the job overall. This is because the default tuning strategy uses results of previous trials to inform the assignment of values in subsequent trials.\n",
|
||||
"\n",
|
||||
"* `search_algorithm`: The available search algorithms are grid, random, or default (None). The default option applies Bayesian optimization to search the space of possible hyperparameter values and is the recommended algorithm.\n",
|
||||
"\n",
|
||||
"Click on the generated link in the output to see your run in the Cloud Console."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "aec22792ee84"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"train_custom_job = aiplatform.CustomJob(\n",
|
||||
" display_name=train_job_name,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" worker_pool_specs=worker_pool_specs,\n",
|
||||
" staging_bucket=STAGING_BUCKET,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"train_hpt_job = aiplatform.HyperparameterTuningJob(\n",
|
||||
" display_name=train_job_name,\n",
|
||||
" custom_job=train_custom_job,\n",
|
||||
" metric_spec=metric_spec,\n",
|
||||
" parameter_spec=parameter_spec,\n",
|
||||
" max_trial_count=MAX_TRIAL_COUNT,\n",
|
||||
" parallel_trial_count=MAX_TRIAL_COUNT,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" search_algorithm=None,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"train_hpt_job.run()\n",
|
||||
"\n",
|
||||
"print(\"experiment is: \", experiment)\n",
|
||||
"print(\"model_dir is: \", model_dir)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "mV-Djz-frBni"
|
||||
},
|
||||
"source": [
|
||||
"### Export best models as TF Saved Model format"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "09Rz1AYspK19"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# This job will export models from TF checkpoints to TF saved model format.\n",
|
||||
"# model_dir is from the section above.\n",
|
||||
"best_trial_dir, best_trial_evaluation_results = get_best_trial(\n",
|
||||
" model_dir, MAX_TRIAL_COUNT, EVALUATION_METRIC\n",
|
||||
")\n",
|
||||
"print(\"best_trial_dir: \", best_trial_dir)\n",
|
||||
"print(\"best_trial_evaluation_results: \", best_trial_evaluation_results)\n",
|
||||
"\n",
|
||||
"worker_pool_specs = [\n",
|
||||
" {\n",
|
||||
" \"machine_spec\": {\n",
|
||||
" \"machine_type\": EXPORT_MACHINE_TYPE,\n",
|
||||
" },\n",
|
||||
" \"replica_count\": 1,\n",
|
||||
" \"container_spec\": {\n",
|
||||
" \"image_uri\": EXPORT_CONTAINER_URI,\n",
|
||||
" \"command\": [],\n",
|
||||
" \"args\": [\n",
|
||||
" \"--objective=%s\" % OBJECTIVE,\n",
|
||||
" \"--input_image_size=%s\" % experiment_container_args[\"input_size\"],\n",
|
||||
" \"--experiment=%s\" % experiment_container_args[\"experiment\"],\n",
|
||||
" \"--config_file=%s/params.yaml\" % best_trial_dir,\n",
|
||||
" \"--checkpoint_path=%s/best_ckpt\" % best_trial_dir,\n",
|
||||
" \"--export_dir=%s/best_model\" % model_dir,\n",
|
||||
" ],\n",
|
||||
" },\n",
|
||||
" }\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"model_export_name = get_job_name_with_datetime(EXPORT_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"model_export_custom_job = aiplatform.CustomJob(\n",
|
||||
" display_name=model_export_name,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" worker_pool_specs=worker_pool_specs,\n",
|
||||
" staging_bucket=STAGING_BUCKET,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"model_export_custom_job.run()\n",
|
||||
"\n",
|
||||
"print(\"best model is saved to: \", os.path.join(model_dir, \"best_model\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "g0BGaofgsMsy"
|
||||
},
|
||||
"source": [
|
||||
"## Test trained models\n",
|
||||
"This section shows how to test with trained models.\n",
|
||||
"1. Upload and deploy models to model registry\n",
|
||||
"2. Run predictions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "NYuQowyZEtxK"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# @title Upload and deploy models\n",
|
||||
"# model_dir is from the section above.\n",
|
||||
"trained_model_dir = os.path.join(model_dir, \"best_model/saved_model\")\n",
|
||||
"\n",
|
||||
"upload_job_name = get_job_name_with_datetime(UPLOAD_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"\n",
|
||||
"model = aiplatform.Model.upload(\n",
|
||||
" display_name=upload_job_name,\n",
|
||||
" artifact_uri=trained_model_dir,\n",
|
||||
" serving_container_image_uri=PREDICTION_CONTAINER_URI,\n",
|
||||
" serving_container_args=SERVING_CONTAINER_ARGS,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"model.wait()\n",
|
||||
"\n",
|
||||
"print(\"The uploaded model name is: \", upload_job_name)\n",
|
||||
"\n",
|
||||
"deploy_model_name = get_job_name_with_datetime(DEPLOY_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"print(\"The deployed job name is: \", deploy_model_name)\n",
|
||||
"\n",
|
||||
"endpoint = model.deploy(\n",
|
||||
" deployed_model_display_name=deploy_model_name,\n",
|
||||
" machine_type=PREDICTION_MACHINE_TYPE,\n",
|
||||
" traffic_split={\"0\": 100},\n",
|
||||
" accelerator_type=PREDICTION_ACCELERATOR_TYPE,\n",
|
||||
" accelerator_count=1,\n",
|
||||
" min_replica_count=1,\n",
|
||||
" max_replica_count=1,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"endpoint_id = endpoint.name\n",
|
||||
"print(\"endpoint id is: \", endpoint_id)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "vbIW9me1F2RY"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# @title Run predictions\n",
|
||||
"\n",
|
||||
"# endpoint_id was generated in the section above (`Upload and deploy models`).\n",
|
||||
"endpoint_id = endpoint.name\n",
|
||||
"\n",
|
||||
"test_filepath = \"\" # @param {type:\"string\"}\n",
|
||||
"# If the input image is too large, we will resize it for prediction.\n",
|
||||
"instances = get_prediction_instances(test_filepath, new_width=1000)\n",
|
||||
"\n",
|
||||
"# The label map file was generated from the section above (`Convert input data for training`).\n",
|
||||
"label_map = get_label_map(label_map_path)[\"label_map\"]\n",
|
||||
"\n",
|
||||
"predictions, _ = predict_custom_trained_model(\n",
|
||||
" project=PROJECT_ID, location=REGION, endpoint_id=endpoint_id, instances=instances\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"probs = dict(predictions[0])[\"probs\"]\n",
|
||||
"max_prob = max(probs)\n",
|
||||
"max_index = probs.index(max_prob)\n",
|
||||
"print(\"The test image: \", test_filepath)\n",
|
||||
"print(\"max_prob: \", max_prob, \", for label: \", label_map[max_index])\n",
|
||||
"img = load_img(test_filepath)\n",
|
||||
"display_image(img)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "kkH2nrpdp4sp"
|
||||
},
|
||||
"source": [
|
||||
"## Clean up"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Ax6vQVZhp9pR"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()\n",
|
||||
"# Delete custom and hpt jobs.\n",
|
||||
"if data_converter_custom_job.list(filter=f'display_name=\"{data_converter_job_name}\"'):\n",
|
||||
" data_converter_custom_job.delete()\n",
|
||||
"if train_hpt_job.list(filter=f'display_name=\"{train_job_name}\"'):\n",
|
||||
" train_hpt_job.delete()\n",
|
||||
"if model_export_custom_job.list(filter=f'display_name=\"{model_export_name}\"'):\n",
|
||||
" model_export_custom_job.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_tfvision_image_classification.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,975 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ur8xi4C7S06n"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "TirJ-SGQseby"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden TFVision With Image Object Detection\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_tfvision_image_object_detection.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
"\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_tfvision_image_object_detection.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td> <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_tfvision_image_object_detection.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "dwGLvtIeECLK"
|
||||
},
|
||||
"source": [
|
||||
"**_NOTE_**: This notebook has been tested in the following environment:\n",
|
||||
"\n",
|
||||
"* Python version = 3.9"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "tvgnzT1CKxrO"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates how to use [TFVision](https://github.com/tensorflow/models/blob/master/official/vision/MODEL_GARDEN.md) in Vertex AI Model Garden.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"* Train new models\n",
|
||||
" * Convert input data to training formats\n",
|
||||
" * Create [hyperparameter tuning jobs](https://cloud.google.com/vertex-ai/docs/training/hyperparameter-tuning-overview) to train new models\n",
|
||||
" * Find and export best models\n",
|
||||
"\n",
|
||||
"* Test trained models\n",
|
||||
" * Upload models to model registry\n",
|
||||
" * Deploy uploaded models\n",
|
||||
" * Run predictions\n",
|
||||
"\n",
|
||||
"* Cleanup resources\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI\n",
|
||||
"pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage\n",
|
||||
"pricing](https://cloud.google.com/storage/pricing), and use the [Pricing\n",
|
||||
"Calculator](https://cloud.google.com/products/calculator/)\n",
|
||||
"to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "KEukV6uRk_S3"
|
||||
},
|
||||
"source": [
|
||||
"## Before you begin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "z__i0w0lCAsW"
|
||||
},
|
||||
"source": [
|
||||
"### Colab Only\n",
|
||||
"Run the following commands for colab and skip this section if you use workbench."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Jvqs-ehKlaYh"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if \"google.colab\" in str(get_ipython()):\n",
|
||||
" ! pip3 install --upgrade google-cloud-aiplatform\n",
|
||||
"\n",
|
||||
" # Automatically restart kernel after installs\n",
|
||||
" import IPython\n",
|
||||
"\n",
|
||||
" app = IPython.Application.instance()\n",
|
||||
" app.kernel.do_shutdown(True)\n",
|
||||
"\n",
|
||||
" from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
" google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "BF1j6f9HApxa"
|
||||
},
|
||||
"source": [
|
||||
"### Set up your Google Cloud project\n",
|
||||
"\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"1. If you are running this notebook locally, you will need to install the [Cloud SDK](https://cloud.google.com/sdk).\n",
|
||||
"\n",
|
||||
"1. Enter your project ID in the cell below. Then run the cell to make sure the\n",
|
||||
"Cloud SDK uses the right project for all the commands in this notebook.\n",
|
||||
"\n",
|
||||
"**Note**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9wExiMUxFk91"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"# The project and bucket are for experiments below.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"BUCKET_URI = \"\" # @param {type:\"string\"}\n",
|
||||
"REGION = \"us-central1\"\n",
|
||||
"\n",
|
||||
"! gcloud config set project $PROJECT_ID\n",
|
||||
"\n",
|
||||
"STAGING_BUCKET = os.path.join(BUCKET_URI, \"temporal\")\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=STAGING_BUCKET)\n",
|
||||
"\n",
|
||||
"# Download config files.\n",
|
||||
"CONFIG_DIR = os.path.join(BUCKET_URI, \"config\")\n",
|
||||
"! wget https://raw.githubusercontent.com/tensorflow/models/master/official/vision/configs/experiments/retinanet/coco_spinenet49_gpu_multiworker_mirrored.yaml\n",
|
||||
"! gsutil cp coco_spinenet49_gpu_multiworker_mirrored.yaml $CONFIG_DIR\n",
|
||||
"\n",
|
||||
"! wget https://raw.githubusercontent.com/tensorflow/models/master/official/vision/configs/experiments/retinanet/coco_spinenet96_gpu_multiworker_mirrored.yaml\n",
|
||||
"! gsutil cp coco_spinenet96_gpu_multiworker_mirrored.yaml $CONFIG_DIR\n",
|
||||
"\n",
|
||||
"! wget https://raw.githubusercontent.com/tensorflow/models/master/official/vision/configs/experiments/retinanet/coco_spinenet143_gpu_multiworker_mirrored.yaml\n",
|
||||
"! gsutil cp coco_spinenet143_gpu_multiworker_mirrored.yaml $CONFIG_DIR\n",
|
||||
"\n",
|
||||
"! wget https://raw.githubusercontent.com/tensorflow/models/master/official/projects/yolo/configs/experiments/yolov4/detection/scaled_yolov4_1280_gpu.yaml\n",
|
||||
"! gsutil cp scaled_yolov4_1280_gpu.yaml $CONFIG_DIR"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "n6IFz75WGCam"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "riG_qUokg0XZ"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"OBJECTIVE = \"iod\"\n",
|
||||
"\n",
|
||||
"# Data converter constants.\n",
|
||||
"DATA_CONVERTER_JOB_PREFIX = \"data_converter\"\n",
|
||||
"DATA_CONVERTER_CONTAINER = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/data-converter:latest\"\n",
|
||||
"DATA_CONVERTER_MACHINE_TYPE = \"n1-highmem-8\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Training constants.\n",
|
||||
"TRAINING_JOB_PREFIX = \"train\"\n",
|
||||
"TRAIN_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-oss:latest\"\n",
|
||||
"TRAIN_MACHINE_TYPE = \"n1-highmem-16\"\n",
|
||||
"TRAIN_ACCELERATOR_TYPE = \"NVIDIA_TESLA_V100\"\n",
|
||||
"TRAIN_NUM_GPU = 2\n",
|
||||
"TRAIN_SPINENET49_CONFIG = os.path.join(\n",
|
||||
" CONFIG_DIR, \"coco_spinenet49_gpu_multiworker_mirrored.yaml\"\n",
|
||||
")\n",
|
||||
"TRAIN_SPINENET96_CONFIG = os.path.join(\n",
|
||||
" CONFIG_DIR, \"coco_spinenet96_gpu_multiworker_mirrored.yaml\"\n",
|
||||
")\n",
|
||||
"TRAIN_SPINENET143_CONFIG = os.path.join(\n",
|
||||
" CONFIG_DIR, \"coco_spinenet143_gpu_multiworker_mirrored.yaml\"\n",
|
||||
")\n",
|
||||
"TRAIN_YOLOV4_CONFIG = os.path.join(CONFIG_DIR, \"scaled_yolov4_1280_gpu.yaml\")\n",
|
||||
"\n",
|
||||
"# Evaluation constants.\n",
|
||||
"EVALUATION_METRIC = \"AP50\"\n",
|
||||
"\n",
|
||||
"# Export constants.\n",
|
||||
"EXPORT_JOB_PREFIX = \"export\"\n",
|
||||
"EXPORT_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-serving:latest\"\n",
|
||||
"EXPORT_MACHINE_TYPE = \"n1-highmem-8\"\n",
|
||||
"\n",
|
||||
"# Prediction constants.\n",
|
||||
"# You can deploy models with\n",
|
||||
"# pre-build-dockers: https://cloud.google.com/vertex-ai/docs/predictions/pre-built-containers.\n",
|
||||
"# and optimized tensorflow runtime dockers: https://cloud.google.com/vertex-ai/docs/predictions/optimized-tensorflow-runtime.\n",
|
||||
"# The example in this notebook uses optimized tensorflow runtime dockers.\n",
|
||||
"# You can adjust accelerator types and machine types to get faster predictions.\n",
|
||||
"PREDICTION_CONTAINER_URI = (\n",
|
||||
" \"us-docker.pkg.dev/vertex-ai-restricted/prediction/tf_opt-gpu.2-11:latest\"\n",
|
||||
")\n",
|
||||
"SERVING_CONTAINER_ARGS = [\"--allow_precompilation\", \"--allow_compression\"]\n",
|
||||
"PREDICTION_ACCELERATOR_TYPE = \"NVIDIA_TESLA_T4\"\n",
|
||||
"PREDICTION_MACHINE_TYPE = \"n1-standard-4\"\n",
|
||||
"UPLOAD_JOB_PREFIX = \"upload\"\n",
|
||||
"DEPLOY_JOB_PREFIX = \"deploy\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ZZFPe_GezXg8"
|
||||
},
|
||||
"source": [
|
||||
"### Define common libraries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "XcYUGwr-AJGY"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import json\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"from typing import Dict, List, Union\n",
|
||||
"\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import numpy as np\n",
|
||||
"import tensorflow as tf\n",
|
||||
"import yaml\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from google.protobuf import json_format\n",
|
||||
"from google.protobuf.struct_pb2 import Value\n",
|
||||
"from PIL import Image, ImageColor, ImageDraw, ImageFont\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_job_name_with_datetime(prefix: str):\n",
|
||||
" return prefix + datetime.now().strftime(\"_%Y%m%d_%H%M%S\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def predict_custom_trained_model(\n",
|
||||
" project: str,\n",
|
||||
" endpoint_id: str,\n",
|
||||
" instances: Union[Dict, List[Dict]],\n",
|
||||
" location: str = \"us-central1\",\n",
|
||||
" api_endpoint: str = \"us-central1-aiplatform.googleapis.com\",\n",
|
||||
"):\n",
|
||||
" # The AI Platform services require regional API endpoints.\n",
|
||||
" client_options = {\"api_endpoint\": api_endpoint}\n",
|
||||
" # Initialize client that will be used to create and send requests.\n",
|
||||
" # This client only needs to be created once, and can be reused for multiple requests.\n",
|
||||
" client = aiplatform.gapic.PredictionServiceClient(client_options=client_options)\n",
|
||||
" parameters_dict = {}\n",
|
||||
" parameters = json_format.ParseDict(parameters_dict, Value())\n",
|
||||
" endpoint = client.endpoint_path(\n",
|
||||
" project=project, location=location, endpoint=endpoint_id\n",
|
||||
" )\n",
|
||||
" response = client.predict(\n",
|
||||
" endpoint=endpoint, instances=instances, parameters=parameters\n",
|
||||
" )\n",
|
||||
" return response.predictions, response.deployed_model_id\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def load_img(path):\n",
|
||||
" img = tf.io.read_file(path)\n",
|
||||
" img = tf.image.decode_jpeg(img, channels=3)\n",
|
||||
" return Image.fromarray(np.uint8(img)).convert(\"RGB\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def display_image(image):\n",
|
||||
" _ = plt.figure(figsize=(20, 15))\n",
|
||||
" plt.grid(False)\n",
|
||||
" plt.imshow(image)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_prediction_instances(test_filepath, new_width=-1):\n",
|
||||
" if new_width <= 0:\n",
|
||||
" with tf.io.gfile.GFile(test_filepath, \"rb\") as input_file:\n",
|
||||
" encoded_string = base64.b64encode(input_file.read()).decode(\"utf-8\")\n",
|
||||
" else:\n",
|
||||
" img = load_img(test_filepath)\n",
|
||||
" width, height = img.size\n",
|
||||
" print(\"original input image size: \", width, \" , \", height)\n",
|
||||
" new_height = int(height * new_width / width)\n",
|
||||
" new_img = img.resize((new_width, new_height))\n",
|
||||
" print(\"resized input image size: \", new_width, \" , \", new_height)\n",
|
||||
" buffered = BytesIO()\n",
|
||||
" new_img.save(buffered, format=\"JPEG\")\n",
|
||||
" encoded_string = base64.b64encode(buffered.getvalue()).decode(\"utf-8\")\n",
|
||||
"\n",
|
||||
" instances = [\n",
|
||||
" {\n",
|
||||
" \"encoded_image\": {\"b64\": encoded_string},\n",
|
||||
" }\n",
|
||||
" ]\n",
|
||||
" return instances\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_label_map(label_map_yaml_filepath):\n",
|
||||
" with tf.io.gfile.GFile(label_map_yaml_filepath, \"rb\") as input_file:\n",
|
||||
" label_map = yaml.safe_load(input_file.read())\n",
|
||||
" return label_map\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_best_trial(model_dir, max_trial_count, evaluation_metric):\n",
|
||||
" best_trial_dir = \"\"\n",
|
||||
" best_trial_evaluation_results = {}\n",
|
||||
" best_performance = -1\n",
|
||||
"\n",
|
||||
" for i in range(max_trial_count):\n",
|
||||
" current_trial = i + 1\n",
|
||||
" current_trial_dir = os.path.join(model_dir, \"trial_\" + str(current_trial))\n",
|
||||
" current_trial_best_ckpt_dir = os.path.join(current_trial_dir, \"best_ckpt\")\n",
|
||||
" current_trial_best_ckpt_evaluation_filepath = os.path.join(\n",
|
||||
" current_trial_best_ckpt_dir, \"info.json\"\n",
|
||||
" )\n",
|
||||
" with tf.io.gfile.GFile(current_trial_best_ckpt_evaluation_filepath, \"rb\") as f:\n",
|
||||
" eval_metric_results = json.load(f)\n",
|
||||
" current_performance = eval_metric_results[evaluation_metric]\n",
|
||||
" if current_performance > best_performance:\n",
|
||||
" best_performance = current_performance\n",
|
||||
" best_trial_dir = current_trial_dir\n",
|
||||
" best_trial_evaluation_results = eval_metric_results\n",
|
||||
" return best_trial_dir, best_trial_evaluation_results\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def draw_bounding_box_on_image(\n",
|
||||
" image, ymin, xmin, ymax, xmax, color, font, thickness=4, display_str_list=()\n",
|
||||
"):\n",
|
||||
" \"\"\"Adds a bounding box to an image.\"\"\"\n",
|
||||
" draw = ImageDraw.Draw(image)\n",
|
||||
" im_width, im_height = image.size\n",
|
||||
" (left, right, top, bottom) = (\n",
|
||||
" xmin * im_width,\n",
|
||||
" xmax * im_width,\n",
|
||||
" ymin * im_height,\n",
|
||||
" ymax * im_height,\n",
|
||||
" )\n",
|
||||
" draw.line(\n",
|
||||
" [(left, top), (left, bottom), (right, bottom), (right, top), (left, top)],\n",
|
||||
" width=thickness,\n",
|
||||
" fill=color,\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # If the total height of the display strings added to the top of the bounding\n",
|
||||
" # box exceeds the top of the image, stack the strings below the bounding box\n",
|
||||
" # instead of above.\n",
|
||||
" display_str_heights = [font.getsize(ds)[1] for ds in display_str_list]\n",
|
||||
" # Each display_str has a top and bottom margin of 0.05x.\n",
|
||||
" total_display_str_height = (1 + 2 * 0.05) * sum(display_str_heights)\n",
|
||||
"\n",
|
||||
" if top > total_display_str_height:\n",
|
||||
" text_bottom = top\n",
|
||||
" else:\n",
|
||||
" text_bottom = top + total_display_str_height\n",
|
||||
" # Reverse list and print from bottom to top.\n",
|
||||
" for display_str in display_str_list[::-1]:\n",
|
||||
" text_width, text_height = font.getsize(display_str)\n",
|
||||
" margin = np.ceil(0.05 * text_height)\n",
|
||||
" draw.rectangle(\n",
|
||||
" [\n",
|
||||
" (left, text_bottom - text_height - 2 * margin),\n",
|
||||
" (left + text_width, text_bottom),\n",
|
||||
" ],\n",
|
||||
" fill=color,\n",
|
||||
" )\n",
|
||||
" draw.text(\n",
|
||||
" (left + margin, text_bottom - text_height - margin),\n",
|
||||
" display_str,\n",
|
||||
" fill=\"black\",\n",
|
||||
" font=font,\n",
|
||||
" )\n",
|
||||
" text_bottom -= text_height - 2 * margin\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def draw_boxes(image, boxes, class_names, scores, max_boxes=40, min_score=0.05):\n",
|
||||
" \"\"\"Overlay labeled boxes on an image with formatted scores and label names.\"\"\"\n",
|
||||
" colors = list(ImageColor.colormap.values())\n",
|
||||
" try:\n",
|
||||
" font = ImageFont.truetype(\n",
|
||||
" \"/usr/share/fonts/truetype/liberation/LiberationSansNarrow-Regular.ttf\", 25\n",
|
||||
" )\n",
|
||||
" except IOError:\n",
|
||||
" print(\"Font not found, using default font.\")\n",
|
||||
" font = ImageFont.load_default()\n",
|
||||
"\n",
|
||||
" for i in range(min(len(boxes), max_boxes)):\n",
|
||||
" if scores[i] >= min_score:\n",
|
||||
" ymin, xmin, ymax, xmax = boxes[i]\n",
|
||||
" display_str = \"{}: {}%\".format(class_names[i], int(100 * scores[i]))\n",
|
||||
" color = colors[hash(class_names[i]) % len(colors)]\n",
|
||||
" draw_bounding_box_on_image(\n",
|
||||
" image,\n",
|
||||
" ymin,\n",
|
||||
" xmin,\n",
|
||||
" ymax,\n",
|
||||
" xmax,\n",
|
||||
" color,\n",
|
||||
" font,\n",
|
||||
" display_str_list=[display_str],\n",
|
||||
" )\n",
|
||||
" return image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "RB_xY9ipr7ZU"
|
||||
},
|
||||
"source": [
|
||||
"## Train new models\n",
|
||||
"This section shows how to train new models.\n",
|
||||
"1. Convert input data to training formats\n",
|
||||
"2. Create hyperparameter tuning jobs to train new models\n",
|
||||
"3. Find and export best models\n",
|
||||
"\n",
|
||||
"If you already trained models, please go to the section `Test trained models`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "zgPO1eR3CYjk"
|
||||
},
|
||||
"source": [
|
||||
"### Prepare input data for training\n",
|
||||
"\n",
|
||||
"Prepare data in the format as described [here](https://cloud.google.com/vertex-ai/docs/image-data/classification/prepare-data), and then convert them to the training formats as below:\n",
|
||||
"\n",
|
||||
"* `input_file_path`: The input file path for preparing data.\n",
|
||||
"* `input_file_type`: The input file type, such as csv or jsonl.\n",
|
||||
"* `split_ratio`: The proportion of data to split into train/validation/test.\n",
|
||||
"* `num_shard`: The number of shards for train/validation/test.\n",
|
||||
"* `output_dir`: The output directory, which will contain prepared train/test/validation data."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "IndQ_m6ddUEM"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# This job will convert input data as training format, with given split ratios\n",
|
||||
"# and number of shards on train/test/validation.\n",
|
||||
"data_converter_job_name = get_job_name_with_datetime(\n",
|
||||
" DATA_CONVERTER_JOB_PREFIX + \"_\" + OBJECTIVE\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"input_file_path = \"\" # @param {type:\"string\"}\n",
|
||||
"input_file_type = \"csv\" # @param ['csv', 'jsonl', 'coco_json']\n",
|
||||
"split_ratio = \"0.8,0.1,0.1\"\n",
|
||||
"num_shard = \"10,10,10\"\n",
|
||||
"data_converter_output_dir = os.path.join(BUCKET_URI, data_converter_job_name)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"worker_pool_specs = [\n",
|
||||
" {\n",
|
||||
" \"machine_spec\": {\n",
|
||||
" \"machine_type\": DATA_CONVERTER_MACHINE_TYPE,\n",
|
||||
" },\n",
|
||||
" \"replica_count\": 1,\n",
|
||||
" \"container_spec\": {\n",
|
||||
" \"image_uri\": DATA_CONVERTER_CONTAINER,\n",
|
||||
" \"command\": [],\n",
|
||||
" \"args\": [\n",
|
||||
" \"--input_file_path=%s\" % input_file_path,\n",
|
||||
" \"--input_file_type=%s\" % input_file_type,\n",
|
||||
" \"--objective=%s\" % OBJECTIVE,\n",
|
||||
" \"--num_shard=%s\" % num_shard,\n",
|
||||
" \"--split_ratio=%s\" % split_ratio,\n",
|
||||
" \"--output_dir=%s\" % data_converter_output_dir,\n",
|
||||
" ],\n",
|
||||
" },\n",
|
||||
" }\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"data_converter_custom_job = aiplatform.CustomJob(\n",
|
||||
" display_name=data_converter_job_name,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" worker_pool_specs=worker_pool_specs,\n",
|
||||
" staging_bucket=STAGING_BUCKET,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"data_converter_custom_job.run()\n",
|
||||
"\n",
|
||||
"input_train_data_path = os.path.join(data_converter_output_dir, \"train.tfrecord*\")\n",
|
||||
"input_validation_data_path = os.path.join(data_converter_output_dir, \"val.tfrecord*\")\n",
|
||||
"label_map_path = os.path.join(data_converter_output_dir, \"label_map.yaml\")\n",
|
||||
"print(\"input_train_data_path for training: \", input_train_data_path)\n",
|
||||
"print(\"input_validation_data_path for training: \", input_validation_data_path)\n",
|
||||
"print(\"label_map_path for prediction: \", label_map_path)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "SA8DVTn7j69v"
|
||||
},
|
||||
"source": [
|
||||
"### Create a Vertex AI custom job with hyperparameter tuning\n",
|
||||
"\n",
|
||||
"You use the Vertex AI SDK to create and run the hyperparameter tuning job with Vertex AI Model Garden Training Dockers."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "aaff6f5be7f6"
|
||||
},
|
||||
"source": [
|
||||
"#### Define the following specifications\n",
|
||||
"\n",
|
||||
"* `worker_pool_specs`: Dictionary specifying the machine type and Docker image. This example defines a single node cluster with one `n1-highmem-16` machine with two `NVIDIA_TESLA_V100` GPUs.\n",
|
||||
"* `parameter_spec`: Dictionary specifying the parameters to optimize. The dictionary key is the string assigned to the command line argument for each hyperparameter in your training application code, and the dictionary value is the parameter specification. The parameter specification includes the type, min/max values, and scale for the hyperparameter.\n",
|
||||
"* `metric_spec`: Dictionary specifying the metric to optimize. The dictionary key is the `hyperparameter_metric_tag` that you set in your training application code, and the value is the optimization goal."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "um_XKbmpTaHx"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud.aiplatform import hyperparameter_tuning as hpt\n",
|
||||
"\n",
|
||||
"label_map = get_label_map(label_map_path)\n",
|
||||
"num_classes = len(label_map[\"label_map\"]) + 1\n",
|
||||
"\n",
|
||||
"# Input train and validation datasets can be found from the section above\n",
|
||||
"# `Convert input data for training`.\n",
|
||||
"# Set prepared datasets if exists.\n",
|
||||
"# input_train_data_path = ''\n",
|
||||
"# input_validation_data_path = ''\n",
|
||||
"\n",
|
||||
"# Refer to https://github.com/tensorflow/models/blob/master/official/vision/MODEL_GARDEN.md\n",
|
||||
"# for more model details.\n",
|
||||
"experiment = \"retinanet_spinenet96\" # @param ['retinanet_spinenet49', \"retinanet_spinenet96\", 'retinanet_spinenet143', 'scaled_yolo_v4']\n",
|
||||
"\n",
|
||||
"train_job_name = get_job_name_with_datetime(TRAINING_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"model_dir = os.path.join(BUCKET_URI, train_job_name)\n",
|
||||
"\n",
|
||||
"# The arguments here are mainly for test purposes. Please update them\n",
|
||||
"# to get better performances.\n",
|
||||
"common_args = {\n",
|
||||
" \"input_train_data_path\": input_train_data_path,\n",
|
||||
" \"input_validation_data_path\": input_validation_data_path,\n",
|
||||
" \"objective\": OBJECTIVE,\n",
|
||||
" \"model_dir\": model_dir,\n",
|
||||
" \"num_classes\": num_classes,\n",
|
||||
" \"global_batch_size\": 4,\n",
|
||||
" \"prefetch_buffer_size\": 12,\n",
|
||||
" \"train_steps\": 2000,\n",
|
||||
" \"input_size\": \"1024,1024\",\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"experiment_container_args_dict = {\n",
|
||||
" # retinanet_spinenet49 experiment args.\n",
|
||||
" \"retinanet_spinenet49\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"retinanet_spinenet_coco\",\n",
|
||||
" \"config_file\": TRAIN_SPINENET49_CONFIG,\n",
|
||||
" \"anchor_size\": 4,\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
" # retinanet_spinenet96 experiment args.\n",
|
||||
" \"retinanet_spinenet96\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"retinanet_spinenet_coco\",\n",
|
||||
" \"config_file\": TRAIN_SPINENET96_CONFIG,\n",
|
||||
" \"anchor_size\": 4,\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
" # retinanet_spinenet143 experiment args.\n",
|
||||
" \"retinanet_spinenet143\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"retinanet_spinenet_coco\",\n",
|
||||
" \"config_file\": TRAIN_SPINENET143_CONFIG,\n",
|
||||
" \"anchor_size\": 4,\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
" # scaled_yolo_v4 experiment args.\n",
|
||||
" \"scaled_yolo_v4\": dict(\n",
|
||||
" common_args,\n",
|
||||
" **{\n",
|
||||
" \"experiment\": \"scaled_yolo\",\n",
|
||||
" \"config_file\": TRAIN_YOLOV4_CONFIG,\n",
|
||||
" },\n",
|
||||
" ),\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"params_override = \"runtime.num_gpus=%s\" % TRAIN_NUM_GPU\n",
|
||||
"eval_params_override = \"runtime.num_gpus=1,runtime.distribution_strategy=mirrored\"\n",
|
||||
"worker_pool_specs = [\n",
|
||||
" {\n",
|
||||
" \"machine_spec\": {\n",
|
||||
" \"machine_type\": TRAIN_MACHINE_TYPE,\n",
|
||||
" \"accelerator_type\": TRAIN_ACCELERATOR_TYPE,\n",
|
||||
" \"accelerator_count\": TRAIN_NUM_GPU,\n",
|
||||
" },\n",
|
||||
" \"replica_count\": 1,\n",
|
||||
" \"container_spec\": {\n",
|
||||
" \"image_uri\": TRAIN_CONTAINER_URI,\n",
|
||||
" \"args\": [\n",
|
||||
" \"--mode=train\",\n",
|
||||
" \"--params_override=%s\" % params_override,\n",
|
||||
" ]\n",
|
||||
" + [\n",
|
||||
" \"--{}={}\".format(k, v)\n",
|
||||
" for k, v in experiment_container_args_dict[experiment].items()\n",
|
||||
" ],\n",
|
||||
" },\n",
|
||||
" },\n",
|
||||
" {},\n",
|
||||
" {},\n",
|
||||
" {\n",
|
||||
" \"machine_spec\": {\n",
|
||||
" \"machine_type\": \"n1-highmem-4\",\n",
|
||||
" \"accelerator_type\": TRAIN_ACCELERATOR_TYPE,\n",
|
||||
" \"accelerator_count\": 1,\n",
|
||||
" },\n",
|
||||
" \"replica_count\": 1,\n",
|
||||
" \"container_spec\": {\n",
|
||||
" \"image_uri\": TRAIN_CONTAINER_URI,\n",
|
||||
" \"args\": [\n",
|
||||
" \"--mode=continuous_eval\",\n",
|
||||
" \"--params_override=%s\" % eval_params_override,\n",
|
||||
" ]\n",
|
||||
" + [\n",
|
||||
" \"--{}={}\".format(k, v)\n",
|
||||
" for k, v in experiment_container_args_dict[experiment].items()\n",
|
||||
" ],\n",
|
||||
" },\n",
|
||||
" },\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"metric_spec = {\"model_performance\": \"maximize\"}\n",
|
||||
"\n",
|
||||
"LEARNING_RATES = [0.001, 0.01]\n",
|
||||
"# Models will be trained with each learning rate separately and max trial count is the number of learning rates.\n",
|
||||
"MAX_TRIAL_COUNT = len(LEARNING_RATES)\n",
|
||||
"parameter_spec = {\n",
|
||||
" \"learning_rate\": hpt.DiscreteParameterSpec(values=LEARNING_RATES, scale=\"linear\"),\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"print(worker_pool_specs, metric_spec, parameter_spec)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "HwcCjwlBTQIz"
|
||||
},
|
||||
"source": [
|
||||
"#### Run hyperparameter tuning jobs\n",
|
||||
"* `max_trial_count`: Sets an upper bound on the number of trials the service will run. The recommended practice is to start with a smaller number of trials and get a sense of how impactful your chosen hyperparameters are before scaling up.\n",
|
||||
"\n",
|
||||
"* `parallel_trial_count`: If you use parallel trials, the service provisions multiple training processing clusters. The worker pool spec that you specify when creating the job is used for each individual training cluster. Increasing the number of parallel trials reduces the amount of time the hyperparameter tuning job takes to run; however, it can reduce the effectiveness of the job overall. This is because the default tuning strategy uses results of previous trials to inform the assignment of values in subsequent trials.\n",
|
||||
"\n",
|
||||
"* `search_algorithm`: The available search algorithms are grid, random, or default (None). The default option applies Bayesian optimization to search the space of possible hyperparameter values and is the recommended algorithm.\n",
|
||||
"\n",
|
||||
"Click on the generated link in the output to see your run in the Cloud Console."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "aec22792ee84"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"train_custom_job = aiplatform.CustomJob(\n",
|
||||
" display_name=train_job_name,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" worker_pool_specs=worker_pool_specs,\n",
|
||||
" staging_bucket=STAGING_BUCKET,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"train_hpt_job = aiplatform.HyperparameterTuningJob(\n",
|
||||
" display_name=train_job_name,\n",
|
||||
" custom_job=train_custom_job,\n",
|
||||
" metric_spec=metric_spec,\n",
|
||||
" parameter_spec=parameter_spec,\n",
|
||||
" max_trial_count=MAX_TRIAL_COUNT,\n",
|
||||
" parallel_trial_count=1,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" search_algorithm=None,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"train_hpt_job.run()\n",
|
||||
"\n",
|
||||
"print(\"experiment is: \", experiment)\n",
|
||||
"print(\"model_dir is: \", model_dir)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "mV-Djz-frBni"
|
||||
},
|
||||
"source": [
|
||||
"### Export best models as TF Saved Model format"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "09Rz1AYspK19"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# This job will export models from TF checkpoints to TF saved model format.\n",
|
||||
"# model_dir is from the section above.\n",
|
||||
"best_trial_dir, best_trial_evaluation_results = get_best_trial(\n",
|
||||
" model_dir, MAX_TRIAL_COUNT, EVALUATION_METRIC\n",
|
||||
")\n",
|
||||
"print(\"best_trial_dir: \", best_trial_dir)\n",
|
||||
"print(\"best_trial_evaluation_results: \", best_trial_evaluation_results)\n",
|
||||
"\n",
|
||||
"worker_pool_specs = [\n",
|
||||
" {\n",
|
||||
" \"machine_spec\": {\n",
|
||||
" \"machine_type\": EXPORT_MACHINE_TYPE,\n",
|
||||
" },\n",
|
||||
" \"replica_count\": 1,\n",
|
||||
" \"container_spec\": {\n",
|
||||
" \"image_uri\": EXPORT_CONTAINER_URI,\n",
|
||||
" \"command\": [],\n",
|
||||
" \"args\": [\n",
|
||||
" \"--objective=%s\" % OBJECTIVE,\n",
|
||||
" \"--input_image_size=1024,1024\",\n",
|
||||
" \"--experiment=%s\"\n",
|
||||
" % experiment_container_args_dict[experiment][\"experiment\"],\n",
|
||||
" \"--config_file=%s/params.yaml\" % best_trial_dir,\n",
|
||||
" \"--checkpoint_path=%s/best_ckpt\" % best_trial_dir,\n",
|
||||
" \"--export_dir=%s/best_model\" % model_dir,\n",
|
||||
" ],\n",
|
||||
" },\n",
|
||||
" }\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"model_export_name = get_job_name_with_datetime(EXPORT_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"model_export_custom_job = aiplatform.CustomJob(\n",
|
||||
" display_name=model_export_name,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" worker_pool_specs=worker_pool_specs,\n",
|
||||
" staging_bucket=STAGING_BUCKET,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"model_export_custom_job.run()\n",
|
||||
"\n",
|
||||
"print(\"best model is saved to: \", os.path.join(model_dir, \"best_model\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "g0BGaofgsMsy"
|
||||
},
|
||||
"source": [
|
||||
"## Test trained models\n",
|
||||
"This section will show how to test with trained models.\n",
|
||||
"1. Upload and deploy models\n",
|
||||
"2. Run predictions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "NYuQowyZEtxK"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# @title Upload and deploy models\n",
|
||||
"# model_dir is from the section above.\n",
|
||||
"trained_model_dir = os.path.join(model_dir, \"best_model/saved_model\")\n",
|
||||
"\n",
|
||||
"upload_job_name = get_job_name_with_datetime(UPLOAD_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"\n",
|
||||
"model = aiplatform.Model.upload(\n",
|
||||
" display_name=upload_job_name,\n",
|
||||
" artifact_uri=trained_model_dir,\n",
|
||||
" serving_container_image_uri=PREDICTION_CONTAINER_URI,\n",
|
||||
" serving_container_args=SERVING_CONTAINER_ARGS,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"model.wait()\n",
|
||||
"\n",
|
||||
"print(\"The uploaded model name is: \", upload_job_name)\n",
|
||||
"\n",
|
||||
"deploy_model_name = get_job_name_with_datetime(DEPLOY_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"print(\"The deployed job name is: \", deploy_model_name)\n",
|
||||
"\n",
|
||||
"endpoint = model.deploy(\n",
|
||||
" deployed_model_display_name=deploy_model_name,\n",
|
||||
" machine_type=PREDICTION_MACHINE_TYPE,\n",
|
||||
" traffic_split={\"0\": 100},\n",
|
||||
" accelerator_type=PREDICTION_ACCELERATOR_TYPE,\n",
|
||||
" accelerator_count=1,\n",
|
||||
" min_replica_count=1,\n",
|
||||
" max_replica_count=1,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"endpoint_id = endpoint.name\n",
|
||||
"print(\"endpoint id is: \", endpoint_id)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "vbIW9me1F2RY"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# @title Run predictions\n",
|
||||
"\n",
|
||||
"# endpoint_id was generated in the section above (`Upload and deploy models`).\n",
|
||||
"endpoint_id = endpoint.name\n",
|
||||
"\n",
|
||||
"# The test image file path.\n",
|
||||
"test_filepath = \"\" # @param {type:\"string\"}\n",
|
||||
"score_threshold = 0.2 # @param {type:\"number\"}\n",
|
||||
"# If the input image is too large, we will resize it for prediction.\n",
|
||||
"instances = get_prediction_instances(test_filepath, new_width=1000)\n",
|
||||
"\n",
|
||||
"# The label map file was generated from the section above (`Convert input data for training`).\n",
|
||||
"label_map = get_label_map(label_map_path)[\"label_map\"]\n",
|
||||
"\n",
|
||||
"predictions, _ = predict_custom_trained_model(\n",
|
||||
" project=PROJECT_ID, location=REGION, endpoint_id=endpoint_id, instances=instances\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"img = load_img(test_filepath)\n",
|
||||
"detection_boxes = predictions[0][\"detection_boxes\"]\n",
|
||||
"detection_scores = predictions[0][\"detection_scores\"]\n",
|
||||
"detection_classes_as_text = []\n",
|
||||
"\n",
|
||||
"for detection_class in predictions[0][\"detection_classes\"]:\n",
|
||||
" detection_classes_as_text.append(label_map[int(detection_class)])\n",
|
||||
"\n",
|
||||
"img = draw_boxes(\n",
|
||||
" img,\n",
|
||||
" detection_boxes,\n",
|
||||
" detection_classes_as_text,\n",
|
||||
" detection_scores,\n",
|
||||
" min_score=score_threshold,\n",
|
||||
")\n",
|
||||
"display_image(img)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "kkH2nrpdp4sp"
|
||||
},
|
||||
"source": [
|
||||
"## Clean up"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Ax6vQVZhp9pR"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()\n",
|
||||
"# Delete custom and hpt jobs.\n",
|
||||
"if data_converter_custom_job.list(filter=f'display_name=\"{data_converter_job_name}\"'):\n",
|
||||
" data_converter_custom_job.delete()\n",
|
||||
"if train_hpt_job.list(filter=f'display_name=\"{train_job_name}\"'):\n",
|
||||
" train_hpt_job.delete()\n",
|
||||
"if model_export_custom_job.list(filter=f'display_name=\"{model_export_name}\"'):\n",
|
||||
" model_export_custom_job.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_tfvision_image_object_detection.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -0,0 +1,946 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ur8xi4C7S06n"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "TirJ-SGQseby"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex AI Model Garden TFVision With Image Segmentation\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_tfvision_image_segmentation.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
"\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_tfvision_image_segmentation.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td> <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_tfvision_image_segmentation.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
"Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "dwGLvtIeECLK"
|
||||
},
|
||||
"source": [
|
||||
"**_NOTE_**: This notebook has been tested in the following environment:\n",
|
||||
"\n",
|
||||
"* Python version = 3.9"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "tvgnzT1CKxrO"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates how to use [TFVision](https://github.com/tensorflow/models/blob/master/official/vision/MODEL_GARDEN.md) in Vertex AI Model Garden.\n",
|
||||
"\n",
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"* Train new models\n",
|
||||
" * Convert input data to training formats\n",
|
||||
" * Create [hyperparameter tuning jobs](https://cloud.google.com/vertex-ai/docs/training/hyperparameter-tuning-overview) to train new models\n",
|
||||
" * Find and export best models\n",
|
||||
"\n",
|
||||
"* Test trained models\n",
|
||||
" * Upload models to model registry\n",
|
||||
" * Deploy uploaded models\n",
|
||||
" * Run predictions\n",
|
||||
"\n",
|
||||
"* Cleanup resources\n",
|
||||
"\n",
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI\n",
|
||||
"pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage\n",
|
||||
"pricing](https://cloud.google.com/storage/pricing), and use the [Pricing\n",
|
||||
"Calculator](https://cloud.google.com/products/calculator/)\n",
|
||||
"to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "KEukV6uRk_S3"
|
||||
},
|
||||
"source": [
|
||||
"## Before you begin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "z__i0w0lCAsW"
|
||||
},
|
||||
"source": [
|
||||
"### Colab Only\n",
|
||||
"\n",
|
||||
"Run the following commands for colab and skip this section if you use workbench."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Jvqs-ehKlaYh"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if \"google.colab\" in str(get_ipython()):\n",
|
||||
" ! pip3 install --upgrade google-cloud-aiplatform\n",
|
||||
"\n",
|
||||
" # Automatically restart kernel after installs\n",
|
||||
" import IPython\n",
|
||||
"\n",
|
||||
" app = IPython.Application.instance()\n",
|
||||
" app.kernel.do_shutdown(True)\n",
|
||||
"\n",
|
||||
" from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
" google_auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "BF1j6f9HApxa"
|
||||
},
|
||||
"source": [
|
||||
"### Set up your Google Cloud project\n",
|
||||
"\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
|
||||
"1. If you are running this notebook locally, you will need to install the [Cloud SDK](https://cloud.google.com/sdk).\n",
|
||||
"\n",
|
||||
"1. Enter your project ID in the cell below. Then run the cell to make sure the\n",
|
||||
"Cloud SDK uses the right project for all the commands in this notebook.\n",
|
||||
"\n",
|
||||
"**Note**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9wExiMUxFk91"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"# The project and bucket are for experiments below.\n",
|
||||
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
|
||||
"BUCKET_URI = \"\" # @param {type:\"string\"}\n",
|
||||
"REGION = \"us-central1\"\n",
|
||||
"\n",
|
||||
"! gcloud config set project $PROJECT_ID\n",
|
||||
"\n",
|
||||
"STAGING_BUCKET = os.path.join(BUCKET_URI, \"temporal\")\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=STAGING_BUCKET)\n",
|
||||
"\n",
|
||||
"# Download config files.\n",
|
||||
"CONFIG_DIR = os.path.join(BUCKET_URI, \"config\")\n",
|
||||
"! wget https://raw.githubusercontent.com/tensorflow/models/master/official/vision/configs/experiments/semantic_segmentation/deeplabv3plus_resnet101_cityscapes_gpu_multiworker_mirrored.yaml\n",
|
||||
"! gsutil cp deeplabv3plus_resnet101_cityscapes_gpu_multiworker_mirrored.yaml $CONFIG_DIR"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "n6IFz75WGCam"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "riG_qUokg0XZ"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"OBJECTIVE = \"isg\"\n",
|
||||
"\n",
|
||||
"# Data converter constants.\n",
|
||||
"DATA_CONVERTER_JOB_PREFIX = \"data_converter\"\n",
|
||||
"DATA_CONVERTER_CONTAINER = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/data-converter:latest\"\n",
|
||||
"DATA_CONVERTER_MACHINE_TYPE = \"n1-highmem-8\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Training constants.\n",
|
||||
"TRAINING_JOB_PREFIX = \"train\"\n",
|
||||
"TRAIN_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-oss:latest\"\n",
|
||||
"TRAIN_MACHINE_TYPE = \"n1-highmem-16\"\n",
|
||||
"TRAIN_ACCELERATOR_TYPE = \"NVIDIA_TESLA_V100\"\n",
|
||||
"TRAIN_NUM_GPU = 2\n",
|
||||
"TRAIN_DEEPLABV3PLUS_CONFIG = os.path.join(\n",
|
||||
" CONFIG_DIR, \"deeplabv3plus_resnet101_cityscapes_gpu_multiworker_mirrored.yaml\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# Evaluation constants.\n",
|
||||
"EVALUATION_METRIC = \"mean_iou\"\n",
|
||||
"\n",
|
||||
"# Export constants.\n",
|
||||
"EXPORT_JOB_PREFIX = \"export\"\n",
|
||||
"EXPORT_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-serving:latest\"\n",
|
||||
"EXPORT_MACHINE_TYPE = \"n1-highmem-8\"\n",
|
||||
"\n",
|
||||
"# Prediction constants.\n",
|
||||
"# You can deploy models with\n",
|
||||
"# pre-build-dockers: https://cloud.google.com/vertex-ai/docs/predictions/pre-built-containers.\n",
|
||||
"# and optimized tensorflow runtime dockers: https://cloud.google.com/vertex-ai/docs/predictions/optimized-tensorflow-runtime.\n",
|
||||
"# The example in this notebook uses optimized tensorflow runtime dockers.\n",
|
||||
"# You can adjust accelerator types and machine types to get faster predictions.\n",
|
||||
"PREDICTION_CONTAINER_URI = (\n",
|
||||
" \"us-docker.pkg.dev/vertex-ai-restricted/prediction/tf_opt-gpu.2-11:latest\"\n",
|
||||
")\n",
|
||||
"SERVING_CONTAINER_ARGS = [\"--allow_precompilation\", \"--allow_compression\"]\n",
|
||||
"PREDICTION_ACCELERATOR_TYPE = \"NVIDIA_TESLA_T4\"\n",
|
||||
"PREDICTION_MACHINE_TYPE = \"n1-standard-4\"\n",
|
||||
"UPLOAD_JOB_PREFIX = \"upload\"\n",
|
||||
"DEPLOY_JOB_PREFIX = \"deploy\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ZZFPe_GezXg8"
|
||||
},
|
||||
"source": [
|
||||
"### Define common libraries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "XcYUGwr-AJGY"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import json\n",
|
||||
"import os\n",
|
||||
"from datetime import datetime\n",
|
||||
"from io import BytesIO\n",
|
||||
"from typing import Dict, List, Union\n",
|
||||
"\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import numpy as np\n",
|
||||
"import tensorflow as tf\n",
|
||||
"import yaml\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from google.protobuf import json_format\n",
|
||||
"from google.protobuf.struct_pb2 import Value\n",
|
||||
"from PIL import Image\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_job_name_with_datetime(prefix: str):\n",
|
||||
" return prefix + datetime.now().strftime(\"_%Y%m%d_%H%M%S\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def predict_custom_trained_model(\n",
|
||||
" project: str,\n",
|
||||
" endpoint_id: str,\n",
|
||||
" instances: Union[Dict, List[Dict]],\n",
|
||||
" location: str = \"us-central1\",\n",
|
||||
" api_endpoint: str = \"us-central1-aiplatform.googleapis.com\",\n",
|
||||
"):\n",
|
||||
" # The AI Platform services require regional API endpoints.\n",
|
||||
" client_options = {\"api_endpoint\": api_endpoint}\n",
|
||||
" # Initialize client that will be used to create and send requests.\n",
|
||||
" # This client only needs to be created once, and can be reused for multiple requests.\n",
|
||||
" client = aiplatform.gapic.PredictionServiceClient(client_options=client_options)\n",
|
||||
" parameters_dict = {}\n",
|
||||
" parameters = json_format.ParseDict(parameters_dict, Value())\n",
|
||||
" endpoint = client.endpoint_path(\n",
|
||||
" project=project, location=location, endpoint=endpoint_id\n",
|
||||
" )\n",
|
||||
" response = client.predict(\n",
|
||||
" endpoint=endpoint, instances=instances, parameters=parameters\n",
|
||||
" )\n",
|
||||
" return response.predictions, response.deployed_model_id\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def load_img(path):\n",
|
||||
" img = tf.io.read_file(path)\n",
|
||||
" img = tf.image.decode_jpeg(img, channels=3)\n",
|
||||
" return Image.fromarray(np.uint8(img)).convert(\"RGB\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def display_image(original_image, category_image_color, score_image_grayscale):\n",
|
||||
" _, axarr = plt.subplots(1, 3, figsize=(20, 15))\n",
|
||||
" axarr[0].imshow(original_image)\n",
|
||||
" axarr[1].imshow(category_image_color)\n",
|
||||
" axarr[2].imshow(score_image_grayscale.convert(\"RGB\"))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_prediction_instances(test_filepath, new_width=-1):\n",
|
||||
" if new_width <= 0:\n",
|
||||
" with tf.io.gfile.GFile(test_filepath, \"rb\") as input_file:\n",
|
||||
" encoded_string = base64.b64encode(input_file.read()).decode(\"utf-8\")\n",
|
||||
" else:\n",
|
||||
" img = load_img(test_filepath)\n",
|
||||
" width, height = img.size\n",
|
||||
" print(\"original input image size: \", width, \" , \", height)\n",
|
||||
" new_height = int(height * new_width / width)\n",
|
||||
" new_img = img.resize((new_width, new_height))\n",
|
||||
" print(\"resized input image size: \", new_width, \" , \", new_height)\n",
|
||||
" buffered = BytesIO()\n",
|
||||
" new_img.save(buffered, format=\"JPEG\")\n",
|
||||
" encoded_string = base64.b64encode(buffered.getvalue()).decode(\"utf-8\")\n",
|
||||
"\n",
|
||||
" instances = [\n",
|
||||
" {\n",
|
||||
" \"encoded_image\": {\"b64\": encoded_string},\n",
|
||||
" }\n",
|
||||
" ]\n",
|
||||
" return instances\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_label_map(label_map_yaml_filepath):\n",
|
||||
" with tf.io.gfile.GFile(label_map_yaml_filepath, \"rb\") as input_file:\n",
|
||||
" label_map = yaml.safe_load(input_file.read())\n",
|
||||
" return label_map\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_best_trial(model_dir, max_trial_count, evaluation_metric):\n",
|
||||
" best_trial_dir = \"\"\n",
|
||||
" best_trial_evaluation_results = {}\n",
|
||||
" best_performance = -1\n",
|
||||
"\n",
|
||||
" for i in range(max_trial_count):\n",
|
||||
" current_trial = i + 1\n",
|
||||
" current_trial_dir = os.path.join(model_dir, \"trial_\" + str(current_trial))\n",
|
||||
" current_trial_best_ckpt_dir = os.path.join(current_trial_dir, \"best_ckpt\")\n",
|
||||
" current_trial_best_ckpt_evaluation_filepath = os.path.join(\n",
|
||||
" current_trial_best_ckpt_dir, \"info.json\"\n",
|
||||
" )\n",
|
||||
" with tf.io.gfile.GFile(current_trial_best_ckpt_evaluation_filepath, \"rb\") as f:\n",
|
||||
" eval_metric_results = json.load(f)\n",
|
||||
" current_performance = eval_metric_results[evaluation_metric]\n",
|
||||
" if current_performance > best_performance:\n",
|
||||
" best_performance = current_performance\n",
|
||||
" best_trial_dir = current_trial_dir\n",
|
||||
" best_trial_evaluation_results = eval_metric_results\n",
|
||||
" return best_trial_dir, best_trial_evaluation_results\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_coco_stuff_label_colormap():\n",
|
||||
" \"\"\"Creates a label colormap used in COCO-Stuff segmentation benchmark.\n",
|
||||
"\n",
|
||||
" Returns:\n",
|
||||
" A colormap for visualizing segmentation results.\n",
|
||||
" \"\"\"\n",
|
||||
" return np.asarray(\n",
|
||||
" [\n",
|
||||
" [54, 178, 118],\n",
|
||||
" [0, 85, 178],\n",
|
||||
" [150, 178, 22],\n",
|
||||
" [107, 0, 0],\n",
|
||||
" [0, 0, 89],\n",
|
||||
" [0, 117, 178],\n",
|
||||
" [47, 178, 124],\n",
|
||||
" [178, 116, 0],\n",
|
||||
" [0, 0, 178],\n",
|
||||
" [79, 178, 92],\n",
|
||||
" [134, 0, 0],\n",
|
||||
" [22, 178, 150],\n",
|
||||
" [178, 87, 0],\n",
|
||||
" [178, 146, 0],\n",
|
||||
" [0, 5, 178],\n",
|
||||
" [0, 0, 125],\n",
|
||||
" [0, 53, 178],\n",
|
||||
" [0, 132, 178],\n",
|
||||
" [111, 178, 60],\n",
|
||||
" [178, 131, 0],\n",
|
||||
" [0, 29, 178],\n",
|
||||
" [178, 109, 0],\n",
|
||||
" [178, 35, 0],\n",
|
||||
" [0, 148, 178],\n",
|
||||
" [9, 172, 163],\n",
|
||||
" [0, 0, 178],\n",
|
||||
" [178, 124, 0],\n",
|
||||
" [178, 102, 0],\n",
|
||||
" [0, 156, 175],\n",
|
||||
" [178, 43, 0],\n",
|
||||
" [0, 0, 170],\n",
|
||||
" [178, 94, 0],\n",
|
||||
" [0, 0, 134],\n",
|
||||
" [67, 178, 105],\n",
|
||||
" [99, 178, 73],\n",
|
||||
" [0, 37, 178],\n",
|
||||
" [86, 178, 86],\n",
|
||||
" [15, 178, 156],\n",
|
||||
" [0, 0, 152],\n",
|
||||
" [178, 21, 0],\n",
|
||||
" [0, 124, 178],\n",
|
||||
" [0, 61, 178],\n",
|
||||
" [178, 50, 0],\n",
|
||||
" [0, 109, 178],\n",
|
||||
" [137, 178, 35],\n",
|
||||
" [0, 13, 178],\n",
|
||||
" [0, 101, 178],\n",
|
||||
" [0, 0, 116],\n",
|
||||
" [0, 45, 178],\n",
|
||||
" [41, 178, 131],\n",
|
||||
" [0, 0, 161],\n",
|
||||
" [178, 72, 0],\n",
|
||||
" [0, 0, 143],\n",
|
||||
" [116, 0, 0],\n",
|
||||
" [28, 178, 143],\n",
|
||||
" [170, 6, 0],\n",
|
||||
" [156, 178, 15],\n",
|
||||
" [89, 0, 0],\n",
|
||||
" [143, 178, 28],\n",
|
||||
" [73, 178, 99],\n",
|
||||
" [118, 178, 54],\n",
|
||||
" [92, 178, 79],\n",
|
||||
" [152, 0, 0],\n",
|
||||
" [178, 153, 0],\n",
|
||||
" [98, 0, 0],\n",
|
||||
" [178, 65, 0],\n",
|
||||
" [60, 178, 111],\n",
|
||||
" [169, 175, 3],\n",
|
||||
" [105, 178, 67],\n",
|
||||
" [178, 13, 0],\n",
|
||||
" [163, 178, 9],\n",
|
||||
" [3, 164, 169],\n",
|
||||
" [125, 0, 0],\n",
|
||||
" [175, 168, 0],\n",
|
||||
" [178, 138, 0],\n",
|
||||
" [178, 28, 0],\n",
|
||||
" [35, 178, 137],\n",
|
||||
" [0, 140, 178],\n",
|
||||
" [0, 0, 98],\n",
|
||||
" [131, 178, 41],\n",
|
||||
" [0, 77, 178],\n",
|
||||
" [0, 0, 107],\n",
|
||||
" [0, 93, 178],\n",
|
||||
" [143, 0, 0],\n",
|
||||
" [178, 58, 0],\n",
|
||||
" [161, 0, 0],\n",
|
||||
" [0, 69, 178],\n",
|
||||
" [178, 160, 0],\n",
|
||||
" [178, 80, 0],\n",
|
||||
" [0, 21, 178],\n",
|
||||
" [124, 178, 47],\n",
|
||||
" [255, 214, 0],\n",
|
||||
" ]\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def parse_segmentation_prediction(prediction):\n",
|
||||
" score_bytes = prediction[\"score_bytes\"]\n",
|
||||
" score_image_grayscale = Image.open(\n",
|
||||
" BytesIO(base64.b64decode(dict(score_bytes)[\"b64\"]))\n",
|
||||
" )\n",
|
||||
" category_bytes = prediction[\"category_bytes\"]\n",
|
||||
" category_image_grayscale = Image.open(\n",
|
||||
" BytesIO(base64.b64decode(dict(category_bytes)[\"b64\"]))\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Visualize category images.\n",
|
||||
" color_map = create_coco_stuff_label_colormap()\n",
|
||||
" category_image_grayscale_np = np.array(category_image_grayscale)\n",
|
||||
" rendered_image_shape = category_image_grayscale_np.shape + (3,)\n",
|
||||
" category_image_color_np = np.zeros(rendered_image_shape, dtype=np.uint8)\n",
|
||||
" unique_labels = np.unique(category_image_grayscale_np)\n",
|
||||
" for label in unique_labels:\n",
|
||||
" if label == 0:\n",
|
||||
" continue\n",
|
||||
" category_image_color_np[category_image_grayscale_np == label] = color_map[\n",
|
||||
" label % len(color_map)\n",
|
||||
" ]\n",
|
||||
" category_image_color = Image.fromarray(category_image_color_np)\n",
|
||||
"\n",
|
||||
" return score_image_grayscale, category_image_color"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "RB_xY9ipr7ZU"
|
||||
},
|
||||
"source": [
|
||||
"## Train new models\n",
|
||||
"This section shows how to train new models.\n",
|
||||
"1. Convert input data to training formats\n",
|
||||
"2. Create hyperparameter tuning jobs to train new models\n",
|
||||
"3. Find and export best models\n",
|
||||
"\n",
|
||||
"If you already trained models, please go to the section `Test trained models`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "zgPO1eR3CYjk"
|
||||
},
|
||||
"source": [
|
||||
"### Prepare input data for training\n",
|
||||
"\n",
|
||||
"Prepare data in the format as described [here](https://cloud.google.com/vertex-ai/docs/image-data/classification/prepare-data), and then convert them to the training formats as below:\n",
|
||||
"\n",
|
||||
"* `input_file_path`: The input file path in coco json formats.\n",
|
||||
"* `split_ratio`: The proportion of data to split into train/validation/test.\n",
|
||||
"* `num_shard`: The number of shards for train/validation/test.\n",
|
||||
"* `output_dir`: The output directory, which will container prepared train/test/validation data."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "IndQ_m6ddUEM"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# This job will convert input data as training format, with given split ratios\n",
|
||||
"# and number of shards on train/test/validation.\n",
|
||||
"data_converter_job_name = get_job_name_with_datetime(\n",
|
||||
" DATA_CONVERTER_JOB_PREFIX + \"_\" + OBJECTIVE\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"input_file_path = \"\" # @param {type:\"string\"}\n",
|
||||
"split_ratio = \"0.8,0.1,0.1\"\n",
|
||||
"num_shard = \"10,10,10\"\n",
|
||||
"data_converter_output_dir = os.path.join(BUCKET_URI, data_converter_job_name)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"worker_pool_specs = [\n",
|
||||
" {\n",
|
||||
" \"machine_spec\": {\n",
|
||||
" \"machine_type\": DATA_CONVERTER_MACHINE_TYPE,\n",
|
||||
" },\n",
|
||||
" \"replica_count\": 1,\n",
|
||||
" \"container_spec\": {\n",
|
||||
" \"image_uri\": DATA_CONVERTER_CONTAINER,\n",
|
||||
" \"command\": [],\n",
|
||||
" \"args\": [\n",
|
||||
" \"--input_file_path=%s\" % input_file_path,\n",
|
||||
" \"--input_file_type=coco_json\",\n",
|
||||
" \"--objective=%s\" % OBJECTIVE,\n",
|
||||
" \"--num_shard=%s\" % num_shard,\n",
|
||||
" \"--split_ratio=%s\" % split_ratio,\n",
|
||||
" \"--output_dir=%s\" % data_converter_output_dir,\n",
|
||||
" ],\n",
|
||||
" },\n",
|
||||
" }\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"data_converter_custom_job = aiplatform.CustomJob(\n",
|
||||
" display_name=data_converter_job_name,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" worker_pool_specs=worker_pool_specs,\n",
|
||||
" staging_bucket=STAGING_BUCKET,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"data_converter_custom_job.run()\n",
|
||||
"\n",
|
||||
"input_train_data_path = os.path.join(data_converter_output_dir, \"train.tfrecord*\")\n",
|
||||
"input_validation_data_path = os.path.join(data_converter_output_dir, \"val.tfrecord*\")\n",
|
||||
"label_map_path = os.path.join(data_converter_output_dir, \"label_map.yaml\")\n",
|
||||
"print(\"input_train_data_path for training: \", input_train_data_path)\n",
|
||||
"print(\"input_validation_data_path for training: \", input_validation_data_path)\n",
|
||||
"print(\"label_map_path for prediction: \", label_map_path)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "S6dU2IrIqW3H"
|
||||
},
|
||||
"source": [
|
||||
"### Create a Vertex AI custom job with hyperparameter tuning\n",
|
||||
"\n",
|
||||
"You use the Vertex AI SDK to create and run the hyperparameter tuning job with Vertex AI Model Garden Training Dockers."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "aaff6f5be7f6"
|
||||
},
|
||||
"source": [
|
||||
"#### Define the following specifications\n",
|
||||
"* `worker_pool_specs`: Dictionary specifying the machine type and Docker image. This example defines a single node cluster with one `n1-standard-4` machine with two `NVIDIA_TESLA_T4` GPUs.\n",
|
||||
"* `parameter_spec`: Dictionary specifying the parameters to optimize. The dictionary key is the string assigned to the command line argument for each hyperparameter in your training application code, and the dictionary value is the parameter specification. The parameter specification includes the type, min/max values, and scale for the hyperparameter.\n",
|
||||
"* `metric_spec`: Dictionary specifying the metric to optimize. The dictionary key is the `hyperparameter_metric_tag` that you set in your training application code, and the value is the optimization goal."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "um_XKbmpTaHx"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud.aiplatform import hyperparameter_tuning as hpt\n",
|
||||
"\n",
|
||||
"label_map = get_label_map(label_map_path)\n",
|
||||
"num_classes = len(label_map[\"label_map\"]) + 1\n",
|
||||
"\n",
|
||||
"# Input train and validation datasets can be found from the section above\n",
|
||||
"# `Convert input data for training`.\n",
|
||||
"# Set prepared datasets if exists.\n",
|
||||
"# input_train_data_path = ''\n",
|
||||
"# input_validation_data_path = ''\n",
|
||||
"\n",
|
||||
"# Refer to https://github.com/tensorflow/models/blob/master/official/vision/MODEL_GARDEN.md\n",
|
||||
"# for more model details.\n",
|
||||
"experiment = \"deeplabv3plus\" # @param [\"deeplabv3plus\"]\n",
|
||||
"\n",
|
||||
"train_job_name = get_job_name_with_datetime(TRAINING_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"model_dir = os.path.join(BUCKET_URI, train_job_name)\n",
|
||||
"\n",
|
||||
"# The arguments here are mainly for test purposes. Please update them\n",
|
||||
"# to get better performances.\n",
|
||||
"experiment_container_args_dict = {\n",
|
||||
" # deeplabv3plus experiment args.\n",
|
||||
" \"deeplabv3plus\": {\n",
|
||||
" \"experiment\": \"seg_deeplabv3plus_pascal\",\n",
|
||||
" \"config_file\": TRAIN_DEEPLABV3PLUS_CONFIG,\n",
|
||||
" \"input_train_data_path\": input_train_data_path,\n",
|
||||
" \"input_validation_data_path\": input_validation_data_path,\n",
|
||||
" \"objective\": OBJECTIVE,\n",
|
||||
" \"model_dir\": model_dir,\n",
|
||||
" \"num_classes\": num_classes,\n",
|
||||
" \"global_batch_size\": 2,\n",
|
||||
" \"prefetch_buffer_size\": 12,\n",
|
||||
" \"train_steps\": 500,\n",
|
||||
" \"output_size\": \"1024,2048\",\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"worker_pool_specs = [\n",
|
||||
" {\n",
|
||||
" \"machine_spec\": {\n",
|
||||
" \"machine_type\": TRAIN_MACHINE_TYPE,\n",
|
||||
" \"accelerator_type\": TRAIN_ACCELERATOR_TYPE,\n",
|
||||
" \"accelerator_count\": TRAIN_NUM_GPU,\n",
|
||||
" },\n",
|
||||
" \"replica_count\": 1,\n",
|
||||
" \"container_spec\": {\n",
|
||||
" \"image_uri\": TRAIN_CONTAINER_URI,\n",
|
||||
" \"args\": [\n",
|
||||
" \"--mode=train_and_eval\",\n",
|
||||
" ]\n",
|
||||
" + [\n",
|
||||
" \"--{}={}\".format(k, v)\n",
|
||||
" for k, v in experiment_container_args_dict[experiment].items()\n",
|
||||
" ],\n",
|
||||
" },\n",
|
||||
" },\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"metric_spec = {\"model_performance\": \"maximize\"}\n",
|
||||
"\n",
|
||||
"LEARNING_RATES = [0.001]\n",
|
||||
"# Models will be trained with each learning rate separately and max trial count is the number of learning rates.\n",
|
||||
"MAX_TRIAL_COUNT = len(LEARNING_RATES)\n",
|
||||
"parameter_spec = {\n",
|
||||
" \"learning_rate\": hpt.DiscreteParameterSpec(values=LEARNING_RATES, scale=\"linear\"),\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"print(worker_pool_specs, metric_spec, parameter_spec)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "HwcCjwlBTQIz"
|
||||
},
|
||||
"source": [
|
||||
"#### Run hyperparameter tuning jobs\n",
|
||||
"* `max_trial_count`: Sets an upper bound on the number of trials the service will run. The recommended practice is to start with a smaller number of trials and get a sense of how impactful your chosen hyperparameters are before scaling up.\n",
|
||||
"\n",
|
||||
"* `parallel_trial_count`: If you use parallel trials, the service provisions multiple training processing clusters. The worker pool spec that you specify when creating the job is used for each individual training cluster. Increasing the number of parallel trials reduces the amount of time the hyperparameter tuning job takes to run; however, it can reduce the effectiveness of the job overall. This is because the default tuning strategy uses results of previous trials to inform the assignment of values in subsequent trials.\n",
|
||||
"\n",
|
||||
"* `search_algorithm`: The available search algorithms are grid, random, or default (None). The default option applies Bayesian optimization to search the space of possible hyperparameter values and is the recommended algorithm.\n",
|
||||
"\n",
|
||||
"Click on the generated link in the output to see your run in the Cloud Console."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "aec22792ee84"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"train_custom_job = aiplatform.CustomJob(\n",
|
||||
" display_name=train_job_name,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" worker_pool_specs=worker_pool_specs,\n",
|
||||
" staging_bucket=STAGING_BUCKET,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"train_hpt_job = aiplatform.HyperparameterTuningJob(\n",
|
||||
" display_name=train_job_name,\n",
|
||||
" custom_job=train_custom_job,\n",
|
||||
" metric_spec=metric_spec,\n",
|
||||
" parameter_spec=parameter_spec,\n",
|
||||
" max_trial_count=MAX_TRIAL_COUNT,\n",
|
||||
" parallel_trial_count=1,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" search_algorithm=None,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"train_hpt_job.run()\n",
|
||||
"\n",
|
||||
"print(\"experiment is: \", experiment)\n",
|
||||
"print(\"model_dir is: \", model_dir)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "mV-Djz-frBni"
|
||||
},
|
||||
"source": [
|
||||
"### Export best models as TF Saved Model format"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "09Rz1AYspK19"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# This job will export models from TF checkpoints to TF saved model format.\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"# model_dir is from the section above.\n",
|
||||
"best_trial_dir, best_trial_evaluation_results = get_best_trial(\n",
|
||||
" model_dir, MAX_TRIAL_COUNT, EVALUATION_METRIC\n",
|
||||
")\n",
|
||||
"print(\"best_trial_dir: \", best_trial_dir)\n",
|
||||
"print(\"best_trial_evaluation_results: \", best_trial_evaluation_results)\n",
|
||||
"\n",
|
||||
"worker_pool_specs = [\n",
|
||||
" {\n",
|
||||
" \"machine_spec\": {\n",
|
||||
" \"machine_type\": EXPORT_MACHINE_TYPE,\n",
|
||||
" },\n",
|
||||
" \"replica_count\": 1,\n",
|
||||
" \"container_spec\": {\n",
|
||||
" \"image_uri\": EXPORT_CONTAINER_URI,\n",
|
||||
" \"command\": [],\n",
|
||||
" \"args\": [\n",
|
||||
" \"--objective=%s\" % OBJECTIVE,\n",
|
||||
" \"--experiment=%s\"\n",
|
||||
" % experiment_container_args_dict[experiment][\"experiment\"],\n",
|
||||
" \"--config_file=%s/params.yaml\" % best_trial_dir,\n",
|
||||
" \"--checkpoint_path=%s/best_ckpt\" % best_trial_dir,\n",
|
||||
" \"--export_dir=%s/best_model\" % model_dir,\n",
|
||||
" \"--input_image_size=%s\"\n",
|
||||
" % experiment_container_args_dict[experiment][\"output_size\"],\n",
|
||||
" ],\n",
|
||||
" },\n",
|
||||
" }\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"model_export_name = get_job_name_with_datetime(EXPORT_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"model_export_custom_job = aiplatform.CustomJob(\n",
|
||||
" display_name=model_export_name,\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" worker_pool_specs=worker_pool_specs,\n",
|
||||
" staging_bucket=STAGING_BUCKET,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"model_export_custom_job.run()\n",
|
||||
"\n",
|
||||
"print(\"best model is saved to: \", os.path.join(model_dir, \"best_model\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "g0BGaofgsMsy"
|
||||
},
|
||||
"source": [
|
||||
"## Test trained models\n",
|
||||
"This section shows how to test with trained models.\n",
|
||||
"1. Upload and deploy models\n",
|
||||
"2. Run predictions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "NYuQowyZEtxK"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# @title Upload and deploy models\n",
|
||||
"# model_dir is from the section above.\n",
|
||||
"trained_model_dir = os.path.join(model_dir, \"best_model/saved_model\")\n",
|
||||
"\n",
|
||||
"upload_job_name = get_job_name_with_datetime(UPLOAD_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"\n",
|
||||
"model = aiplatform.Model.upload(\n",
|
||||
" display_name=upload_job_name,\n",
|
||||
" artifact_uri=trained_model_dir,\n",
|
||||
" serving_container_image_uri=PREDICTION_CONTAINER_URI,\n",
|
||||
" serving_container_args=SERVING_CONTAINER_ARGS,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"model.wait()\n",
|
||||
"\n",
|
||||
"print(\"The uploaded model name is: \", upload_job_name)\n",
|
||||
"\n",
|
||||
"deploy_model_name = get_job_name_with_datetime(DEPLOY_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
|
||||
"print(\"The deployed job name is: \", deploy_model_name)\n",
|
||||
"\n",
|
||||
"endpoint = model.deploy(\n",
|
||||
" deployed_model_display_name=deploy_model_name,\n",
|
||||
" machine_type=PREDICTION_MACHINE_TYPE,\n",
|
||||
" traffic_split={\"0\": 100},\n",
|
||||
" accelerator_type=PREDICTION_ACCELERATOR_TYPE,\n",
|
||||
" accelerator_count=1,\n",
|
||||
" min_replica_count=1,\n",
|
||||
" max_replica_count=1,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"endpoint_id = endpoint.name\n",
|
||||
"print(\"endpoint id is: \", endpoint_id)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "vbIW9me1F2RY"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# @title Run predictions\n",
|
||||
"# endpoint_id was generated in the section above (`Upload and deploy models`).\n",
|
||||
"endpoint_id = endpoint.name\n",
|
||||
"\n",
|
||||
"# The test image file path.\n",
|
||||
"test_filepath = \"\" # @param {type:\"string\"}\n",
|
||||
"score_threshold = 0.5 # @param {type:\"number\"}\n",
|
||||
"# If the input image is too large, we will resize it for prediction.\n",
|
||||
"instances = get_prediction_instances(test_filepath, new_width=1000)\n",
|
||||
"\n",
|
||||
"# The label map file was generated from the section above (`Convert input data for training`).\n",
|
||||
"label_map = get_label_map(label_map_path)[\"label_map\"]\n",
|
||||
"\n",
|
||||
"predictions, _ = predict_custom_trained_model(\n",
|
||||
" project=PROJECT_ID, location=REGION, endpoint_id=endpoint_id, instances=instances\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"score_image_grayscale, category_image_color = parse_segmentation_prediction(\n",
|
||||
" dict(predictions[0])\n",
|
||||
")\n",
|
||||
"display_image(\n",
|
||||
" load_img(test_filepath), category_image_color, score_image_grayscale.convert(\"RGB\")\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "kkH2nrpdp4sp"
|
||||
},
|
||||
"source": [
|
||||
"## Clean up"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Ax6vQVZhp9pR"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Undeploy model and delete endpoint.\n",
|
||||
"endpoint.delete(force=True)\n",
|
||||
"# Delete models.\n",
|
||||
"model.delete()\n",
|
||||
"# Delete custom and hpt jobs.\n",
|
||||
"if data_converter_custom_job.list(filter=f'display_name=\"{data_converter_job_name}\"'):\n",
|
||||
" data_converter_custom_job.delete()\n",
|
||||
"if train_hpt_job.list(filter=f'display_name=\"{train_job_name}\"'):\n",
|
||||
" train_hpt_job.delete()\n",
|
||||
"if model_export_custom_job.list(filter=f'display_name=\"{model_export_name}\"'):\n",
|
||||
" model_export_custom_job.delete()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "model_garden_tfvision_image_segmentation.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
+25
-9
@@ -29,7 +29,7 @@
|
||||
"id": "JAPoU8Sm5E6e"
|
||||
},
|
||||
"source": [
|
||||
"# Model Versioning with Vertex AI Model Registry\n",
|
||||
"# Model Management with Vertex AI Model Registry\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"<table align=\"left\">\n",
|
||||
@@ -198,7 +198,7 @@
|
||||
"if IS_WORKBENCH_NOTEBOOK:\n",
|
||||
" USER_FLAG = \"--user\"\n",
|
||||
"\n",
|
||||
"! pip3 install --upgrade tensorflow google-cloud-bigquery google-cloud-aiplatform {USER_FLAG} -q --no-warn-conflicts"
|
||||
"! pip3 install --upgrade tensorflow google-cloud-bigquery google-cloud-aiplatform \"shapely<2\" {USER_FLAG} -q --no-warn-conflicts"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1292,10 +1292,10 @@
|
||||
" pandas \\\n",
|
||||
" python \\\n",
|
||||
" pyspark \\\n",
|
||||
" findspark\n",
|
||||
" findspark \n",
|
||||
"\n",
|
||||
"# Use conda to install spark-nlp\n",
|
||||
"RUN ${CONDA_HOME}/bin/conda install -n base -c johnsnowlabs spark-nlp\n",
|
||||
"RUN ${CONDA_HOME}/bin/conda install -n base -c johnsnowlabs 'spark-nlp=4.0.2'\n",
|
||||
"\n",
|
||||
"# Add lemma dictionary\n",
|
||||
"# ENV CONFIG_DIR='/home/app/build'\n",
|
||||
@@ -1425,7 +1425,7 @@
|
||||
"import sparknlp\n",
|
||||
"from sparknlp.base import *\n",
|
||||
"from sparknlp.annotator import *\n",
|
||||
"from pyspark.ml.feature import CountVectorizer\n",
|
||||
"from pyspark.ml.feature import CountVectorizer, SQLTransformer\n",
|
||||
"from pyspark.ml import Pipeline\n",
|
||||
"\n",
|
||||
"# Variables ------------------------------------------------------------------------------------------------------------\n",
|
||||
@@ -1473,7 +1473,7 @@
|
||||
" Returns:\n",
|
||||
" preliminary_steps: The preliminary steps for the preprocessing.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" \n",
|
||||
" document_assembler = DocumentAssembler().setInputCol(\"text\").setOutputCol(\"document\").setCleanupMode('shrink_full')\n",
|
||||
" sentence_detector = SentenceDetector().setInputCols(\"document\").setOutputCol(\"sentence\")\n",
|
||||
" tokenizer = Tokenizer().setInputCols(\"sentence\").setOutputCol(\"token\")\n",
|
||||
@@ -1512,6 +1512,16 @@
|
||||
" feature_extraction_steps = [count_vectorizer]\n",
|
||||
" return feature_extraction_steps\n",
|
||||
"\n",
|
||||
"def build_postprocessing_steps():\n",
|
||||
" '''\n",
|
||||
" This function builds the postprocessing steps.\n",
|
||||
" Returns:\n",
|
||||
" target_conversion_step: The target conversion step.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" sql_transformer = SQLTransformer(statement=\"SELECT CASE WHEN (category != 'business') THEN 'other' ELSE category END AS category, text, lemma_features, features FROM __THIS__\")\n",
|
||||
" build_postprocessing_steps = [sql_transformer]\n",
|
||||
" return build_postprocessing_steps\n",
|
||||
"\n",
|
||||
"def read_data(spark_session, data_schema, input_dir):\n",
|
||||
" '''\n",
|
||||
@@ -1599,7 +1609,8 @@
|
||||
" preliminary_steps = build_preliminary_steps()\n",
|
||||
" common_preprocess_steps = build_common_preprocess_steps(lemma_uri)\n",
|
||||
" feature_extraction_steps = build_feature_extraction_steps()\n",
|
||||
" pipeline = Pipeline(stages=preliminary_steps + common_preprocess_steps + feature_extraction_steps)\n",
|
||||
" postprocessing_steps = build_postprocessing_steps()\n",
|
||||
" pipeline = Pipeline(stages=preliminary_steps + common_preprocess_steps + feature_extraction_steps + postprocessing_steps)\n",
|
||||
"\n",
|
||||
" # Read data\n",
|
||||
" logger.info('Reading data')\n",
|
||||
@@ -1697,6 +1708,7 @@
|
||||
" --batch=$PREPROCESS_BATCH_ID \\\n",
|
||||
" --container-image=$DATAPROC_RUNTIME_CONTAINER_IMAGE \\\n",
|
||||
" --region=$REGION \\\n",
|
||||
" --version='1.0.21' \\\n",
|
||||
" --subnet='default' \\\n",
|
||||
" --properties spark.executor.instances=2,spark.driver.cores=4,spark.executor.cores=4,spark.app.name=spark_preprocessing_job \\\n",
|
||||
" -- --input_path=$PREPARED_FILE_PATH --lemmas_path=$LEMMA_DICTIONARY_PATH --gcs_output_path=$PROCESS_DATA_PATH --bq_output_table_uri=$BQ_OUTPUT_TABLE_URI --bucket=$BUCKET_NAME --project=$PROJECT_ID"
|
||||
@@ -1954,7 +1966,7 @@
|
||||
" \"accuracy\": round(accuracy_score(y_test, y_pred, sample_weight=get_weights(y_test)), 5),\n",
|
||||
" \"f1_score\": round(f1_score(y_test, y_pred, sample_weight=get_weights(y_test), average=\"weighted\"), 5),\n",
|
||||
" \"log_loss\": round(log_loss(y_test, y_pred_proba, sample_weight=get_weights(y_test)), 5),\n",
|
||||
" \"roc_auc\": round(roc_auc_score(y_test, y_pred_proba, multi_class='ovr'), 5)\n",
|
||||
" \"roc_auc\": round(roc_auc_score(y_test, y_pred_proba[:,1], sample_weight=get_weights(y_test), average=\"weighted\"), 5)\n",
|
||||
" }\n",
|
||||
" return metrics\n",
|
||||
"\n",
|
||||
@@ -2709,7 +2721,11 @@
|
||||
"\n",
|
||||
"versions = registry.list_versions()\n",
|
||||
"for version in versions:\n",
|
||||
" registry.delete_version(version=version.version_id)\n",
|
||||
" if \"default\" not in version.version_aliases:\n",
|
||||
" registry.delete_version(version=version.version_id)\n",
|
||||
" else:\n",
|
||||
" model = registry.get_model(version=\"default\")\n",
|
||||
" model.delete()\n",
|
||||
"\n",
|
||||
"naive_bayes_train_job.delete()\n",
|
||||
"\n",
|
||||
|
||||
+1496
File diff suppressed because it is too large
Load Diff
+95
-41
@@ -54,18 +54,20 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "tvgnzT1CKxrO"
|
||||
"id": "239ba71252d3"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook shows how to use `Vertex AI Pipelines` and `BigQuery ML pipeline components` to train and evaluate a demand forecasting model.\n",
|
||||
"\n",
|
||||
"### Dataset\n",
|
||||
"\n",
|
||||
"The dataset is a modified version of the dataset in [Build and visualize demand forecast predictions using Datastream, Dataflow, BigQuery ML, and Looker\n",
|
||||
"](https://cloud.google.com/architecture/build-visualize-demand-forecast-prediction-datastream-dataflow-bigqueryml-looker) solution architecture\n",
|
||||
"\n",
|
||||
"This notebook shows how to use `Vertex AI Pipelines` and `BigQuery ML pipeline components` to train and evaluate a demand forecasting model."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "25c28706c23e"
|
||||
},
|
||||
"source": [
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"In this tutorial, you learn how to train and evaluate a BigQuery ML model using Vertex AI Pipelines and BigQuery ML pipeline components. \n",
|
||||
@@ -87,8 +89,27 @@
|
||||
" - Generate the ARIMA Plus forecasts\n",
|
||||
" - Generate the ARIMA PLUS forecast explainations\n",
|
||||
"- Compile the pipeline.\n",
|
||||
"- Execute the pipeline.\n",
|
||||
"- Execute the pipeline."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "586acfa9b502"
|
||||
},
|
||||
"source": [
|
||||
"### Dataset\n",
|
||||
"\n",
|
||||
"The dataset is a modified version of the dataset in [Build and visualize demand forecast predictions using Datastream, Dataflow, BigQuery ML, and Looker\n",
|
||||
"](https://cloud.google.com/architecture/build-visualize-demand-forecast-prediction-datastream-dataflow-bigqueryml-looker) solution architecture\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "tvgnzT1CKxrO"
|
||||
},
|
||||
"source": [
|
||||
"### Costs \n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
@@ -352,9 +373,8 @@
|
||||
"id": "06571eb4063b"
|
||||
},
|
||||
"source": [
|
||||
"#### Timestamp\n",
|
||||
"\n",
|
||||
"If you are in a live tutorial session, you might be using a shared test account or project. To avoid name collisions between users on resources created, you create a timestamp for each instance session, and append it onto the name of resources you create in this tutorial."
|
||||
"#### UUID\n",
|
||||
"If you are in a live tutorial session, you might be using a shared test account or project. To avoid name collisions between users on resources created, you create a uuid for each instance session, and append it onto the name of resources you create in this tutorial."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -365,9 +385,16 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from datetime import datetime\n",
|
||||
"import random\n",
|
||||
"import string\n",
|
||||
"\n",
|
||||
"TIMESTAMP = datetime.now().strftime(\"%Y%m%d%H%M%S\")"
|
||||
"\n",
|
||||
"# Generate a uuid of a specifed length(default=8)\n",
|
||||
"def generate_uuid(length: int = 8) -> str:\n",
|
||||
" return \"\".join(random.choices(string.ascii_lowercase + string.digits, k=length))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"UUID = generate_uuid()"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -485,7 +512,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if BUCKET_NAME == \"\" or BUCKET_NAME is None or BUCKET_NAME == \"[your-bucket-name]\":\n",
|
||||
" BUCKET_NAME = PROJECT_ID + \"-aip-\" + TIMESTAMP\n",
|
||||
" BUCKET_NAME = PROJECT_ID + \"-aip-\" + UUID\n",
|
||||
" BUCKET_URI = f\"gs://{BUCKET_NAME}\""
|
||||
]
|
||||
},
|
||||
@@ -706,6 +733,7 @@
|
||||
"KFP_COMPONENTS_PATH = \"components\"\n",
|
||||
"PIPELINES_PATH = \"pipelines\"\n",
|
||||
"\n",
|
||||
"! mkdir -m 777 -p {DATA_PATH}\n",
|
||||
"! mkdir -m 777 -p {KFP_COMPONENTS_PATH}\n",
|
||||
"! mkdir -m 777 -p {PIPELINES_PATH}"
|
||||
]
|
||||
@@ -771,7 +799,7 @@
|
||||
" --location={LOCATION} \\\n",
|
||||
" --source_format=CSV \\\n",
|
||||
" --skip_leading_rows=1\\\n",
|
||||
" fast_fresh.orders_{TIMESTAMP} \\\n",
|
||||
" fast_fresh.orders_{UUID} \\\n",
|
||||
" {RAW_DATA_URI} \\\n",
|
||||
" time_of_sale:DATETIME,order_id:INTEGER,product_name:STRING,price:NUMERIC,quantity:NUMERIC,payment_method:STRING,store_id:INTEGER,user_id:INTEGER"
|
||||
]
|
||||
@@ -782,7 +810,7 @@
|
||||
"id": "ZrgOD30o7HcL"
|
||||
},
|
||||
"source": [
|
||||
"## BQML Training Formalization\n",
|
||||
"## BigQuery ML Training Formalization\n",
|
||||
"\n",
|
||||
"In the next cells, you build the components and pipeline to train and evaluate the BQML demand forecasting model."
|
||||
]
|
||||
@@ -820,13 +848,13 @@
|
||||
"BQ_EVALUATE_MODEL_TABLE_PREFIX = \"orders_arima_model_evaluate\"\n",
|
||||
"BQ_FORECAST_TABLE_PREFIX = \"orders_arima_forecast\"\n",
|
||||
"BQ_EXPLAIN_FORECAST_TABLE_PREFIX = \"orders_arima_explain_forecast\"\n",
|
||||
"BQ_ORDERS_TABLE = f\"{BQ_ORDERS_TABLE_PREFIX}_{TIMESTAMP}\"\n",
|
||||
"BQ_TRAINING_TABLE = f\"{BQ_TRAINING_TABLE_PREFIX}_{TIMESTAMP}\"\n",
|
||||
"BQ_MODEL_TABLE = f\"{BQ_MODEL_TABLE_PREFIX}_{TIMESTAMP}\"\n",
|
||||
"BQ_EVALUATE_TS_TABLE = f\"{BQ_EVALUATE_TS_TABLE_PREFIX}_{TIMESTAMP}\"\n",
|
||||
"BQ_EVALUATE_MODEL_TABLE = f\"{BQ_EVALUATE_MODEL_TABLE_PREFIX}_{TIMESTAMP}\"\n",
|
||||
"BQ_FORECAST_TABLE = f\"{BQ_FORECAST_TABLE_PREFIX}_{TIMESTAMP}\"\n",
|
||||
"BQ_EXPLAIN_FORECAST_TABLE = f\"{BQ_EXPLAIN_FORECAST_TABLE_PREFIX}_{TIMESTAMP}\"\n",
|
||||
"BQ_ORDERS_TABLE = f\"{BQ_ORDERS_TABLE_PREFIX}_{UUID}\"\n",
|
||||
"BQ_TRAINING_TABLE = f\"{BQ_TRAINING_TABLE_PREFIX}_{UUID}\"\n",
|
||||
"BQ_MODEL_TABLE = f\"{BQ_MODEL_TABLE_PREFIX}_{UUID}\"\n",
|
||||
"BQ_EVALUATE_TS_TABLE = f\"{BQ_EVALUATE_TS_TABLE_PREFIX}_{UUID}\"\n",
|
||||
"BQ_EVALUATE_MODEL_TABLE = f\"{BQ_EVALUATE_MODEL_TABLE_PREFIX}_{UUID}\"\n",
|
||||
"BQ_FORECAST_TABLE = f\"{BQ_FORECAST_TABLE_PREFIX}_{UUID}\"\n",
|
||||
"BQ_EXPLAIN_FORECAST_TABLE = f\"{BQ_EXPLAIN_FORECAST_TABLE_PREFIX}_{UUID}\"\n",
|
||||
"\n",
|
||||
"BQ_TRAIN_CONFIGURATION = {\n",
|
||||
" \"destinationTable\": {\n",
|
||||
@@ -1022,7 +1050,7 @@
|
||||
"id": "pcSL1FHk69KT"
|
||||
},
|
||||
"source": [
|
||||
"### Build the BQML training pipeline\n",
|
||||
"### Build the BigQuery ML training pipeline\n",
|
||||
"\n",
|
||||
"Define your workflow using Kubeflow Pipelines DSL package. \n",
|
||||
"\n",
|
||||
@@ -1094,8 +1122,8 @@
|
||||
" location=location,\n",
|
||||
" ).set_display_name(\"get train data\")\n",
|
||||
"\n",
|
||||
" # Train the ARIMA PLUS model\n",
|
||||
" bq_arima_model_op = (\n",
|
||||
" # Run an ARIMA PLUS experiment\n",
|
||||
" bq_arima_model_exp_op = (\n",
|
||||
" BigqueryCreateModelJobOp(\n",
|
||||
" query=f\"\"\"\n",
|
||||
" -- create model table\n",
|
||||
@@ -1104,10 +1132,7 @@
|
||||
" MODEL_TYPE = \\'ARIMA_PLUS\\',\n",
|
||||
" TIME_SERIES_TIMESTAMP_COL = \\'hourly_timestamp\\',\n",
|
||||
" TIME_SERIES_DATA_COL = \\'total_sold\\',\n",
|
||||
" TIME_SERIES_ID_COL = [\\'product_name\\'],\n",
|
||||
" MODEL_REGISTRY = \\'vertex_ai\\',\n",
|
||||
" VERTEX_AI_MODEL_ID = \\'order_demand_forecasting\\',\n",
|
||||
" VERTEX_AI_MODEL_VERSION_ALIASES = [\\'staging\\']\n",
|
||||
" TIME_SERIES_ID_COL = [\\'product_name\\']\n",
|
||||
" ) AS\n",
|
||||
" SELECT\n",
|
||||
" hourly_timestamp,\n",
|
||||
@@ -1119,7 +1144,7 @@
|
||||
" project=project,\n",
|
||||
" location=location,\n",
|
||||
" )\n",
|
||||
" .set_display_name(\"train arima plus model\")\n",
|
||||
" .set_display_name(\"run arima+ model experiment\")\n",
|
||||
" .after(create_training_dataset_op)\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
@@ -1128,12 +1153,12 @@
|
||||
" BigqueryMLArimaEvaluateJobOp(\n",
|
||||
" project=project,\n",
|
||||
" location=location,\n",
|
||||
" model=bq_arima_model_op.outputs[\"model\"],\n",
|
||||
" model=bq_arima_model_exp_op.outputs[\"model\"],\n",
|
||||
" show_all_candidate_models=False,\n",
|
||||
" job_configuration_query=bq_evaluate_time_series_configuration,\n",
|
||||
" )\n",
|
||||
" .set_display_name(\"evaluate arima plus time series\")\n",
|
||||
" .after(bq_arima_model_op)\n",
|
||||
" .after(bq_arima_model_exp_op)\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Evaluate ARIMA Plus model\n",
|
||||
@@ -1141,12 +1166,12 @@
|
||||
" BigqueryEvaluateModelJobOp(\n",
|
||||
" project=project,\n",
|
||||
" location=location,\n",
|
||||
" model=bq_arima_model_op.outputs[\"model\"],\n",
|
||||
" model=bq_arima_model_exp_op.outputs[\"model\"],\n",
|
||||
" query_statement=f\"\"\"SELECT * FROM `{project}.{bq_dataset}.{bq_training_table}` WHERE split='TEST'\"\"\",\n",
|
||||
" job_configuration_query=bq_evaluate_model_configuration,\n",
|
||||
" )\n",
|
||||
" .set_display_name(\"evaluate arima plus model\")\n",
|
||||
" .after(bq_arima_model_op)\n",
|
||||
" .after(bq_arima_model_exp_op)\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Plot model metrics\n",
|
||||
@@ -1164,6 +1189,34 @@
|
||||
" < PERF_THRESHOLD,\n",
|
||||
" name=\"avg. mae good\",\n",
|
||||
" ):\n",
|
||||
" # Train the ARIMA PLUS model\n",
|
||||
" bq_arima_model_op = (\n",
|
||||
" BigqueryCreateModelJobOp(\n",
|
||||
" query=f\"\"\"\n",
|
||||
" -- create model table\n",
|
||||
" CREATE OR REPLACE MODEL `{project}.{bq_dataset}.{bq_model_table}`\n",
|
||||
" OPTIONS(\n",
|
||||
" MODEL_TYPE = \\'ARIMA_PLUS\\',\n",
|
||||
" TIME_SERIES_TIMESTAMP_COL = \\'hourly_timestamp\\',\n",
|
||||
" TIME_SERIES_DATA_COL = \\'total_sold\\',\n",
|
||||
" TIME_SERIES_ID_COL = [\\'product_name\\'],\n",
|
||||
" MODEL_REGISTRY = \\'vertex_ai\\',\n",
|
||||
" VERTEX_AI_MODEL_ID = \\'order_demand_forecasting\\',\n",
|
||||
" VERTEX_AI_MODEL_VERSION_ALIASES = [\\'staging\\']\n",
|
||||
" ) AS\n",
|
||||
" SELECT\n",
|
||||
" DATETIME_TRUNC(time_of_sale, HOUR) as hourly_timestamp,\n",
|
||||
" product_name,\n",
|
||||
" SUM(quantity) AS total_sold,\n",
|
||||
" FROM `{project}.{bq_dataset}.{bq_orders_table}`\n",
|
||||
" GROUP BY hourly_timestamp, product_name;\n",
|
||||
" \"\"\",\n",
|
||||
" project=project,\n",
|
||||
" location=location,\n",
|
||||
" )\n",
|
||||
" .set_display_name(\"train arima+ model\")\n",
|
||||
" .after(get_evaluation_model_metrics_op)\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Generate the ARIMA PLUS forecasts\n",
|
||||
" bq_arima_forecast_op = (\n",
|
||||
@@ -1224,7 +1277,7 @@
|
||||
"source": [
|
||||
"### Execute your pipeline\n",
|
||||
"\n",
|
||||
"Next, you execute the pipeline. It takes the following parameters which we set as default:\n",
|
||||
"Next, we execute the pipeline. It takes the following parameters which we set as default:\n",
|
||||
"\n",
|
||||
"- `bq_dataset`: The BigQuery dataset to train on.\n",
|
||||
"- `bq_orders_table` : The BigQuery table of raw data.\n",
|
||||
@@ -1266,7 +1319,7 @@
|
||||
"source": [
|
||||
"### View BigQuery ML training pipeline results\n",
|
||||
"\n",
|
||||
"Finally, you will view the artifact outputs of each task in the pipeline."
|
||||
"Finally, you view the artifact outputs of each task in the pipeline."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1342,8 +1395,8 @@
|
||||
"print(\"bigquery-ml-arima-evaluate-job\")\n",
|
||||
"artifacts = print_pipeline_output(bqml_pipeline, \"bigquery-ml-arima-evaluate-job\")\n",
|
||||
"print(\"\\n\\n\")\n",
|
||||
"print(\"get-model-evaluation-metrics\")\n",
|
||||
"artifacts = print_pipeline_output(bqml_pipeline, \"get-model-evaluation-metrics\")\n",
|
||||
"print(\"bigquery-evaluate-model-job\")\n",
|
||||
"artifacts = print_pipeline_output(bqml_pipeline, \"bigquery-evaluate-model-job\")\n",
|
||||
"print(\"\\n\\n\")\n",
|
||||
"print(\"bigquery-forecast-model-job\")\n",
|
||||
"artifacts = print_pipeline_output(bqml_pipeline, \"bigquery-forecast-model-job\")\n",
|
||||
@@ -1407,7 +1460,8 @@
|
||||
"\n",
|
||||
"# Remove local resorces\n",
|
||||
"! rm -rf {KFP_COMPONENTS_PATH}\n",
|
||||
"! rm -rf {PIPELINES_PATH}"
|
||||
"! rm -rf {PIPELINES_PATH}\n",
|
||||
"! rm -rf {DATA_PATH}"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
+870
@@ -0,0 +1,870 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "view-in-github"
|
||||
},
|
||||
"source": [
|
||||
"<a href=\"https://colab.research.google.com/github/Narwhalprime/vertex-ai-samples/blob/main/notebooks/community/pipelines/google_cloud_pipeline_components_cloud_natural_language_pipeline.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "1142fd18"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2022 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "BwO30Ag12YcB"
|
||||
},
|
||||
"source": [
|
||||
"# Vertex Pipelines: Cloud Natural Language model training pipeline\n",
|
||||
"<table align=\"left\">\n",
|
||||
"\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/pipelines/google_cloud_pipeline_components_cloud_natural_language_pipeline.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/pipelines/google_cloud_pipeline_components_cloud_natural_language_pipeline.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/ai/platform/notebooks/deploy-notebook?download_url=https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/natural_language/cloud_natural_language_pipeline.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
" Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "tvgnzT1CKxrO"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"This notebook shows how to use [Google Cloud Pipeline Components SDK](https://cloud.google.com/vertex-ai/docs/pipelines/components-introduction) and additional components in this directory to run a machine learning pipeline in [Vertex AI Pipelines](https://cloud.google.com/vertex-ai/docs/pipelines/introduction) to train a TensorFlow text classification model.\n",
|
||||
"\n",
|
||||
"In this pipeline, the model training Docker image utilizes [TFHub](https://tfhub.dev/) models to perform state-of-the-art text classification training. The image is pre-built and ready to use, so no additional Docker setup is required."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d975e698c9a4"
|
||||
},
|
||||
"source": [
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"In this tutorial, you learn how to construct an end-to-end training pipeine within Vertex AI pipelines that ingests a dataset, trains a text classification model on it, and outputs evaluation metrics.\n",
|
||||
"\n",
|
||||
"This tutorial uses the following Google Cloud ML services and resources:\n",
|
||||
"\n",
|
||||
"- Vertex AI Pipelines\n",
|
||||
"- Vertex AI Datasets\n",
|
||||
"\n",
|
||||
"The steps performed include:\n",
|
||||
"\n",
|
||||
"- Define Kubeflow pipeline components\n",
|
||||
"- Setup Kubeflow pipeline\n",
|
||||
"- Run pipeline on Vertex AI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "08d289fa873f"
|
||||
},
|
||||
"source": [
|
||||
"## Dataset\n",
|
||||
"\n",
|
||||
"This notebook requires that the user has two datasets exported from Vertex AI [managed datasets](https://cloud.google.com/vertex-ai/docs/training/using-managed-datasets): one with train and validation data splits, and the other with test data used for evaluation. Please ensure no data is shared between the two datasets (in particular, no evaluation data should be part of the train or validation splits). To export a Vertex AI dataset, please follow the following public docs:\n",
|
||||
"* [Preparing data](https://cloud.google.com/vertex-ai/docs/text-data/classification/prepare-data)\n",
|
||||
"* [Creating a Vertex AI dataset](https://cloud.google.com/vertex-ai/docs/text-data/classification/create-dataset) from the above data\n",
|
||||
"* [Exporting dataset and its annotations](https://cloud.google.com/vertex-ai/docs/datasets/export-metadata-annotations); ensure the resulting export is located in a Google Cloud Storage (GCS) bucket you own. You may need to manually separate the test split data into its own file."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "aed92deeb4a0"
|
||||
},
|
||||
"source": [
|
||||
"## Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI\n",
|
||||
"* Cloud Storage\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI\n",
|
||||
"pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage\n",
|
||||
"pricing](https://cloud.google.com/storage/pricing), and use the [Pricing\n",
|
||||
"Calculator](https://cloud.google.com/products/calculator/)\n",
|
||||
"to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "setup_local"
|
||||
},
|
||||
"source": [
|
||||
"## Setup\n",
|
||||
"\n",
|
||||
"If you are using Colab or Google Vertex AI Workbench Notebooks, your environment already meets all the requirements to run this notebook. You can skip this step.\n",
|
||||
"\n",
|
||||
"***NOTE***: This notebook has been tested in the following environment:\n",
|
||||
"\n",
|
||||
"* Python version = 3.8\n",
|
||||
"\n",
|
||||
"Otherwise, make sure your environment meets this notebook's requirements. You need the following:\n",
|
||||
"\n",
|
||||
"- The Cloud Storage SDK\n",
|
||||
"- Python 3\n",
|
||||
"- virtualenv\n",
|
||||
"- Jupyter notebook running in a virtual environment with Python 3\n",
|
||||
"\n",
|
||||
"The Cloud Storage guide to [Setting up a Python development environment](https://cloud.google.com/python/setup) and the [Jupyter installation guide](https://jupyter.org/install) provide detailed instructions for meeting these requirements. The following steps provide a condensed set of instructions:\n",
|
||||
"\n",
|
||||
"1. [Install and initialize the SDK](https://cloud.google.com/sdk/docs/).\n",
|
||||
"\n",
|
||||
"2. [Install Python 3](https://cloud.google.com/python/setup#installing_python).\n",
|
||||
"\n",
|
||||
"3. [Install virtualenv](https://cloud.google.com/python/setup#installing_and_using_virtualenv) and create a virtual environment that uses Python 3. Activate the virtual environment.\n",
|
||||
"\n",
|
||||
"4. Activate that environment and run `pip3 install Jupyter` in a terminal shell to install Jupyter.\n",
|
||||
"\n",
|
||||
"5. Run `jupyter notebook` on the command line in a terminal shell to launch Jupyter.\n",
|
||||
"\n",
|
||||
"6. Open this notebook in the Jupyter Notebook Dashboard.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "568d5c16"
|
||||
},
|
||||
"source": [
|
||||
"### Install additional packages\n",
|
||||
"\n",
|
||||
"Run the following commands to setup the packages for this notebook. Note that the last code snippet in this section restarts your kernel in order to load the installs properly, so when initalizing this notebook from scratch, it is recommended to run up to that cell, then afterwards you may start running the cell after that."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "dac98aac"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Install using pip3\n",
|
||||
"!pip3 install -U tensorflow google-cloud-pipeline-components google-cloud-aiplatform kfp==1.8.16 \"shapely<2\" -q"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "alRWYgYTdz7P"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Version check\n",
|
||||
"# This has been tested with KFP 1.8.16\n",
|
||||
"! python3 -c \"import kfp; print('KFP SDK version: {}'.format(kfp.__version__))\"\n",
|
||||
"! python3 -c \"import google_cloud_pipeline_components; print('google_cloud_pipeline_components version: {}'.format(google_cloud_pipeline_components.__version__))\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "d0a15440"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"if not os.getenv(\"IS_TESTING\"):\n",
|
||||
" # Automatically restart kernel after installs\n",
|
||||
" import IPython\n",
|
||||
"\n",
|
||||
" app = IPython.Application.instance()\n",
|
||||
" app.kernel.do_shutdown(True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "B9IYalYObAbY"
|
||||
},
|
||||
"source": [
|
||||
"## Before you begin\n",
|
||||
"\n",
|
||||
"### Set up your Google Cloud project\n",
|
||||
"\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"2. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"3. [Enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,storage.googleapis.com).\n",
|
||||
"\n",
|
||||
"4. If you are running this notebook locally, you need to install the [Cloud SDK](https://cloud.google.com/sdk)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "VA_kzAIIj2G_"
|
||||
},
|
||||
"source": [
|
||||
"### Authenticate your Google Cloud account\n",
|
||||
"\n",
|
||||
"**If you are using Vertex AI Workbench Notebooks**, your environment is already\n",
|
||||
"authenticated. Skip this step.\n",
|
||||
"\n",
|
||||
"**If you are using Colab**, run the cell below and follow the instructions\n",
|
||||
"when prompted to authenticate your account via oAuth.\n",
|
||||
"\n",
|
||||
"**Otherwise**, follow these steps:\n",
|
||||
"\n",
|
||||
"1. In the Cloud Console, go to the [**Create service account key**\n",
|
||||
" page](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
|
||||
"\n",
|
||||
"2. Click **Create service account**.\n",
|
||||
"\n",
|
||||
"3. In the **Service account name** field, enter a name, and\n",
|
||||
" click **Create**.\n",
|
||||
"\n",
|
||||
"4. In the **Grant this service account access to project** section, click the **Role** drop-down list. Type \"Vertex AI\"\n",
|
||||
"into the filter box, and select\n",
|
||||
" **Vertex AI Administrator**. Type \"Storage Object Admin\" into the filter box, and select **Storage Object Admin**.\n",
|
||||
"\n",
|
||||
"5. Click *Create*. A JSON file that contains your key downloads to your\n",
|
||||
"local environment.\n",
|
||||
"\n",
|
||||
"6. Enter the path to your service account key as the\n",
|
||||
"`GOOGLE_APPLICATION_CREDENTIALS` variable in the cell below and run the cell."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "PyQmSRbKA8r-"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# If you are running this notebook in Colab, run this cell and follow the\n",
|
||||
"# instructions to authenticate your GCP account. This provides access to your\n",
|
||||
"# Cloud Storage bucket and lets you submit training jobs and prediction\n",
|
||||
"# requests.\n",
|
||||
"\n",
|
||||
"import os\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"# If on Vertex AI Workbench, then don't execute this code\n",
|
||||
"IS_COLAB = \"google.colab\" in sys.modules\n",
|
||||
"if not os.path.exists(\"/opt/deeplearning/metadata/env_version\") and not os.getenv(\n",
|
||||
" \"DL_ANACONDA_HOME\"\n",
|
||||
"):\n",
|
||||
" if \"google.colab\" in sys.modules:\n",
|
||||
" from google.colab import auth as google_auth\n",
|
||||
"\n",
|
||||
" google_auth.authenticate_user()\n",
|
||||
"\n",
|
||||
" # If you are running this notebook locally, replace the string below with the\n",
|
||||
" # path to your service account key and run this cell to authenticate your GCP\n",
|
||||
" # account.\n",
|
||||
" elif not os.getenv(\"IS_TESTING\"):\n",
|
||||
" %env GOOGLE_APPLICATION_CREDENTIALS ''"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "set_service_account"
|
||||
},
|
||||
"source": [
|
||||
"### Set project ID\n",
|
||||
"\n",
|
||||
"Set your project ID here. If you don't know this, the following snippet attempts to deterine this from your gcloud config. Please continue only if the notebook can see your desired project."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "AkqEd5Gin9mn"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"PROJECT_ID = \"your-project-id\" # @param {type:\"string\"}\n",
|
||||
"if PROJECT_ID == \"\" or PROJECT_ID is None or PROJECT_ID == \"[your-project-id]\":\n",
|
||||
" # Get your GCP project id from gcloud\n",
|
||||
" shell_output = !gcloud config list --format 'value(core.project)' 2>/dev/null\n",
|
||||
" PROJECT_ID = shell_output[0]\n",
|
||||
"print(\"Project ID:\", PROJECT_ID)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "OVO_gUqpFEP2"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!gcloud config set project $PROJECT_ID"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "a27d4cee"
|
||||
},
|
||||
"source": [
|
||||
"### Setup project information\n",
|
||||
"\n",
|
||||
"Enter information about your project and datasets here."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7e9477a2"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"REGION = \"us\" # @param {type:\"string\"}\n",
|
||||
"LOCATION = \"us-central1\" # @param {type:\"string\"}\n",
|
||||
"TRAINING_DATA_LOCATION = \"gs://your-training-data-location\" # @param {type:\"string\"}\n",
|
||||
"TASK_TYPE = \"CLASSIFICATION\" # @param [\"CLASSIFICATION\", \"MULTILABEL_CLASSIFICATION\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "o-MZnHsimbOH"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Since we are training a custom model, we need to specify the list of possible\n",
|
||||
"# classes/labels.\n",
|
||||
"# e.g, [\"FirstClass\", \"SecondClass\"]\n",
|
||||
"# An additional class \"[UNK]\" will be added to the list indicating that none of\n",
|
||||
"# the specified labels are a match.\n",
|
||||
"CLASS_NAMES = [\"\"]\n",
|
||||
"\n",
|
||||
"# This is a list of GCS URIs; e.g., [\"gs://your-bucket-name-here/your-input-file.jsonl\"].\n",
|
||||
"TEST_DATA_URIS = [\"gs://your-bucket-name-here/your-input-file.jsonl\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "timestamp"
|
||||
},
|
||||
"source": [
|
||||
"#### UUID\n",
|
||||
"\n",
|
||||
"To avoid name collisions with other resources in your project, you can create a UUID with the code below and append it onto the name of the bucket(s) created in this notebook."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "wh9sgzemwLXE"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import random\n",
|
||||
"import string\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Generate a uuid of a specifed length(default=8)\n",
|
||||
"def generate_uuid(length: int = 8) -> str:\n",
|
||||
" return \"\".join(random.choices(string.ascii_lowercase + string.digits, k=length))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"UUID = generate_uuid()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "bucket:mbsdk"
|
||||
},
|
||||
"source": [
|
||||
"### Create a Cloud Storage bucket\n",
|
||||
"\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"When you initialize the Vertex AI SDK for Python, you specify a Cloud Storage staging bucket. The staging bucket is where all the data associated with your dataset and model resources are retained across sessions.\n",
|
||||
"\n",
|
||||
"Set the name of your Cloud Storage bucket below. Bucket names must be globally unique across all Google Cloud projects, including those outside of your organization."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "bucket"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"BUCKET_NAME = \"[your-bucket-name]\" # @param {type:\"string\"}\n",
|
||||
"BUCKET_URI = f\"gs://{BUCKET_NAME}\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "autoset_bucket"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"if BUCKET_NAME == \"\" or BUCKET_NAME is None or BUCKET_NAME == \"[your-bucket-name]\":\n",
|
||||
" BUCKET_NAME = PROJECT_ID + \"aip-\" + UUID\n",
|
||||
" BUCKET_URI = \"gs://\" + BUCKET_NAME"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "create_bucket"
|
||||
},
|
||||
"source": [
|
||||
"**Only if your bucket doesn't already exist**: Run the following cell to create your Cloud Storage bucket."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "dO0NV93IwLXF"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!gsutil mb -l $REGION $BUCKET_URI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "validate_bucket"
|
||||
},
|
||||
"source": [
|
||||
"Finally, validate access to your Cloud Storage bucket by examining its contents:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Hg5f2oKBwLXG"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!gsutil ls -al $BUCKET_URI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "EuFETRptyKXc"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google.cloud import aiplatform\n",
|
||||
"\n",
|
||||
"aiplatform.init(project=PROJECT_ID, staging_bucket=BUCKET_URI)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "f3a09765"
|
||||
},
|
||||
"source": [
|
||||
"## Create training pipeline"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "89bb4a50"
|
||||
},
|
||||
"source": [
|
||||
"### Import libraries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "0f361e65"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from google_cloud_pipeline_components.aiplatform import ModelBatchPredictOp\n",
|
||||
"from google_cloud_pipeline_components.experimental import natural_language\n",
|
||||
"from google_cloud_pipeline_components.experimental.evaluation import (\n",
|
||||
" GetVertexModelOp, ModelEvaluationClassificationOp,\n",
|
||||
" TargetFieldDataRemoverOp)\n",
|
||||
"from kfp import components\n",
|
||||
"from kfp.v2 import compiler, dsl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "d33c87e4-2ada-4b87-bf75-064247f3162d"
|
||||
},
|
||||
"source": [
|
||||
"### Define constants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "36ceb9f8"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Worker pool specs\n",
|
||||
"TRAINING_MACHINE_TYPE = \"n1-highmem-8\"\n",
|
||||
"ACCELERATOR_TYPE = \"NVIDIA_TESLA_T4\"\n",
|
||||
"ACCELERATOR_COUNT = 1\n",
|
||||
"EVAL_MACHINE_TYPE = \"n1-highmem-8\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "zAaMJKrhAe5L"
|
||||
},
|
||||
"source": [
|
||||
"## Define components\n",
|
||||
"\n",
|
||||
"This pipeline is composed from the following components:\n",
|
||||
"\n",
|
||||
"- **train-tfhub-model** - Trains a new Tensorflow model using TFHub layers from pre-built Docker image\n",
|
||||
"- **upload-tensorflow-model-to-google-cloud-vertex-ai** - Uploads resulting model to Vertex AI model registry\n",
|
||||
"- **get-vertex-model** - Gets model that has just been uploaded as an artifact in pipeline\n",
|
||||
"- **convert-dataset-export-for-batch-predict** - Preprocessing component that takes the test dataset exported from Vertex datasets and converts it to a simpler compatible one that is readable from the batch predict component\n",
|
||||
"- **target-field-data-remover** - Removes the target field (i.e., label) in the test dataset for the downstream batch predict component\n",
|
||||
"- **model-batch-predict** - Performs a batch prediction job\n",
|
||||
"- **model-evaluation-classification** - Calculates the evaluation metrics from the above batch predict job and exports the metrics artifact\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "DKe2iQNKgpKG"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Load upload TF model component\n",
|
||||
"upload_tensorflow_model_to_vertex_op = components.load_component_from_url(\n",
|
||||
" \"https://raw.githubusercontent.com/Ark-kun/pipeline_components/c6a8b67d1ada2cc17665c99ff6b410df588bee28/components/google-cloud/Vertex_AI/Models/Upload_Tensorflow_model/workaround_for_buggy_KFPv2_compiler/component.yaml\"\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "TEnh9Pcx6Xfi"
|
||||
},
|
||||
"source": [
|
||||
"### Define the pipeline\n",
|
||||
"\n",
|
||||
"The pipeline performs the following steps:\n",
|
||||
"- Trains new text classification model\n",
|
||||
"- Uploads model to Vertex AI Model Registry\n",
|
||||
"- Performs preprocessing steps on test dataset export: formats data for batch predcition, removes target field\n",
|
||||
"- Performs batch prediction on preprocessed test data\n",
|
||||
"- Evaluates performance of model based on batch prediction output"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "2a67cde8"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"@dsl.pipeline(name=\"text-classification-model\")\n",
|
||||
"def pipeline():\n",
|
||||
" train_task = natural_language.TrainTextClassificationOp()(\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" location=LOCATION,\n",
|
||||
" machine_type=TRAINING_MACHINE_TYPE,\n",
|
||||
" accelerator_type=ACCELERATOR_TYPE,\n",
|
||||
" accelerator_count=ACCELERATOR_COUNT,\n",
|
||||
" input_data_path=TRAINING_DATA_LOCATION,\n",
|
||||
" input_format=\"jsonl\",\n",
|
||||
" natural_language_task_type=TASK_TYPE,\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" upload_task = upload_tensorflow_model_to_vertex_op(\n",
|
||||
" model=train_task.outputs[\"model_output\"]\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" get_model_task = GetVertexModelOp(\n",
|
||||
" model_resource_name=upload_task.outputs[\"model_name\"]\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" classification_type = (\n",
|
||||
" \"multilabel\" if TASK_TYPE == \"MULTILABEL_CLASSIFICATION\" else \"multiclass\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" convert_dataset_task = natural_language.ConvertDatasetExportForBatchPredictOp(\n",
|
||||
" file_paths=TEST_DATA_URIS, classification_type=classification_type\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" target_field_remover_task = TargetFieldDataRemoverOp(\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" location=LOCATION,\n",
|
||||
" root_dir=BUCKET_URI,\n",
|
||||
" gcs_source_uris=convert_dataset_task.outputs[\"output_files\"],\n",
|
||||
" target_field_name=\"labels\",\n",
|
||||
" instances_format=\"jsonl\",\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Note: ModelBatchPredictOp doesn't support accelerators currently.\n",
|
||||
" batch_predict_task = ModelBatchPredictOp(\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" location=LOCATION,\n",
|
||||
" model=get_model_task.outputs[\"model\"],\n",
|
||||
" job_display_name=\"nl-batch-predict-evaluation\",\n",
|
||||
" gcs_source_uris=target_field_remover_task.outputs[\"gcs_output_directory\"],\n",
|
||||
" instances_format=\"jsonl\",\n",
|
||||
" predictions_format=\"jsonl\",\n",
|
||||
" gcs_destination_output_uri_prefix=BUCKET_URI,\n",
|
||||
" machine_type=EVAL_MACHINE_TYPE,\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" # Note: Because we're running a custom training pipeline, the model source\n",
|
||||
" # is detected as Custom and thus it doesn't use AutoML NL's default settings\n",
|
||||
" # and fails if class_labels is excluded.\n",
|
||||
" ModelEvaluationClassificationOp(\n",
|
||||
" project=PROJECT_ID,\n",
|
||||
" location=LOCATION,\n",
|
||||
" root_dir=BUCKET_URI,\n",
|
||||
" class_labels=CLASS_NAMES + [\"[UNK]\"],\n",
|
||||
" predictions_gcs_source=batch_predict_task.outputs[\"gcs_output_directory\"],\n",
|
||||
" predictions_format=\"jsonl\",\n",
|
||||
" prediction_label_column=\"prediction.displayNames\",\n",
|
||||
" prediction_score_column=\"prediction.confidences\",\n",
|
||||
" ground_truth_gcs_source=convert_dataset_task.outputs[\"output_files\"],\n",
|
||||
" ground_truth_format=\"jsonl\",\n",
|
||||
" target_field_name=\"labels\",\n",
|
||||
" classification_type=TASK_TYPE,\n",
|
||||
" )"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "3211ba19"
|
||||
},
|
||||
"source": [
|
||||
"### Compile the pipeline"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "c368c73f"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"compiler.Compiler().compile(pipeline, \"nl_pipeline.json\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "l_Vxwz5cdF5f"
|
||||
},
|
||||
"source": [
|
||||
"Running the above line will generate a file locally or in Colab's directory."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ax0jOxIaholy"
|
||||
},
|
||||
"source": [
|
||||
"### Run the pipeline\n",
|
||||
"\n",
|
||||
"This sends a create pipeline job request to Vertex Pipelines. Note that this task run synchronously and may take a while to complete.\n",
|
||||
"\n",
|
||||
"You may view the progress of the job at any time by clicking on the generated links (after \"View Pipeline Job\" in the console output of the cell below). Once the pipeline finishes, you may examine the artifacts produced from this pipeline."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Wfs7QOSxhp_n"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"job = aiplatform.PipelineJob(\n",
|
||||
" display_name=\"nl_pipeline\",\n",
|
||||
" template_path=\"nl_pipeline.json\",\n",
|
||||
" location=LOCATION,\n",
|
||||
" enable_caching=True,\n",
|
||||
" parameter_values={},\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"job.run()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "UIyGPaihWJWn"
|
||||
},
|
||||
"source": [
|
||||
"Once the pipeline successfully finishes, go to the pipeline and examine the resulting metrics artifacts for the results. Otherwise, refer to the failing step(s) in the pipeline to determine the cause of any errors."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "OoexTJTy9jnH"
|
||||
},
|
||||
"source": [
|
||||
"## View model evaluation results\n",
|
||||
"\n",
|
||||
"To check the results of evaluation after pipeline execution, find the \"model-evaluation-classification\" subdirectory in the Cloud Storage bucket created by this pipeline. You may also run the following to directly output the contents of the metrics file:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "h9EqPCQF9lN9"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"\n",
|
||||
"EVAL_TASK_NAME = \"model-evaluation-classification\"\n",
|
||||
"PROJECT_NUMBER = job.gca_resource.name.split(\"/\")[1]\n",
|
||||
"for _ in range(len(job.gca_resource.job_detail.task_details)):\n",
|
||||
" TASK_ID = job.gca_resource.job_detail.task_details[_].task_id\n",
|
||||
" EVAL_METRICS = (\n",
|
||||
" BUCKET_URI\n",
|
||||
" + \"/\"\n",
|
||||
" + PROJECT_NUMBER\n",
|
||||
" + \"/\"\n",
|
||||
" + job.name\n",
|
||||
" + \"/\"\n",
|
||||
" + EVAL_TASK_NAME\n",
|
||||
" + \"_\"\n",
|
||||
" + str(TASK_ID)\n",
|
||||
" + \"/executor_output.json\"\n",
|
||||
" )\n",
|
||||
" if tf.io.gfile.exists(EVAL_METRICS):\n",
|
||||
" ! gsutil cat $EVAL_METRICS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "TpV-iwP9qw9c"
|
||||
},
|
||||
"source": [
|
||||
"## Cleaning up\n",
|
||||
"\n",
|
||||
"To clean up the resources used by this pipeline, run the command below:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "sx_vKniMq9ZX"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Delete GCS bucket.\n",
|
||||
"!gsutil -m rm -r {BUCKET_URI}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "UMuyzrnZLoUa"
|
||||
},
|
||||
"source": [
|
||||
"# Next steps\n",
|
||||
"\n",
|
||||
"For an alternate approach, please check out the [\"ready-to-go\" text classification pipeline](https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/master/notebooks/community/pipelines/google_cloud_pipeline_components_ready_to_go_text_classification_pipeline.ipynb). This pipeline exposes the model logic for further customization if needed, and adds an additional pipeline step to deploy the model to enable online predictions."
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"collapsed_sections": [
|
||||
"d975e698c9a4",
|
||||
"08d289fa873f",
|
||||
"d33c87e4-2ada-4b87-bf75-064247f3162d",
|
||||
"3211ba19",
|
||||
"TpV-iwP9qw9c",
|
||||
"UMuyzrnZLoUa"
|
||||
],
|
||||
"name": "google_cloud_pipeline_components_cloud_natural_language_pipeline.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
+1208
File diff suppressed because it is too large
Load Diff
+1750
File diff suppressed because it is too large
Load Diff
+1872
File diff suppressed because it is too large
Load Diff
+1506
File diff suppressed because one or more lines are too long
@@ -112,7 +112,7 @@ def benchmark(
|
||||
|
||||
results = []
|
||||
for qps in qps_list:
|
||||
num_requests = max(qps * duration_sec, 10)
|
||||
num_requests = int(max(qps * duration_sec, 10))
|
||||
requests_for_qps = list(
|
||||
itertools.islice(itertools.cycle(requests), num_requests)
|
||||
)
|
||||
|
||||
+1569
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,987 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "18ebbd838e32"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2023 Google LLC\n",
|
||||
"#\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# https://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "219f1b1fe8fe"
|
||||
},
|
||||
"source": [
|
||||
"# Deploy and host a Stable Diffusion model on Vertex AI\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "JAPoU8Sm5E6e"
|
||||
},
|
||||
"source": [
|
||||
"<table align=\"left\">\n",
|
||||
"\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/vertex_endpoints/torchserve/dreambooth_stablediffusion.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/vertex_endpoints/torchserve/dreambooth_stablediffusion.ipynb\">\n",
|
||||
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
|
||||
" View on GitHub\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
" <td>\n",
|
||||
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/vertex_endpoints/torchserve/dreambooth_stablediffusion.ipynb\">\n",
|
||||
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
|
||||
" Open in Vertex AI Workbench\n",
|
||||
" </a>\n",
|
||||
" </td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "fce05a8186d6"
|
||||
},
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"This notebook demonstrates how to deploy and host a fine-tuned [Stable Diffusion 1.5](https://huggingface.co/runwayml/stable-diffusion-v1-5) model on Vertex AI. For hosting, you use the PyTorch 3 container built for Vertex AI with [TorchServe](https://pytorch.org/serve/index.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "c76216b03fec"
|
||||
},
|
||||
"source": [
|
||||
"### Objective\n",
|
||||
"\n",
|
||||
"In this tutorial, you learn how to host and deploy a Stable Diffusion 1.5 model on Vertex AI.\n",
|
||||
"\n",
|
||||
"This tutorial uses the following Google Cloud ML services:\n",
|
||||
"\n",
|
||||
"+ Vertex AI `Model` resource\n",
|
||||
"+ Vertex AI `Endpoint` resource\n",
|
||||
"\n",
|
||||
"The steps performed include:\n",
|
||||
"\n",
|
||||
"+ Create a `torchserve` handler for responding to prediction requests.\n",
|
||||
"+ Upload a Stable Diffusion 1.5 model on a prebuilt PyTorch container in Vertex AI.\n",
|
||||
"+ Deploy a model to a Vertex AI Endpoint.\n",
|
||||
"+ Send requests to the endpoint and parse the responses using Vertex AI Prediction service."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "c6deba5a8557"
|
||||
},
|
||||
"source": [
|
||||
"### Model\n",
|
||||
"\n",
|
||||
"This notebook uses a collection of model artifacts fine-tuned to generate images of a small dog. These are the same images used in the original [DreamBooth paper](https://dreambooth.github.io/)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "911dc651ea9c"
|
||||
},
|
||||
"source": [
|
||||
"### Costs\n",
|
||||
"\n",
|
||||
"This tutorial uses billable components of Google Cloud:\n",
|
||||
"\n",
|
||||
"* Vertex AI models\n",
|
||||
"* Vertex AI endpoints\n",
|
||||
"* Vertex AI prediction\n",
|
||||
"* Cloud Storage\n",
|
||||
"* (Optionally) Vertex AI Workbench\n",
|
||||
"\n",
|
||||
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing) and [Cloud Storage pricing](https://cloud.google.com/storage/pricing), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0d36bd3d53fa"
|
||||
},
|
||||
"source": [
|
||||
"## Hardware requirements\n",
|
||||
"\n",
|
||||
"This notebook requires that you use a GPU with a sufficient amount of VRAM available. It was tested on a `NVIDIA Tesla A100 GPU` with 85 GB of VRAM. Run the following cell to ensure that you have the correct hardware configuration."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "3dd4022552e5"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!nvidia-smi --query-gpu=name,memory.total,memory.free --format=\"csv,noheader\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "a782627e5f73"
|
||||
},
|
||||
"source": [
|
||||
"### Create a user-managed notebook on Vertex AI\n",
|
||||
"\n",
|
||||
"If you are using Vertex AI Workbench, you can create a notebook with the correct configuration by doing the following:\n",
|
||||
"\n",
|
||||
"+ Go to [Vertex AI Workbench](https://console.cloud.google.com/vertex-ai/workbench/user-managed) in the Google Cloud Console.\n",
|
||||
"+ Click **New Notebook** and then click **PyTorch 1.13** > **With 1 NVIDIA T4**.\n",
|
||||
"+ In the **New notebook** dialog box, click **Advanced Options**. The **Create a user-managed notebook** page opens up.\n",
|
||||
"+ In the **Create a user-managed notebook** page, do the following:\n",
|
||||
" * In the **Notebook name** box, type a name for your notebook, for example \"my-stablediffusion-nb\".\n",
|
||||
" * In the **Machine type** drop-down, select **A2 highgpu** > **a2-highgpu-1g**.\n",
|
||||
" * In the **GPU type** drop-down, select **NVIDIA Tesla A100**.\n",
|
||||
" * Check the box next to **Install NVIDIA GPU driver automatically for me**\n",
|
||||
" * Expand **Disk(s)** and do the following:\n",
|
||||
" - Under **Boot disk type**, select **SSD Persistent Disk**.\n",
|
||||
" - Under **Data disk type**, select **SSD Persistent Disk**.\n",
|
||||
" * Click **Create**."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "FAPoU8Sm5E6e"
|
||||
},
|
||||
"source": [
|
||||
"<div style=\"background:#feefe3; padding:5px; color:#aa0000\">\n",
|
||||
"<strong>Caution:</strong> Using a Vertex AI Workbench notebook with the above configuration can increase your costs significantly. You can estimate your costs using the <a href=\"https://cloud.google.com/products/calculator\"><u>costs calculator</u></a>.</div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0bb4201cc99a"
|
||||
},
|
||||
"source": [
|
||||
"## Installation\n",
|
||||
"\n",
|
||||
"Install the following packages required to execute this notebook.\n",
|
||||
"\n",
|
||||
"**Note**: You might need to change the version of PyTorch (`torch`) installed by `pip`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "9c769df171a6"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%%writefile requirements.txt\n",
|
||||
"diffusers\n",
|
||||
"ftfy\n",
|
||||
"google-cloud-aiplatform\n",
|
||||
"gradio\n",
|
||||
"ninja\n",
|
||||
"tensorboard==1.15.0\n",
|
||||
"torch\n",
|
||||
"torchaudio\n",
|
||||
"torchvision\n",
|
||||
"torchserve\n",
|
||||
"torch-model-archiver\n",
|
||||
"torch-workflow-archiver\n",
|
||||
"transformers"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "e46804ac90d8"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%pip install -r requirements.txt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "58707a750154"
|
||||
},
|
||||
"source": [
|
||||
"### Colab only: Uncomment the following cell to restart the kernel."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "77c11549298a"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Automatically restart kernel after installs so that your environment can access the new packages\n",
|
||||
"# import IPython\n",
|
||||
"\n",
|
||||
"# app = IPython.Application.instance()\n",
|
||||
"# app.kernel.do_shutdown(True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "294df346a918"
|
||||
},
|
||||
"source": [
|
||||
"## Before you begin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "BF1j6f9HApxa"
|
||||
},
|
||||
"source": [
|
||||
"### Set up your Google Cloud project\n",
|
||||
"\n",
|
||||
"**The following steps are required, regardless of your notebook environment.**\n",
|
||||
"\n",
|
||||
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
|
||||
"\n",
|
||||
"2. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
|
||||
"\n",
|
||||
"3. [Enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com).\n",
|
||||
"\n",
|
||||
"4. If you are running this notebook locally, you need to install the [Cloud SDK](https://cloud.google.com/sdk)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "WReHDGG5g0XY"
|
||||
},
|
||||
"source": [
|
||||
"#### Set your project ID\n",
|
||||
"\n",
|
||||
"**If you don't know your project ID**, try the following:\n",
|
||||
"* Run `gcloud config list`.\n",
|
||||
"* Run `gcloud projects list`.\n",
|
||||
"* See the support page: [Locate the project ID](https://support.google.com/googleapi/answer/7014113)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "oM1iC_MfAts1"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}\n",
|
||||
"\n",
|
||||
"# Set the project id\n",
|
||||
"! gcloud config set project {PROJECT_ID}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "region"
|
||||
},
|
||||
"source": [
|
||||
"#### Region\n",
|
||||
"\n",
|
||||
"You can also change the `REGION` variable used by Vertex AI. Learn more about [Vertex AI regions](https://cloud.google.com/vertex-ai/docs/general/locations)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "region"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"REGION = \"us-central1\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "sBCra4QMA2wR"
|
||||
},
|
||||
"source": [
|
||||
"### Authenticate your Google Cloud account\n",
|
||||
"\n",
|
||||
"Depending on your Jupyter environment, you may have to manually authenticate. Follow the relevant instructions below."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "74ccc9e52986"
|
||||
},
|
||||
"source": [
|
||||
"**1. Vertex AI Workbench**\n",
|
||||
"* Do nothing as you are already authenticated."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "de775a3773ba"
|
||||
},
|
||||
"source": [
|
||||
"**2. Local JupyterLab instance, uncomment and run:**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "254614fa0c46"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# ! gcloud auth login"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ef21552ccea8"
|
||||
},
|
||||
"source": [
|
||||
"**3. Colab, uncomment and run:**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "603adbbf0532"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# from google.colab import auth\n",
|
||||
"# auth.authenticate_user()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "f6b2ccc891ed"
|
||||
},
|
||||
"source": [
|
||||
"**4. Service account or other**\n",
|
||||
"* See how to grant Cloud Storage permissions to your service account at https://cloud.google.com/storage/docs/gsutil/commands/iam#ch-examples."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "cb5c4ca3e851"
|
||||
},
|
||||
"source": [
|
||||
"### Import libraries"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "7348591eda51"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import base64\n",
|
||||
"import math\n",
|
||||
"\n",
|
||||
"import torch\n",
|
||||
"from diffusers import StableDiffusionPipeline\n",
|
||||
"from google.cloud import aiplatform\n",
|
||||
"from IPython import display\n",
|
||||
"from PIL import Image\n",
|
||||
"from torch import autocast"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "697566b5f660"
|
||||
},
|
||||
"source": [
|
||||
"## Optional: View model inferences\n",
|
||||
"\n",
|
||||
"Before uploading the model to Vertex AI, you can review the expected output from the model. The model used in this notebook is available for your use and can be downloaded from Cloud Storage. This download may take a few minutes to complete."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "d63df8d91215"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!gsutil -m cp gs://cloud-samples-data/vertex-ai/model-deployment/models/stable-diffusion/model_artifacts.zip \\\n",
|
||||
" ."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "89d613ae9573"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!unzip model_artifacts.zip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "9192ea4f3b57"
|
||||
},
|
||||
"source": [
|
||||
"### Create new images\n",
|
||||
"\n",
|
||||
"With everything in place, you can now generate new images from the Stable Diffusion model. First you must load your model into a `StableDiffusionPipeline`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "cd1f30223b79"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model_path = \"model_artifacts\"\n",
|
||||
"\n",
|
||||
"pipe = StableDiffusionPipeline.from_pretrained(\n",
|
||||
" model_path, torch_dtype=torch.float16\n",
|
||||
").to(\"cuda\")\n",
|
||||
"\n",
|
||||
"g_cuda = None"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "dd91520f58cf"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"g_cuda = torch.Generator(device=\"cuda\")\n",
|
||||
"seed = 52362\n",
|
||||
"g_cuda.manual_seed(seed)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "1e9c5d734b9f"
|
||||
},
|
||||
"source": [
|
||||
"With the model loaded into a `StableDiffusionPipeline`, you can now generate results (inferences) from the model. Each set of inference requires an input (called a [prompt](https://learnprompting.org/)) that specifies what the model should create.\n",
|
||||
"\n",
|
||||
"You can also vary other inputs into the model, as shown in the following cell."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "a28b73de55ce"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"prompt = \"photo of examplePup dog in a Monet style\"\n",
|
||||
"\n",
|
||||
"num_samples = 4\n",
|
||||
"num_batches = 1\n",
|
||||
"num_columns = 2\n",
|
||||
"guidance_scale = 10\n",
|
||||
"num_inference_steps = 50\n",
|
||||
"height = 512\n",
|
||||
"width = 512"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "11a7bb79de59"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def image_grid(imgs, cols):\n",
|
||||
" total = len(imgs)\n",
|
||||
" rows = math.ceil(total / cols)\n",
|
||||
"\n",
|
||||
" w, h = imgs[0].size\n",
|
||||
" grid = Image.new(\"RGB\", size=(cols * w, rows * h))\n",
|
||||
" grid_w, grid_h = grid.size\n",
|
||||
"\n",
|
||||
" for i, img in enumerate(imgs):\n",
|
||||
" grid.paste(img, box=(i % cols * w, i // cols * h))\n",
|
||||
" return grid\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"all_images = []\n",
|
||||
"for _ in range(num_batches):\n",
|
||||
" with autocast(\"cuda\"):\n",
|
||||
" images = pipe(\n",
|
||||
" [prompt] * num_samples,\n",
|
||||
" height=height,\n",
|
||||
" width=width,\n",
|
||||
" num_inference_steps=num_inference_steps,\n",
|
||||
" guidance_scale=guidance_scale,\n",
|
||||
" ).images\n",
|
||||
" all_images.extend(images)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"grid = image_grid(all_images, num_columns)\n",
|
||||
"grid"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "bbc72963ff88"
|
||||
},
|
||||
"source": [
|
||||
"## Deploy the model to Vertex AI\n",
|
||||
"\n",
|
||||
"You can host your Stable Diffusion 1.5 model on a Vertex AI endpoint where you can get inferences from it online. Uploading your model is a four step process: \n",
|
||||
"\n",
|
||||
"1. Create a custom TorchServe handler.\n",
|
||||
"1. Upload the model artifacts onto Cloud Storage.\n",
|
||||
"2. Create a Vertex AI model with the model artifacts and a prebuilt PyTorch container image.\n",
|
||||
"3. Deploy the Vertex AI model onto an endpoint."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "eafbb0e0-40e6-43a0-a38e-edc54323da51"
|
||||
},
|
||||
"source": [
|
||||
"### Create the custom TorchServe handler\n",
|
||||
"\n",
|
||||
"The model deployed to Vertex AI uses [TorchServe](https://pytorch.org/serve/) to handle requests and return responses from the model. You must create a custom TorchServe handler to include in with the model artifacts uploaded to Vertex AI.\n",
|
||||
"\n",
|
||||
"The handler file should be included in the directory with the other model artifacts."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "94567a87-9d74-4c87-a749-306ddaf01b61"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%%writefile model_artifacts/handler.py\n",
|
||||
"\n",
|
||||
"\"\"\"Customized handler for Stable Diffusion 1.5.\"\"\"\n",
|
||||
"import base64\n",
|
||||
"import logging\n",
|
||||
"from io import BytesIO\n",
|
||||
"\n",
|
||||
"import torch\n",
|
||||
"from diffusers import EulerDiscreteScheduler\n",
|
||||
"from diffusers import StableDiffusionPipeline\n",
|
||||
"from ts.torch_handler.base_handler import BaseHandler\n",
|
||||
"\n",
|
||||
"logger = logging.getLogger(__name__)\n",
|
||||
"model_id = 'runwayml/stable-diffusion-v1-5'\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class ModelHandler(BaseHandler):\n",
|
||||
"\n",
|
||||
" def __init__(self):\n",
|
||||
" self.initialized = False\n",
|
||||
" self.map_location = None\n",
|
||||
" self.device = None\n",
|
||||
" self.use_gpu = True\n",
|
||||
" self.store_avg = True\n",
|
||||
" self.pipe = None\n",
|
||||
"\n",
|
||||
" def initialize(self, context):\n",
|
||||
" \"\"\"Initializes the pipe.\"\"\"\n",
|
||||
" properties = context.system_properties\n",
|
||||
" gpu_id = properties.get('gpu_id')\n",
|
||||
"\n",
|
||||
" self.map_location, self.device, self.use_gpu = \\\n",
|
||||
" ('cuda', torch.device('cuda:' + str(gpu_id)),\n",
|
||||
" True) if torch.cuda.is_available() else \\\n",
|
||||
" ('cpu', torch.device('cpu'), False)\n",
|
||||
"\n",
|
||||
" # Use the Euler scheduler here instead\n",
|
||||
" scheduler = EulerDiscreteScheduler.from_pretrained(model_id,\n",
|
||||
" subfolder='scheduler')\n",
|
||||
" pipe = StableDiffusionPipeline.from_pretrained(model_id,\n",
|
||||
" scheduler=scheduler,\n",
|
||||
" torch_dtype=torch.float16)\n",
|
||||
" pipe = pipe.to('cuda')\n",
|
||||
" # Uncomment the following line to reduce the GPU memory usage.\n",
|
||||
" # pipe.enable_attention_slicing()\n",
|
||||
" self.pipe = pipe\n",
|
||||
"\n",
|
||||
" self.initialized = True\n",
|
||||
"\n",
|
||||
" def preprocess(self, requests):\n",
|
||||
" \"\"\"Noting to do here.\"\"\"\n",
|
||||
" logger.info('requests: %s', requests)\n",
|
||||
" return requests\n",
|
||||
"\n",
|
||||
" def inference(self, preprocessed_data, *args, **kwargs):\n",
|
||||
" \"\"\"Run the inference.\"\"\"\n",
|
||||
" images = []\n",
|
||||
" for pd in preprocessed_data:\n",
|
||||
" prompt = pd['prompt']\n",
|
||||
" images.extend(self.pipe(prompt).images)\n",
|
||||
" return images\n",
|
||||
"\n",
|
||||
" def postprocess(self, output_batch):\n",
|
||||
" \"\"\"Converts the images to base64 string.\"\"\"\n",
|
||||
" postprocessed_data = []\n",
|
||||
" for op in output_batch:\n",
|
||||
" fp = BytesIO()\n",
|
||||
" op.save(fp, format='JPEG')\n",
|
||||
" postprocessed_data.append(base64.b64encode(fp.getvalue()).decode('utf-8'))\n",
|
||||
" fp.close()\n",
|
||||
" return postprocessed_data\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "6ace1dac0af0"
|
||||
},
|
||||
"source": [
|
||||
"After creating the handler file, you must package the handler as a model archiver (MAR) file. The output file must be named 'model.mar'."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "67707f95d440"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!torch-model-archiver \\\n",
|
||||
" -f \\\n",
|
||||
" --model-name model \\\n",
|
||||
" --version 1.0 \\\n",
|
||||
" --handler model_artifacts/handler.py \\\n",
|
||||
" --export-path model_artifacts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ffab030f4bc8"
|
||||
},
|
||||
"source": [
|
||||
"### Upload the model artifacts to Cloud Storage\n",
|
||||
"\n",
|
||||
"Create a new folder in your Cloud Storage bucket to hold the model artifacts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "MzGDU7TWdts_"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"BUCKET_NAME = \"your-bucket-name-unique\" # @param {type:\"string\"}\n",
|
||||
"BUCKET_URI = f\"gs://{BUCKET_NAME}/\"\n",
|
||||
"FULL_GCS_PATH = f\"{BUCKET_URI}model_artifacts\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "-EcIXiGsCePi"
|
||||
},
|
||||
"source": [
|
||||
"**Only if your bucket doesn't already exist**: Run the following cell to create your Cloud Storage bucket."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "NIq7R4HZCfIc"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"! gsutil mb -l $REGION -p $PROJECT_ID $BUCKET_URI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "971232e28657"
|
||||
},
|
||||
"source": [
|
||||
"Next, upload the model archive file and your trained Stable Diffusion 1.5 model to the folder on Cloud Storage."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ef6baf44c808"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!gsutil cp -r model_artifacts $BUCKET_URI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "402370ca9396"
|
||||
},
|
||||
"source": [
|
||||
"### Create the Vertex AI model\n",
|
||||
"\n",
|
||||
"Once you've uploaded the model artifacts into a Cloud Storage bucket, you can create a new Vertex AI model. This notebook uses the [Vertex AI SDK](https://cloud.google.com/vertex-ai/docs/start/use-vertex-ai-python-sdk) to create the model."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "b6c58a74a0fd"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"PYTORCH_PREDICTION_IMAGE_URI = (\n",
|
||||
" \"us-docker.pkg.dev/vertex-ai/prediction/pytorch-gpu.1-12:latest\"\n",
|
||||
")\n",
|
||||
"APP_NAME = \"my-stable-diffusion\"\n",
|
||||
"VERSION = 1\n",
|
||||
"MODEL_DISPLAY_NAME = \"stable_diffusion_1_5-unique\"\n",
|
||||
"MODEL_DESCRIPTION = \"stable_diffusion_1_5 container\"\n",
|
||||
"ENDPOINT_DISPLAY_NAME = f\"{APP_NAME}-endpoint\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "07c3503a1a2e"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=BUCKET_NAME)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "FAPoU8Sm5E6e"
|
||||
},
|
||||
"source": [
|
||||
"<div style=\"background:#e3effe; padding:5px; color:#0000aa\">\n",
|
||||
"<strong>Note:</strong> The next cell fails if you haven't <a href=\"https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com\"><u>enabled the Vertex API</u></a>.</div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "a776324dd16f"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model = aiplatform.Model.upload(\n",
|
||||
" display_name=MODEL_DISPLAY_NAME,\n",
|
||||
" description=MODEL_DESCRIPTION,\n",
|
||||
" serving_container_image_uri=PYTORCH_PREDICTION_IMAGE_URI,\n",
|
||||
" artifact_uri=FULL_GCS_PATH,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"model.wait()\n",
|
||||
"\n",
|
||||
"print(model.display_name)\n",
|
||||
"print(model.resource_name)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0fbc3d371574"
|
||||
},
|
||||
"source": [
|
||||
"### Deploy the model to an endpoint\n",
|
||||
"\n",
|
||||
"To get online preductions from your Stable Diffusion 2.0 model, you must [deploy it to a Vertex AI endpoint](https://cloud.google.com/vertex-ai/docs/predictions/overview). You can again use the Vertex AI SDK to create the endpoint and deploy your model."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "ab29f0a770cb"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"endpoint = aiplatform.Endpoint.create(display_name=ENDPOINT_DISPLAY_NAME)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "25f703df88c7"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model.deploy(\n",
|
||||
" endpoint=endpoint,\n",
|
||||
" deployed_model_display_name=MODEL_DISPLAY_NAME,\n",
|
||||
" machine_type=\"n1-standard-8\",\n",
|
||||
" accelerator_type=\"NVIDIA_TESLA_P100\",\n",
|
||||
" accelerator_count=1,\n",
|
||||
" traffic_percentage=100,\n",
|
||||
" deploy_request_timeout=1200,\n",
|
||||
" sync=True,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "c9fc560df0a9"
|
||||
},
|
||||
"source": [
|
||||
"The previous cell, which deploys your model to the endpoint, can take a while to complete. If the previous cell times out before returning, your endpoint might still be successfully deployed to an endpoint. Check the [Cloud Console](https://console.cloud.google.com/vertex-ai/endpoints) to verify the results.\n",
|
||||
"\n",
|
||||
"You can also extend the time to wait for deployment by changing the `deploy_request_timeout` argument passed to `model.deploy()`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "88a5304dfdc9"
|
||||
},
|
||||
"source": [
|
||||
"## Get online predictions\n",
|
||||
"\n",
|
||||
"Finally, with your Stable Diffusion 1.5 model deployed to a Vertex AI endpoint, you can now get online predictions from it. Using the Vertex AI SDK, you only need a few lines of code to get an inference."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "0d6bc4aa34d6"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"instances = [{\"prompt\": \"An examplePup dog with a baseball jersey.\"}]\n",
|
||||
"response = endpoint.predict(instances=instances)\n",
|
||||
"\n",
|
||||
"with open(\"img5.jpg\", \"wb\") as g:\n",
|
||||
" g.write(base64.b64decode(response.predictions[0]))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "65bafefda60c"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"display.Image(\"img5.jpg\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "TpV-iwP9qw9c"
|
||||
},
|
||||
"source": [
|
||||
"## Cleaning up\n",
|
||||
"\n",
|
||||
"To clean up all Google Cloud resources used in this project, you can [delete the Google Cloud\n",
|
||||
"project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#shutting_down_projects) you used for the tutorial.\n",
|
||||
"\n",
|
||||
"Otherwise, you can delete the individual resources you created in this tutorial:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "sx_vKniMq9ZX"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"# Delete endpoint resource\n",
|
||||
"endpoint.undeploy_all()\n",
|
||||
"endpoint.delete()\n",
|
||||
"\n",
|
||||
"# Delete model resource\n",
|
||||
"model.delete()\n",
|
||||
"\n",
|
||||
"# Delete Cloud Storage objects that were created\n",
|
||||
"delete_bucket = False\n",
|
||||
"if delete_bucket or os.getenv(\"IS_TESTING\"):\n",
|
||||
" ! gsutil -m rm -r $BUCKET_URI"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"name": "dreambooth_stablediffusion.ipynb",
|
||||
"toc_visible": true
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"name": "python3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -74,7 +74,9 @@
|
||||
"source": [
|
||||
"## Overview\n",
|
||||
"\n",
|
||||
"{TODO: Include a paragraph or two explaining what this example demonstrates, who should be interested in it, and what you need to know before you get started.}"
|
||||
"{TODO: Include a paragraph or two explaining what this example demonstrates, who should be interested in it, and what you need to know before you get started.}\n",
|
||||
"\n",
|
||||
"Learn more about [web-doc-title](linkback-to-webdoc-page). {TODO: if more than one primary feature, add tag/linkback for each one}"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -160,7 +162,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Install the packages\n",
|
||||
"! pip3 install --user --upgrade google-cloud-aiplatform"
|
||||
"! pip3 install --upgrade --quiet google-cloud-aiplatform"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -351,7 +353,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"BUCKET_URI = \"gs://your-bucket-name-unique\" # @param {type:\"string\"}"
|
||||
"BUCKET_URI = f\"gs://your-bucket-name-{PROJECT_ID}-unique\" # @param {type:\"string\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,62 @@
|
||||
- Incorrect examples: "Let's update the field", "We'll update the field", "The user should update the field"
|
||||
- **Googlers**: Please follow our [branding guidelines](http://goto/cloud-branding).
|
||||
|
||||
### Code
|
||||
|
||||
## Authoring guidelines
|
||||
|
||||
### Focus
|
||||
|
||||
Notebooks for official are expected to be narrow focused, which highlight a subset of features of a Vertex AI product/service.
|
||||
The product/feature is to be highlighted in the Overview section. For example:
|
||||
|
||||
```
|
||||
This tutorial demonstrates using Vertex AI Training to train an XGBoost model using a XGBoost pre-built training container.
|
||||
```
|
||||
|
||||
In the above example, the Vertex AI product/service is `Vertex AI Training` and the feature is `XGBoost pre-built training container`.
|
||||
|
||||
### Scope
|
||||
|
||||
Notebooks for official are expected to be narrow in scope, without extra extraneous steps. For example, if the notebook is about training, we discourage ending the notebook with deploying the model and doing an online/batch prediction. On the later, we recommend a separate notebook about prediction that uses a pretrained model.
|
||||
|
||||
#### Training
|
||||
|
||||
Notebooks for training should be constructed as follows:
|
||||
|
||||
1. If the training script(s) are small, embed them in the notebook and use %writefile to store them locally.
|
||||
2. If the training script(s) are large, store them in our public bucket: gs://cloud-samples-data/vertex-ai/dataset-management/script, and use !wgets to retrieve and store the script locally.
|
||||
3. Train the model using the Vertex AI SDK methods for custom training.
|
||||
4. Preferrable have the service upload the trained model to the Vertex AI Model Registry.
|
||||
4. Have the script do an evaluation.
|
||||
5. Retrieve the evaluation metrics and attach them as an artifact to the corresponding entry in the Model Registry.
|
||||
6. Optionally, download the model artifacts and test locally -- i.e., make a local prediction request.
|
||||
|
||||
#### Evaluation
|
||||
|
||||
Notebooks for evaluation should be constructed as follows:
|
||||
|
||||
1. Use a pretrained model from a public repository.
|
||||
2. Upload the pretrained model to the Vertex AI Model Registry.
|
||||
3. Perform a model evaluation.
|
||||
4. Review the model evaluation.
|
||||
4. Attach the model evaluation to the corresponding entry in the Model Registry.
|
||||
|
||||
#### Prediction
|
||||
|
||||
Notebooks for prediction should be constructed as follows:
|
||||
|
||||
1. Use a pretrained model from a public repository.
|
||||
2. If relevant, attach a serving function to the model artifacts.
|
||||
3. Upload the pretrained model to the Vertex AI Model Registry.
|
||||
4. For online:<br/>
|
||||
A. Deploy the model.<br/>
|
||||
B. Perform an online prediction.</br>
|
||||
C. Review the result.
|
||||
5. For batch:<br/>
|
||||
A. Perform a batch prediction.</br/>
|
||||
B. Review the result.
|
||||
|
||||
## Code
|
||||
|
||||
- Put all your installs and imports in a setup section.
|
||||
- Save the notebook with the Table of Contents open.
|
||||
@@ -31,7 +86,7 @@
|
||||
- Follow the [Google Python Style guide](https://github.com/google/styleguide/blob/gh-pages/pyguide.md) and write readable code.
|
||||
- Keep cells small (max ~20 lines).
|
||||
|
||||
## TensorFlow code style
|
||||
### TensorFlow code style
|
||||
|
||||
Use the highest level API that gets the job done (unless the goal is to demonstrate the low level API). For example, when using Tensorflow:
|
||||
|
||||
|
||||
@@ -29,15 +29,16 @@
|
||||
/pipelines/google_cloud_pipelines_dataproc_tabular @inardini
|
||||
/automl/automl_forecasting_bqml_arima_plus_comparison.ipynb @TheMichaelHu
|
||||
/automl/automl_tabular_on_vertex_pipelines.ipynb @helinwang
|
||||
/custom/custom_training_tensorboard_profiler.ipynb @itseric
|
||||
/custom/custom_training_tensorboard_profiler.ipynb @gericdong
|
||||
/custom/get_started_with_vertex_endpoint_and_shared_vm.ipynb @andrewferlitsch
|
||||
/workbench/spark/spark_sample_notebook.ipynb @bradmiro
|
||||
/workbench/spark/spark_ml.ipynb @bradmiro
|
||||
/model_registry/bqml_vertexai_model_registry.ipynb @soheilazangeneh
|
||||
/workbench/exploratory_data_analysis/explore_data_in_bigquery_with_workbench.ipynb @alokpattani
|
||||
/model_evaluation/automl_tabular_classification_model_evaluation.ipynb @soheilazangeneh
|
||||
/model_evaluation/automl_tabular_regression_model_evaluation.ipynb @soheilazangeneh
|
||||
/tabular_workflows/tabnet_on_vertex_pipelines.ipynb @sakagarwal
|
||||
/tabular_workflows/wide_and_deep_on_vertex_pipelines.ipynb @sakagarwal
|
||||
/tabular_workflows/prophet_on_vertex_pipelines.ipynb @TheMichaelHu
|
||||
/model_evaluation/custom_tabular_classification_model_evaluation.ipynb @soheilazangeneh
|
||||
/sdk/SDK_FBProphet_Forecasting_Online.ipynb @brianchunkang
|
||||
/automl/sdk_automl_forecasting_hierarchical_batch.ipynb @ivanmkc
|
||||
/pipelines/Train_tabular_models_with_many_frameworks_and_import_to_Vertex_AI_using_Pipelines @Ark-kun
|
||||
/experiments/get_started_with_vertex_experiments_autologging.ipynb @inardini
|
||||
/experiments/delete_outdated_tensorboard_experiments.ipynb @inardini
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user