Google Colaboratory、TensorFlowの使い方

Google Colaboratoryのチュートリアルをやりながら、
「ここが意味わからん」
とつまづいた部分のメモです。

きっと同じ個所でつまづく人もいるだろうと思い記録に残しておきます。

技術レベルとしては、
Python: わかる
機械学習: ぼんやりわかる
TensorFlow: 初心者
くらいの人を対象にしています。

import tensorflow as tf

TensorFlowを使うためのモジュールをインポート

import tensorflow_datasets as tfds

データセットモジュールのインポート
MNIST: 手書き数字の画像データ
IMDB: 映画の口コミデータ(英語)
などを簡単に利用できるようになります。

これらの基本データセットを使って、画像認識の練習や、ネガポジ分類器の作り方を練習します。
自分の持っているデータをもとにいきなり実践を始めると、どういう形式のデータを渡せばいいのか調べるのに苦労します。
tensorflow_datasetsを使ってチュートリアルをこなせば、
「こういうデータを渡せばああなってこうなって最終的にこういうデータが手に入るのね」
という感覚がつかめます。

datasets = tfds.load('imdb_reviews')

IMDBの映画レビューデータを読み込む

datasets, info = tfds.load('imdb_reviews', with_info=True)

with_info=True
のオプションを付けるとdatasetsの中身がどういう形式になっているか、print(info)で確認できるようになる。
datasetsの中身自体は、以下の2通りの書き方どちらでも変わらない。
datasets = tfds.load('imdb_reviews')
datasets, info = tfds.load('imdb_reviews', with_info=True)

print(info)の実行結果は以下の通り。

{'test': <DatasetV1Adapter shapes: {label: (), text: ()}, types: {label: tf.int64, text: tf.string}>, 'train': <DatasetV1Adapter shapes: {label: (), text: ()}, types: {label: tf.int64, text: tf.string}>, 'unsupervised': <DatasetV1Adapter shapes: {label: (), text: ()}, types: {label: tf.int64, text: tf.string}>}
tfds.core.DatasetInfo(
   name='imdb_reviews',
   version=1.0.0,
   description='Large Movie Review Dataset.
This is a dataset for binary sentiment classification containing substantially more data than previous benchmark datasets. We provide a set of 25,000 highly polar movie reviews for training, and 25,000 for testing. There is additional unlabeled data for use as well.',
   homepage='http://ai.stanford.edu/~amaas/data/sentiment/',
   features=FeaturesDict({
       'label': ClassLabel(shape=(), dtype=tf.int64, num_classes=2),
       'text': Text(shape=(), dtype=tf.string),
   }),
   total_num_examples=100000,
   splits={
       'test': 25000,
       'train': 25000,
       'unsupervised': 50000,
   },
   supervised_keys=('text', 'label'),
   citation="""@InProceedings{maas-EtAl:2011:ACL-HLT2011,
     author    = {Maas, Andrew L.  and  Daly, Raymond E.  and  Pham, Peter T.  and  Huang, Dan  and  Ng, Andrew Y.  and  Potts, Christopher},
     title     = {Learning Word Vectors for Sentiment Analysis},
     booktitle = {Proceedings of the 49th Annual Meeting of the Association for Computational Linguistics: Human Language Technologies},
     month     = {June},
     year      = {2011},
     address   = {Portland, Oregon, USA},
     publisher = {Association for Computational Linguistics},
     pages     = {142--150},
     url       = {http://www.aclweb.org/anthology/P11-1015}
   }""",
   redistribution_info=,
)

datasetsの中身を確認していきましょう。

type(datasets)

上記を実行すると

dict

datasetsは辞書型であることが分かります。

datasets.keys()

上記を実行すると

dict_keys(['test', 'train', 'unsupervised'])

datasetsにはtest、train、unsupervisedの3種類のデータがあることがわかります。

trainは訓練用データ、映画のレビューが書かれた英文+ラベル
ラベルは0がネガティブ、1がポジティブの2値

testは評価用データ、映画のレビューが書かれた英文+ラベル

unsupervisedはラベルがない、映画のレビューが書かれた英文のみのデータ
チュートリアルではたぶん使いません。

train_data = datasets['train']

トレーニング用のデータだけ取り出します。

batches = train_data.batch(100)

.batch()
でトレーニングデータをミニバッチに分けます。
imdb_reviewsのデータセットの場合、トレーニングデータが25000件あります。
1回1回の学習(重みを更新)に25000件のすべてを使うと学習にめちゃめちゃ時間がかかります。
そのため、100件だけ取り出して1回学習、次の100件を取り出して1回学習、……のようにデータを区切って学習させます。
その時に使うのが
.batch()

.batch(10)なら10件ずつデータを区切る、
.batch(100)なら100件ずつデータを区切る、
何件ずつ区切るのが妥当かは場合によります。
場合によるとはいいつつも、1件ずつ区切るのは単位が小さすぎるし、1000件ずつ区切るのはたぶん単位が大きすぎる。

batches = train_data.batch(5).take(2)

for batch in batches :
   print(batch)

.batch(5)
により、25000件のデータを5個ずつに区切ります。
5個ずつの塊が5000ブロックできあがります。

.take(2)
5個ずつの塊が5000ブロックできあがっているので、そこら先頭の2ブロックだけ取り出します。

for batch in batches :
    print(batch)
5個ワンセットのミニバッチを取り出して表示。
train_dataの中身がどうなっているのかを確認しましょう。
printの結果は以下の通りです。

{'label': <tf.Tensor: shape=(5,), dtype=int64, numpy=array([0, 0, 0, 1, 1])>, 'text': <tf.Tensor: shape=(5,), dtype=string, numpy=
array([b"This was an absolutely terrible movie. Don't be lured in by Christopher Walken or Michael Ironside. Both are great actors, but this must simply be their worst role in history. Even their great acting could not redeem this movie's ridiculous storyline. This movie is an early nineties US propaganda piece. The most pathetic scenes were those when the Columbian rebels were making their cases for revolutions. Maria Conchita Alonso appeared phony, and her pseudo-love affair with Walken was nothing but a pathetic emotional plug in a movie that was devoid of any real meaning. I am disappointed that there are movies like this, ruining actor's like Christopher Walken's good name. I could barely sit through it.",
      b'I have been known to fall asleep during films, but this is usually due to a combination of things including, really tired, being warm and comfortable on the sette and having just eaten a lot. However on this occasion I fell asleep because the film was rubbish. The plot development was constant. Constantly slow and boring. Things seemed to happen, but with no explanation of what was causing them or why. I admit, I may have missed part of the film, but i watched the majority of it and everything just seemed to happen of its own accord without any real concern for anything else. I cant recommend this film at all.',
      b'Mann photographs the Alberta Rocky Mountains in a superb fashion, and Jimmy Stewart and Walter Brennan give enjoyable performances as they always seem to do. <br /><br />But come on Hollywood - a Mountie telling the people of Dawson City, Yukon to elect themselves a marshal (yes a marshal!) and to enforce the law themselves, then gunfighters battling it out on the streets for control of the town? <br /><br />Nothing even remotely resembling that happened on the Canadian side of the border during the Klondike gold rush. Mr. Mann and company appear to have mistaken Dawson City for Deadwood, the Canadian North for the American Wild West.<br /><br />Canadian viewers be prepared for a Reefer Madness type of enjoyable howl with this ludicrous plot, or, to shake your head in disgust.',
      b'This is the kind of film for a snowy Sunday afternoon when the rest of the world can go ahead with its own business as you descend into a big arm-chair and mellow for a couple of hours. Wonderful performances from Cher and Nicolas Cage (as always) gently row the plot along. There are no rapids to cross, no dangerous waters, just a warm and witty paddle through New York life at its best. A family film in every sense and one that deserves the praise it received.',
      b'As others have mentioned, all the women that go nude in this film are mostly absolutely gorgeous. The plot very ably shows the hypocrisy of the female libido. When men are around they want to be pursued, but when no "men" are around, they become the pursuers of a 14 year old boy. And the boy becomes a man really fast (we should all be so lucky at this age!). He then gets up the courage to pursue his true love.'],
     dtype=object)>}
{'label': <tf.Tensor: shape=(5,), dtype=int64, numpy=array([1, 0, 0, 0, 0])>, 'text': <tf.Tensor: shape=(5,), dtype=string, numpy=
array([b"This is a film which should be seen by anybody interested in, effected by, or suffering from an eating disorder. It is an amazingly accurate and sensitive portrayal of bulimia in a teenage girl, its causes and its symptoms. The girl is played by one of the most brilliant young actresses working in cinema today, Alison Lohman, who was later so spectacular in 'Where the Truth Lies'. I would recommend that this film be shown in all schools, as you will never see a better on this subject. Alison Lohman is absolutely outstanding, and one marvels at her ability to convey the anguish of a girl suffering from this compulsive disorder. If barometers tell us the air pressure, Alison Lohman tells us the emotional pressure with the same degree of accuracy. Her emotional range is so precise, each scene could be measured microscopically for its gradations of trauma, on a scale of rising hysteria and desperation which reaches unbearable intensity. Mare Winningham is the perfect choice to play her mother, and does so with immense sympathy and a range of emotions just as finely tuned as Lohman's. Together, they make a pair of sensitive emotional oscillators vibrating in resonance with one another. This film is really an astonishing achievement, and director Katt Shea should be proud of it. The only reason for not seeing it is if you are not interested in people. But even if you like nature films best, this is after all animal behaviour at the sharp edge. Bulimia is an extreme version of how a tormented soul can destroy her own body in a frenzy of despair. And if we don't sympathise with people suffering from the depths of despair, then we are dead inside.",
      b'Okay, you have:<br /><br />Penelope Keith as Miss Herringbone-Tweed, B.B.E. (Backbone of England.) She\'s killed off in the first scene - that\'s right, folks; this show has no backbone!<br /><br />Peter O\'Toole as Ol\' Colonel Cricket from The First War and now the emblazered Lord of the Manor.<br /><br />Joanna Lumley as the ensweatered Lady of the Manor, 20 years younger than the colonel and 20 years past her own prime but still glamourous (Brit spelling, not mine) enough to have a toy-boy on the side. It\'s alright, they have Col. Cricket\'s full knowledge and consent (they guy even comes \'round for Christmas!) Still, she\'s considerate of the colonel enough to have said toy-boy her own age (what a gal!)<br /><br />David McCallum as said toy-boy, equally as pointlessly glamourous as his squeeze. Pilcher couldn\'t come up with any cover for him within the story, so she gave him a hush-hush job at the Circus.<br /><br />and finally:<br /><br />Susan Hampshire as Miss Polonia Teacups, Venerable Headmistress of the Venerable Girls\' Boarding-School, serving tea in her office with a dash of deep, poignant advice for life in the outside world just before graduation. Her best bit of advice: "I\'ve only been to Nancherrow (the local Stately Home of England) once. I thought it was very beautiful but, somehow, not part of the real world." Well, we can\'t say they didn\'t warn us.<br /><br />Ah, Susan - time was, your character would have been running the whole show. They don\'t write \'em like that any more. Our loss, not yours.<br /><br />So - with a cast and setting like this, you have the re-makings of "Brideshead Revisited," right?<br /><br />Wrong! They took these 1-dimensional supporting roles because they paid so well. After all, acting is one of the oldest temp-jobs there is (YOU name another!)<br /><br />First warning sign: lots and lots of backlighting. They get around it by shooting outdoors - "hey, it\'s just the sunlight!"<br /><br />Second warning sign: Leading Lady cries a lot. When not crying, her eyes are moist. That\'s the law of romance novels: Leading Lady is "dewy-eyed."<br /><br />Henceforth, Leading Lady shall be known as L.L.<br /><br />Third warning sign: L.L. actually has stars in her eyes when she\'s in love. Still, I\'ll give Emily Mortimer an award just for having to act with that spotlight in her eyes (I wonder . did they use contacts?)<br /><br />And lastly, fourth warning sign: no on-screen female character is "Mrs." She\'s either "Miss" or "Lady."<br /><br />When all was said and done, I still couldn\'t tell you who was pursuing whom and why. I couldn\'t even tell you what was said and done.<br /><br />To sum up: they all live through World War II without anything happening to them at all.<br /><br />OK, at the end, L.L. finds she\'s lost her parents to the Japanese prison camps and baby sis comes home catatonic. Meanwhile (there\'s always a "meanwhile,") some young guy L.L. had a crush on (when, I don\'t know) comes home from some wartime tough spot and is found living on the street by Lady of the Manor (must be some street if SHE\'s going to find him there.) Both war casualties are whisked away to recover at Nancherrow (SOMEBODY has to be "whisked away" SOMEWHERE in these romance stories!)<br /><br />Great drama.',
      b'The film is based on a genuine 1950s novel.<br /><br />Journalist Colin McInnes wrote a set of three "London novels": "Absolute Beginners", "City of Spades" and "Mr Love and Justice". I have read all three. The first two are excellent. The last, perhaps an experiment that did not come off. But McInnes\'s work is highly acclaimed; and rightly so. This musical is the novelist\'s ultimate nightmare - to see the fruits of one\'s mind being turned into a glitzy, badly-acted, soporific one-dimensional apology of a film that says it captures the spirit of 1950s London, and does nothing of the sort.<br /><br />Thank goodness Colin McInnes wasn\'t alive to witness it.',
      b'I really love the sexy action and sci-fi films of the sixties and its because of the actress\'s that appeared in them. They found the sexiest women to be in these films and it didn\'t matter if they could act (Remember "Candy"?). The reason I was disappointed by this film was because it wasn\'t nostalgic enough. The story here has a European sci-fi film called "Dragonfly" being made and the director is fired. So the producers decide to let a young aspiring filmmaker (Jeremy Davies) to complete the picture. They\'re is one real beautiful woman in the film who plays Dragonfly but she\'s barely in it. Film is written and directed by Roman Coppola who uses some of his fathers exploits from his early days and puts it into the script. I wish the film could have been an homage to those early films. They could have lots of cameos by actors who appeared in them. There is one actor in this film who was popular from the sixties and its John Phillip Law (Barbarella). Gerard Depardieu, Giancarlo Giannini and Dean Stockwell appear as well. I guess I\'m going to have to continue waiting for a director to make a good homage to the films of the sixties. If any are reading this, "Make it as sexy as you can"! I\'ll be waiting!',
      b'Sure, this one isn\'t really a blockbuster, nor does it target such a position. "Dieter" is the first name of a quite popular German musician, who is either loved or hated for his kind of acting and thats exactly what this movie is about. It is based on the autobiography "Dieter Bohlen" wrote a few years ago but isn\'t meant to be accurate on that. The movie is filled with some sexual offensive content (at least for American standard) which is either amusing (not for the other "actors" of course) or dumb - it depends on your individual kind of humor or on you being a "Bohlen"-Fan or not. Technically speaking there isn\'t much to criticize. Speaking of me I find this movie to be an OK-movie.'],
     dtype=object)>}

1個のミニバッチの中身は辞書になっていて
'label': <tf.Tensor: shape=(5,), dtype=int64, numpy=array([0, 0, 0, 1, 1])>
'text': <tf.Tensor: shape=(5,), dtype=string, numpy=
array([b"This was an absolutely terrible movie. Don't be lured ……
のように、labelとtextの2つの要素があります。
labelの中身は[0, 0, 0, 1, 1]のような長さ5のarrayです。arrayの中身は0か1かの数値。
textの中身も長さ5のarrayです。arrayの中身はテキストデータです。

datasets, info = tfds.load('imdb_reviews', with_info=True, as_supervised=True)

train_data = datasets['train']
batches = train_data.batch(5).take(2)

for batch in batches:
   print(batch)

tfds.loadのときにas_supervised=True
というオプションをつけるとtrain_dataの中身が辞書ではなくタプルになります。
print(batch)の結果は以下の通り。

(<tf.Tensor: shape=(5,), dtype=string, numpy=
array([b"This was an absolutely terrible movie. Don't be lured in by Christopher Walken or Michael Ironside. Both are great actors, but this must simply be their worst role in history. Even their great acting could not redeem this movie's ridiculous storyline. This movie is an early nineties US propaganda piece. The most pathetic scenes were those when the Columbian rebels were making their cases for revolutions. Maria Conchita Alonso appeared phony, and her pseudo-love affair with Walken was nothing but a pathetic emotional plug in a movie that was devoid of any real meaning. I am disappointed that there are movies like this, ruining actor's like Christopher Walken's good name. I could barely sit through it.",
      b'I have been known to fall asleep during films, but this is usually due to a combination of things including, really tired, being warm and comfortable on the sette and having just eaten a lot. However on this occasion I fell asleep because the film was rubbish. The plot development was constant. Constantly slow and boring. Things seemed to happen, but with no explanation of what was causing them or why. I admit, I may have missed part of the film, but i watched the majority of it and everything just seemed to happen of its own accord without any real concern for anything else. I cant recommend this film at all.',
      b'Mann photographs the Alberta Rocky Mountains in a superb fashion, and Jimmy Stewart and Walter Brennan give enjoyable performances as they always seem to do. <br /><br />But come on Hollywood - a Mountie telling the people of Dawson City, Yukon to elect themselves a marshal (yes a marshal!) and to enforce the law themselves, then gunfighters battling it out on the streets for control of the town? <br /><br />Nothing even remotely resembling that happened on the Canadian side of the border during the Klondike gold rush. Mr. Mann and company appear to have mistaken Dawson City for Deadwood, the Canadian North for the American Wild West.<br /><br />Canadian viewers be prepared for a Reefer Madness type of enjoyable howl with this ludicrous plot, or, to shake your head in disgust.',
      b'This is the kind of film for a snowy Sunday afternoon when the rest of the world can go ahead with its own business as you descend into a big arm-chair and mellow for a couple of hours. Wonderful performances from Cher and Nicolas Cage (as always) gently row the plot along. There are no rapids to cross, no dangerous waters, just a warm and witty paddle through New York life at its best. A family film in every sense and one that deserves the praise it received.',
      b'As others have mentioned, all the women that go nude in this film are mostly absolutely gorgeous. The plot very ably shows the hypocrisy of the female libido. When men are around they want to be pursued, but when no "men" are around, they become the pursuers of a 14 year old boy. And the boy becomes a man really fast (we should all be so lucky at this age!). He then gets up the courage to pursue his true love.'],
     dtype=object)>, <tf.Tensor: shape=(5,), dtype=int64, numpy=array([0, 0, 0, 1, 1])>)
(<tf.Tensor: shape=(5,), dtype=string, numpy=
array([b"This is a film which should be seen by anybody interested in, effected by, or suffering from an eating disorder. It is an amazingly accurate and sensitive portrayal of bulimia in a teenage girl, its causes and its symptoms. The girl is played by one of the most brilliant young actresses working in cinema today, Alison Lohman, who was later so spectacular in 'Where the Truth Lies'. I would recommend that this film be shown in all schools, as you will never see a better on this subject. Alison Lohman is absolutely outstanding, and one marvels at her ability to convey the anguish of a girl suffering from this compulsive disorder. If barometers tell us the air pressure, Alison Lohman tells us the emotional pressure with the same degree of accuracy. Her emotional range is so precise, each scene could be measured microscopically for its gradations of trauma, on a scale of rising hysteria and desperation which reaches unbearable intensity. Mare Winningham is the perfect choice to play her mother, and does so with immense sympathy and a range of emotions just as finely tuned as Lohman's. Together, they make a pair of sensitive emotional oscillators vibrating in resonance with one another. This film is really an astonishing achievement, and director Katt Shea should be proud of it. The only reason for not seeing it is if you are not interested in people. But even if you like nature films best, this is after all animal behaviour at the sharp edge. Bulimia is an extreme version of how a tormented soul can destroy her own body in a frenzy of despair. And if we don't sympathise with people suffering from the depths of despair, then we are dead inside.",
      b'Okay, you have:<br /><br />Penelope Keith as Miss Herringbone-Tweed, B.B.E. (Backbone of England.) She\'s killed off in the first scene - that\'s right, folks; this show has no backbone!<br /><br />Peter O\'Toole as Ol\' Colonel Cricket from The First War and now the emblazered Lord of the Manor.<br /><br />Joanna Lumley as the ensweatered Lady of the Manor, 20 years younger than the colonel and 20 years past her own prime but still glamourous (Brit spelling, not mine) enough to have a toy-boy on the side. It\'s alright, they have Col. Cricket\'s full knowledge and consent (they guy even comes \'round for Christmas!) Still, she\'s considerate of the colonel enough to have said toy-boy her own age (what a gal!)<br /><br />David McCallum as said toy-boy, equally as pointlessly glamourous as his squeeze. Pilcher couldn\'t come up with any cover for him within the story, so she gave him a hush-hush job at the Circus.<br /><br />and finally:<br /><br />Susan Hampshire as Miss Polonia Teacups, Venerable Headmistress of the Venerable Girls\' Boarding-School, serving tea in her office with a dash of deep, poignant advice for life in the outside world just before graduation. Her best bit of advice: "I\'ve only been to Nancherrow (the local Stately Home of England) once. I thought it was very beautiful but, somehow, not part of the real world." Well, we can\'t say they didn\'t warn us.<br /><br />Ah, Susan - time was, your character would have been running the whole show. They don\'t write \'em like that any more. Our loss, not yours.<br /><br />So - with a cast and setting like this, you have the re-makings of "Brideshead Revisited," right?<br /><br />Wrong! They took these 1-dimensional supporting roles because they paid so well. After all, acting is one of the oldest temp-jobs there is (YOU name another!)<br /><br />First warning sign: lots and lots of backlighting. They get around it by shooting outdoors - "hey, it\'s just the sunlight!"<br /><br />Second warning sign: Leading Lady cries a lot. When not crying, her eyes are moist. That\'s the law of romance novels: Leading Lady is "dewy-eyed."<br /><br />Henceforth, Leading Lady shall be known as L.L.<br /><br />Third warning sign: L.L. actually has stars in her eyes when she\'s in love. Still, I\'ll give Emily Mortimer an award just for having to act with that spotlight in her eyes (I wonder . did they use contacts?)<br /><br />And lastly, fourth warning sign: no on-screen female character is "Mrs." She\'s either "Miss" or "Lady."<br /><br />When all was said and done, I still couldn\'t tell you who was pursuing whom and why. I couldn\'t even tell you what was said and done.<br /><br />To sum up: they all live through World War II without anything happening to them at all.<br /><br />OK, at the end, L.L. finds she\'s lost her parents to the Japanese prison camps and baby sis comes home catatonic. Meanwhile (there\'s always a "meanwhile,") some young guy L.L. had a crush on (when, I don\'t know) comes home from some wartime tough spot and is found living on the street by Lady of the Manor (must be some street if SHE\'s going to find him there.) Both war casualties are whisked away to recover at Nancherrow (SOMEBODY has to be "whisked away" SOMEWHERE in these romance stories!)<br /><br />Great drama.',
      b'The film is based on a genuine 1950s novel.<br /><br />Journalist Colin McInnes wrote a set of three "London novels": "Absolute Beginners", "City of Spades" and "Mr Love and Justice". I have read all three. The first two are excellent. The last, perhaps an experiment that did not come off. But McInnes\'s work is highly acclaimed; and rightly so. This musical is the novelist\'s ultimate nightmare - to see the fruits of one\'s mind being turned into a glitzy, badly-acted, soporific one-dimensional apology of a film that says it captures the spirit of 1950s London, and does nothing of the sort.<br /><br />Thank goodness Colin McInnes wasn\'t alive to witness it.',
      b'I really love the sexy action and sci-fi films of the sixties and its because of the actress\'s that appeared in them. They found the sexiest women to be in these films and it didn\'t matter if they could act (Remember "Candy"?). The reason I was disappointed by this film was because it wasn\'t nostalgic enough. The story here has a European sci-fi film called "Dragonfly" being made and the director is fired. So the producers decide to let a young aspiring filmmaker (Jeremy Davies) to complete the picture. They\'re is one real beautiful woman in the film who plays Dragonfly but she\'s barely in it. Film is written and directed by Roman Coppola who uses some of his fathers exploits from his early days and puts it into the script. I wish the film could have been an homage to those early films. They could have lots of cameos by actors who appeared in them. There is one actor in this film who was popular from the sixties and its John Phillip Law (Barbarella). Gerard Depardieu, Giancarlo Giannini and Dean Stockwell appear as well. I guess I\'m going to have to continue waiting for a director to make a good homage to the films of the sixties. If any are reading this, "Make it as sexy as you can"! I\'ll be waiting!',
      b'Sure, this one isn\'t really a blockbuster, nor does it target such a position. "Dieter" is the first name of a quite popular German musician, who is either loved or hated for his kind of acting and thats exactly what this movie is about. It is based on the autobiography "Dieter Bohlen" wrote a few years ago but isn\'t meant to be accurate on that. The movie is filled with some sexual offensive content (at least for American standard) which is either amusing (not for the other "actors" of course) or dumb - it depends on your individual kind of humor or on you being a "Bohlen"-Fan or not. Technically speaking there isn\'t much to criticize. Speaking of me I find this movie to be an OK-movie.'],
     dtype=object)>, <tf.Tensor: shape=(5,), dtype=int64, numpy=array([1, 0, 0, 0, 0])>)

'label': <tf.Tensor: shape=(5,), dtype=int64, numpy=array([0, 0, 0, 1, 1])>
'text': <tf.Tensor: shape=(5,), dtype=string, numpy=
となっていた部分が
<tf.Tensor: shape=(5,), dtype=string, numpy=array([b"This was an absolutely terrible movie. Don't be lured ……
<tf.Tensor: shape=(5,), dtype=int64, numpy=array([0, 0, 0, 1, 1])>
という感じに変わりました。
('label': や 'text':の部分がなくなりました。)

datasets, info = tfds.load('imdb_reviews/subwords32k', with_info=True, as_supervised=True)

前回まで
tfds.load('imdb_reviews')
としていた部分を、以下のように変更
tfds.load('imdb_reviews/subwords32k')
/subwords32kというのを追加しました。

batches = train_data.batch(5).take(2)

for batch in batches:
   print(batch)

loadの対象をimdb_reviews/subwords32kにした結果、データの中身はどうなったのかを確認しましょう。

---------------------------------------------------------------------------
InvalidArgumentError                      Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/context.py in execution_mode(mode)
  1985       ctx.executor = executor_new
-> 1986       yield
  1987     finally:

10 frames
InvalidArgumentError: Cannot batch tensors with different shapes in component 0. First element had shape [143] and element 1 had shape [129]. [Op:IteratorGetNext]

During handling of the above exception, another exception occurred:

InvalidArgumentError                      Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/executor.py in wait(self)
    65   def wait(self):
    66     """Waits for ops dispatched in this executor to finish."""
---> 67     pywrap_tfe.TFE_ExecutorWaitForAllPendingNodes(self._handle)
    68 
    69   def clear_error(self):

InvalidArgumentError: Cannot batch tensors with different shapes in component 0. First element had shape [143] and element 1 had shape [129].

なんと上記のようなエラーになりました。

InvalidArgumentError: Cannot batch tensors with different shapes in component 0. First element had shape [143] and element 1 had shape [129].
というエラーになりました。
different shapesなので、データの長さが不揃いだから何とかしろと怒られていますね。
different shapesの意味を説明する前に、以下を試しましょう。

batches = train_data.batch(1).take(2)

for batch in batches:
   print(batch)

実行結果は以下の通り。

(<tf.Tensor: shape=(1, 143), dtype=int64, numpy=
array([[   56,    18,    41,   496,   674,    59,     3,   574, 32433,
          25,    34, 21905,    10,    39,  1626,  8210,    49,   548,
       17768,     3,  1730,    29,   112,   520,     2,    24,    14,
         256,   382,    34,    72,   312,   335,    10,  1216,     3,
         422,    72,   112,   170,   106,    33,  8157,    14,    59,
       32433,    11,  1133,  1964,     3,    56,    27,     8,    41,
         476, 15843, 32426,  1504,  4185,  2692,     3,    19,    96,
        2143,   199,    77,   178,    66,     1, 27162,   381, 15791,
          77,   281,    72,  5479,    22,  5693, 32509,     3,  4147,
       24625, 11296, 24690,    50,  1849, 27610,     2,     5,    54,
        4184, 32439,   157,  2520,    21,  8210,    18,   223,    24,
           4,  2143,  1041, 14185,    10,     4,    27,    13,    18,
        5414,     6,   111,   188,  4811,     3,    12,   274,  1357,
          13,    84,    29,   154,    46,   204,     2, 11717,   758,
       32433,    11,    46,  1626,  8003, 32433,    11,    68,  1417,
           3,    12,   106,  1403,   951,   175,    37, 32440]])>, <tf.Tensor: shape=(1,), dtype=int64, numpy=array([0])>)
(<tf.Tensor: shape=(1, 129), dtype=int64, numpy=
array([[   12,    31,    85,   662,     7,   897,  4048,   370,   324,
           2,    24,    14,     8,   755,   776,     7,     4,  2794,
           6,   252, 10868,     2,    75, 10038,     2,   124,  3469,
           5,  5585,    26,     1, 17952,   183,     5,   327,    52,
        8969,     4,  1536,     3,  1986,    26,    14, 10628,    12,
        1830,  4048,    92,     1,    32,    18,  3943,     3,    19,
         167,  1714,    18, 17573,  2446,     3, 28626, 12923,   912,
           5,   816,     3,  3448,   504,     7,  1693,     2,    24,
          21,    78,  2906,     6,    65,    18,  5362,   146,    49,
        1340,     3,    12,  5010,     2,    12,   240,    31,  1460,
         241,     6,     1,    61,     2,    24,   135,   349,     1,
        2542,     6,    15,     5,   409,    52,   504,     7,   967,
           6,   108,   260, 14305,  5249,   248,   111,   188,  7145,
          22,   300,   880,     3,    12,  3078,   429,    14,    32,
          40,   203, 32440]])>, <tf.Tensor: shape=(1,), dtype=int64, numpy=array([0])>)

1つ目の文章は
This was an absolutely terrible movie. Don't be lured in by Christopher
となっていましたが、
Thisが56、wasが18、anが41みたいな数字に変換されています。

これが
tfds.load('imdb_reviews')

tfds.load('imdb_reviews/subwords32k')
の違いです。

機械学習をするときは、モデルに与えるデータは数値に変換しておく必要があります。
そのため、thisは1、thatは2、itなら3……みたいな単語と数値の対応表を自分で作る必要があります。
tfds.load('imdb_reviews/subwords32k')を読み込むと、その面倒な作業が終わった状態のデータを利用できます。
便利!

tfds.load('imdb_reviews/subwords32k')
のやってくれること

1.単語と数字の変換表が既に作られている
2.変換表にもとづいてテキストを数字に置き換えておいてくれる

encoder = info.features['text'].encoder

encoderを使って単語と数字の変換表を再利用できます。

print(encoder.vocab_size)

print(encoder.vocab_size)の実行結果は32650です。
単語と数字の変換表に32650の単語があります。

for i in range(10):
   print(i, encoder.decode([i]))

上記を実行すると下記のような結果になります。

0 
1 the 
2 , 
3 . 
4 a 
5 and 
6 of 
7 to 
8 is 
9 br

空文字は0番、theは1番、カンマは2番……のように置き換えられるようです。

encoder.decode([56, 18, 41, 496, 674, 59, 3])

上記を実行すると下記のようなテキストが得られます。

This was an absolutely terrible movie. 

また、逆に下記を実行すると

encoder.encode('This was an absolutely terrible movie. ')

次のような数値の配列が得られます。

[56, 18, 41, 496, 674, 59, 3]

encoder.encode()
でテキストから数値への変換
encoder.decode()
で数値からテキストへの変換です。

さて、
tfds.load('imdb_reviews/subwords32k')
と、encode、decodeの意味が分かったところで、
InvalidArgumentError: Cannot batch tensors with different shapes in component 0. First element had shape [143] and element 1 had shape [129].というエラーの話に戻ります。

batches = train_data.batch(5).take(2)

for batch in batches:
   print(batch)

上記を実行した時に出たエラーでした。

batches = train_data.batch(1).take(2)

for batch in batches:
   print(batch)

上記のように.batch(1)に変更したらエラーが出ませんでした。

1つ目のデータには以下のような数値のリストが入っていました。
[ 56, 18, 41, 496, 674, 59, 3, 574, 32433,……]
この数字は143個あります。

そして、2つ目のデータには以下のようなデータが入っていました。
[12, 31, 85, 662, 7, 897, 4048, 370, 324,……]
この数字は129個あります。

機械学習するときには入力データの長さをそろえないとダメなんですよ。
143個と129個だとデータ長が違うのでエラーになったわけです。

データ長が違うときにどうするかっていうと、ゼロパディングをします。
2つ目のデータの末尾に、[12, 31, 85, 662, 7, 897, 4048, 370, 324,……,0,0,0,0]
みたいに0を追加してやります。
0を14個足してやれば129→143になって1つ目のデータと2つ目のデータで長さが一致します。
3つ目以降のデータにも長さを合わせるためには、全データの中で一番長い奴を調べて、それに合わせてゼロパディングをすればOK。

batches = train_data.padded_batch(5).take(2)

.batch()
の代わりに
.padded_batch()
を使いましょう。
データ数が一番多いものに合わせて末尾にゼロパディングをしてくれます。

for batch in batches:
   print(batch)
   print()

ゼロパディングで長さをそろえたので
上記を実行してもエラーが出なくなります。
実行結果は以下の通り。

(<tf.Tensor: shape=(5, 171), dtype=int64, numpy=
array([[   56,    18,    41,   496,   674,    59,     3,   574, 32433,
          25,    34, 21905,    10,    39,  1626,  8210,    49,   548,
       17768,     3,  1730,    29,   112,   520,     2,    24,    14,
         256,   382,    34,    72,   312,   335,    10,  1216,     3,
         422,    72,   112,   170,   106,    33,  8157,    14,    59,
       32433,    11,  1133,  1964,     3,    56,    27,     8,    41,
         476, 15843, 32426,  1504,  4185,  2692,     3,    19,    96,
        2143,   199,    77,   178,    66,     1, 27162,   381, 15791,
          77,   281,    72,  5479,    22,  5693, 32509,     3,  4147,
       24625, 11296, 24690,    50,  1849, 27610,     2,     5,    54,
        4184, 32439,   157,  2520,    21,  8210,    18,   223,    24,
           4,  2143,  1041, 14185,    10,     4,    27,    13,    18,
        5414,     6,   111,   188,  4811,     3,    12,   274,  1357,
          13,    84,    29,   154,    46,   204,     2, 11717,   758,
       32433,    11,    46,  1626,  8003, 32433,    11,    68,  1417,
           3,    12,   106,  1403,   951,   175,    37, 32440,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0],
      [   12,    31,    85,   662,     7,   897,  4048,   370,   324,
           2,    24,    14,     8,   755,   776,     7,     4,  2794,
           6,   252, 10868,     2,    75, 10038,     2,   124,  3469,
           5,  5585,    26,     1, 17952,   183,     5,   327,    52,
        8969,     4,  1536,     3,  1986,    26,    14, 10628,    12,
        1830,  4048,    92,     1,    32,    18,  3943,     3,    19,
         167,  1714,    18, 17573,  2446,     3, 28626, 12923,   912,
           5,   816,     3,  3448,   504,     7,  1693,     2,    24,
          21,    78,  2906,     6,    65,    18,  5362,   146,    49,
        1340,     3,    12,  5010,     2,    12,   240,    31,  1460,
         241,     6,     1,    61,     2,    24,   135,   349,     1,
        2542,     6,    15,     5,   409,    52,   504,     7,   967,
           6,   108,   260, 14305,  5249,   248,   111,   188,  7145,
          22,   300,   880,     3,    12,  3078,   429,    14,    32,
          40,   203, 32440,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0],
      [ 8352, 12617,     1,  5191,     4, 12768, 11631,    11,    10,
           4,  1387,  2991,     2,     5,  2465,  2132,     5,  2842,
       14392, 32426,   235,  1121,   555,    20,    47,   255,   334,
           7,   566,   197,     9,    16,     9,    17,   115,   267,
          26,  1337,    90,     4, 16559,  1335,  1184,     1,   110,
           6,  8883,  2784,     2, 18963,    26,     7, 18173, 32426,
         866,     4, 17450,   993,    28,  3082,     4, 17450,   993,
        1204,     5,     7, 14606, 32426,     1,  2491,  1450,     2,
         129, 17498,  1259, 13635,    15,    57,    26,     1,  3774,
          22,  1715,     6,     1,  1464,  2187,     9,    16,     9,
          17,  1735,    73,  3121, 11490,    13,   888,    26,     1,
        2939,   736,     6,     1,  6675,   370,     1, 24526,  6566,
        9572,   183,  3742,  8656, 32498,     3,   589,     3,  8352,
           5,  1985,  1123,     7,    31,  8171,  8883,  2367,    22,
        2387,  4391,     2,     1,  2939,  3976,    22,     1,   360,
        4866,  3495,    23,     9,    16,     9,    17,  2939,  1195,
          34,  3594,    22,     4, 11156, 11558, 24500, 32426,   661,
           6,  1121, 20219, 32426,    21,    14,  5830,   377,     2,
         642,     2,     7,  6956,   142,   591,    10, 14258, 32440],
      [   56,     8,     1,   286,     6,    32,    22,     4, 28969,
        4199,  5715,    66,     1,   416,     6,     1,   341,    76,
         172,  2320,    21,   108,   260,  1613,    20,    35, 22095,
       32426,    86,     4,   275,  5783, 32439,  5929,     5, 14969,
        9551,    22,     4,   445,     6,  2266,     3,  7079,   555,
          44, 12502,     5,  8014,  5871,    28,    20,  2589,    55,
       18134,  6151,     1,   167,  2464,     3,   156,    29,    78,
       16283,    11,     7,  3955,     2,    78,  2678, 20740,     2,
          52,     4,  3469,     5,  3538, 18026,  1185,   175,   558,
        1198,   196,    40,   108,   670,     3,   122,   332,    32,
          10,   216,   406,     5,    42,    13,  1249,     1,  4471,
          15, 15365, 32440,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0],
      [  224,   675,    31,  3527,     2,    45,     1,   562,    13,
         172,  3577,    10,    14,    32,    29,   783,   496,  6224,
           3,    19,   167,    60,  3533,   366,     1, 22946, 32426,
           6,     1,   779, 31092,     3,   296,   517,    29,   245,
          47,   212,     7,    34, 27560, 32494,     2,    24,    66,
         851,    36,  1134,    48,    29,  1122,     2,    47,   452,
           1, 27560,  1468,     6,     4,  4009,   472,   202,  1207,
           3,   119,     1,   682,   501,     4,   190,    75,  1700,
          28,    97,   162,    45,    34,    50,  3122,    40,    14,
        1264,  2672,   164,   129,   243,    70,     1,  4824,     7,
       10066,    30,   401,   648, 32440,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0,
           0,     0,     0,     0,     0,     0,     0,     0,     0]])>, <tf.Tensor: shape=(5,), dtype=int64, numpy=array([0, 0, 0, 1, 1])>)

(<tf.Tensor: shape=(5, 865), dtype=int64, numpy=
array([[   56,     8,     4, ...,     0,     0,     0],
      [ 2442,     2,    35, ...,  1208,  1090, 32440],
      [   19,    32,     8, ...,     0,     0,     0],
      [   12,    75,   157, ...,     0,     0,     0],
      [ 2202,     2,    14, ...,     0,     0,     0]])>, <tf.Tensor: shape=(5,), dtype=int64, numpy=array([1, 0, 0, 0, 0])>)

1つ目のバッチでは、shape=(5, 171)になっていますね。
1つ目のバッチの3番目のデータが171個の数字で構成されています。
1,2,4,5個目のデータはこれに合わせて末尾に0が追加されてデータ長が171で統一されました。

また、2つ目のバッチは、shape=(5, 865)となっています。
バッチの中で長さが揃っていれば、1つ目のバッチと2つ目のバッチで長さが不揃いでもOKみたいですね。

# batches = train_data.padded_batch(5).take(2)
# for batch in batches:
#    print(batch)
#    print()

# batches = train_data.padded_batch(5)
# for batch in batches.take(1):
#    print(batch)
#    print()
   
batches = train_data.padded_batch(5)
for texts, labels in batches.take(1):
   print(texts)
   print(labels)

ここまでは
padded_batch(5).take(2)
のようにpadded_batch()とtake()をまとめて書いていましたが、
batches = train_data.padded_batch(5)
のようにミニバッチに分割する部分を単独で書いた方が後々使いやすいです。

batches = train_data.padded_batch(5)
for batch in batches.take(1):
    print(batch)
のようにループを回すときにtake()を使うと1件だけ取り出して中のデータを確認したり、10件だけ取り出して軽く動作確認をしたりできます。

さらに
for batch in batches.take(1):
のかわりに
for texts, labels in batches.take(1):
のように書くとレビューデータとラベルデータを分けて使用できます。

textsの中身は以下のようなものです。

tf.Tensor(
[[  62   18   41  604  927   65    3  644 7968   21   35 5096   36   11
   43 2948 5240  102   50  681 7862 1244    3 3266   29  122  640    2
   26   14  279  438   35   79  349  384   11 1991    3  492   79  122
  188  117   33 4047 4531   14   65 7968    8 1819 3947    3   62   27
    9   41  577 5044 2629 2552 7193 7961 3642    3   19  107 3903  225
   85  198   72    1 1512  738 2347  102 6245    8   85  308   79 6936
 7961   23 4981 8044    3 6429 7961 1141 1335 1848 4848   55 3601 4217
 8050    2    5   59 3831 1484 8040 7974  174 5773   22 5240  102   18
  247   26    4 3903 1612 3902  291   11    4   27   13   18 4092 4008
 7961    6  119  213 2774    3   12  258 2306   13   91   29  171   52
  229    2 1245 5790  995 7968    8   52 2948 5240 8039 7968    8   74
 1249    3   12  117 2438 1369  192   39 7975    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0    0    0    0    0    0    0    0    0    0    0
    0    0    0    0]
中略
], shape=(5, 200), dtype=int64)

labelsの中身は以下のようなものです。

tf.Tensor([0 0 0 1 1], shape=(5,), dtype=int64)

takeを使うとミニバッチ1回分ずつデータを取り出します。
take(n)のnの部分に数字を入れると何回データを取り出すかを指定できます。

for i, (texts, labels) in enumerate(batches.take(2)):
   print(i)
   print(labels)
   print()

上記を実行すると下記のようになります。

0
tf.Tensor([0 0 0 1 1], shape=(5,), dtype=int64)

1
tf.Tensor([1 0 0 0 0], shape=(5,), dtype=int64)

ループの1周目でデータを5件取り出して、ループの2周目で5件取り出して、1バッチごとに5件ずつデータを取り出しています。
これは事前に.padded_batch(5)で5件ずつにデータを区切ったためです。

for i, (texts, labels) in enumerate(batches.take(-1)):
   print(i)
   print(labels)
   print()

上記のように.take(-1)とするとすべてのデータを取り出します。
元のデータが25,000件で、5個ずつにデータを区切った場合は、5000回ループが走ることになります。






いいなと思ったら応援しよう!