ბუნებრივი ენის დამუშავება Jupyter ნოუთბუქი · TensorFlow

სასწავლო CBoW მოდელი

ეს არის პრაქტიკული ნოუთბუქი. წაიკითხე კოდი და შედეგები აქ, ან გაუშვი ინტერაქტიულად Google Colab-ში ან Jupyter-ში.

ეს ნოუთბუქები არის AI დამწყებთათვის სასწავლო პროგრამა-ის ნაწილი

ამ მაგალითში ჩვენ განვიხილავთ სასწავლო CBoW ენის მოდელს, რომ მივიღოთ საკუთარი Word2Vec ჩაშენებული სივრცე. ჩვენ გამოვიყენებთ AG News მონაცემთა ბაზას, როგორც ტექსტის წყაროს.

იტვირთება…

ჩვენ დავიწყებთ თარიღების ნაკრების ჩატვირთვით:

იტვირთება…

CBoW მოდელი

CBoW სწავლობს სიტყვის წინასწარმეტყველებას $2N$ მეზობელ სიტყვებზე დაყრდნობით. მაგალითად, როდესაც $N=1$, ჩვენ მივიღებთ შემდეგ წყვილებს წინადადებიდან I like to train networks: (like,I), (I, like), (to, like), (like,to), (train,to), (to, train), (networks, train), (train,networks). აქ, პირველი სიტყვა არის მეზობელი სიტყვა, რომელიც გამოიყენება შეყვანის სახით, ხოლო მეორე სიტყვა არის ის, რასაც ჩვენ ვიწინასწარმეტყველებთ.

შემდეგი სიტყვის პროგნოზირებისთვის ქსელის ასაშენებლად, ჩვენ უნდა მივაწოდოთ მეზობელი სიტყვა შეყვანის სახით და მივიღოთ სიტყვის ნომერი, როგორც გამოსავალი. CBoW ქსელის არქიტექტურა შემდეგია:

  • შეყვანის სიტყვა გადადის ჩაშენების ფენაში. სწორედ ეს ჩაშენებული ფენა იქნება ჩვენი Word2Vec ემბედინგი, ამიტომ ჩვენ განვსაზღვრავთ მას ცალკე, როგორც embedder ცვლადი. ჩვენ გამოვიყენებთ ჩაშენების ზომას = 30 ამ მაგალითში, მიუხედავად იმისა, რომ თქვენ შეიძლება გქონდეთ ექსპერიმენტი უფრო მაღალი ზომებით (რეალური word2vec აქვს 300)
  • ჩაშენების ვექტორი შემდეგ გადაეცემა მკვრივ ფენას, რომელიც იწინასწარმეტყველებს გამომავალ სიტყვას. ამრიგად, მას აქვს vocab_size ნეირონები.

Keras-ში ჩაშენებულმა ფენამ ავტომატურად იცის, როგორ გადაიყვანოს რიცხვითი შეყვანა one-hot დაშიფვრად, ასე რომ ჩვენ არ მოგვიწევს ცალკე სიტყვის one-hot კოდირება. ჩვენ ვაზუსტებთ input_length=1-ს, რათა მივუთითოთ, რომ ჩვენ გვინდა მხოლოდ ერთი სიტყვა შეყვანის თანმიმდევრობაში - ჩვეულებრივ, ჩაშენებული ფენა შექმნილია უფრო გრძელი თანმიმდევრობით მუშაობისთვის.

გამოსასვლელად, თუ გამოვიყენებთ sparse_categorical_crossentropy-ს, როგორც დაკარგვის ფუნქციას, ჩვენ ასევე მოგვიწევს მხოლოდ სიტყვების რიცხვების მიწოდება, როგორც მოსალოდნელი შედეგები, ერთჯერადი კოდირების გარეშე.

ჩვენ დავაყენებთ vocab_size-ზე 5000-ზე, რათა ცოტა შევზღუდოთ გამოთვლები. ჩვენ ასევე განვსაზღვრავთ ვექტორიზატორს, რომელსაც მოგვიანებით გამოვიყენებთ.

იტვირთება…
გამოტანა
Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 embedding_1 (Embedding)     (None, 1, 30)             150000    
                                                                 
 dense_1 (Dense)             (None, 1, 5000)           155000    
                                                                 
=================================================================
Total params: 305,000
Trainable params: 305,000
Non-trainable params: 0
_________________________________________________________________

მოდი ვექტორიზატორის ინიციალიზაცია მოვახდინოთ და ამოვიღოთ ლექსიკა:

იტვირთება…

ტრენინგის მონაცემების მომზადება

ახლა მოდით დავაპროგრამოთ მთავარი ფუნქცია, რომელიც გამოთვლის CBoW სიტყვების წყვილებს ტექსტიდან. ეს ფუნქცია საშუალებას მოგვცემს დავაზუსტოთ ფანჯრის ზომა და დააბრუნოს წყვილების ნაკრები - შემავალი და გამომავალი სიტყვა. გაითვალისწინეთ, რომ ამ ფუნქციის გამოყენება შესაძლებელია როგორც სიტყვებზე, ასევე ვექტორებზე/ტენზორებზე - რაც მოგვცემს ტექსტის დაშიფვრის საშუალებას, სანამ გადავიტანთ მას to_cbow ფუნქციაზე.

იტვირთება…
გამოტანა
[['like', 'I'], ['to', 'I'], ['I', 'like'], ['to', 'like'], ['train', 'like'], ['I', 'to'], ['like', 'to'], ['train', 'to'], ['networks', 'to'], ['like', 'train'], ['to', 'train'], ['networks', 'train'], ['to', 'networks'], ['train', 'networks']]
[[<tf.Tensor: shape=(), dtype=int64, numpy=376>, <tf.Tensor: shape=(), dtype=int64, numpy=771>], [<tf.Tensor: shape=(), dtype=int64, numpy=3>, <tf.Tensor: shape=(), dtype=int64, numpy=771>], [<tf.Tensor: shape=(), dtype=int64, numpy=771>, <tf.Tensor: shape=(), dtype=int64, numpy=376>], [<tf.Tensor: shape=(), dtype=int64, numpy=3>, <tf.Tensor: shape=(), dtype=int64, numpy=376>], [<tf.Tensor: shape=(), dtype=int64, numpy=1>, <tf.Tensor: shape=(), dtype=int64, numpy=376>], [<tf.Tensor: shape=(), dtype=int64, numpy=771>, <tf.Tensor: shape=(), dtype=int64, numpy=3>], [<tf.Tensor: shape=(), dtype=int64, numpy=376>, <tf.Tensor: shape=(), dtype=int64, numpy=3>], [<tf.Tensor: shape=(), dtype=int64, numpy=1>, <tf.Tensor: shape=(), dtype=int64, numpy=3>], [<tf.Tensor: shape=(), dtype=int64, numpy=1045>, <tf.Tensor: shape=(), dtype=int64, numpy=3>], [<tf.Tensor: shape=(), dtype=int64, numpy=376>, <tf.Tensor: shape=(), dtype=int64, numpy=1>], [<tf.Tensor: shape=(), dtype=int64, numpy=3>, <tf.Tensor: shape=(), dtype=int64, numpy=1>], [<tf.Tensor: shape=(), dtype=int64, numpy=1045>, <tf.Tensor: shape=(), dtype=int64, numpy=1>], [<tf.Tensor: shape=(), dtype=int64, numpy=3>, <tf.Tensor: shape=(), dtype=int64, numpy=1045>], [<tf.Tensor: shape=(), dtype=int64, numpy=1>, <tf.Tensor: shape=(), dtype=int64, numpy=1045>]]

მოდით მოვამზადოთ ტრენინგის მონაცემთა ბაზა. ჩვენ გადავხედავთ ყველა სიახლეს, დავურეკეთ to_cbow-ს, რათა მივიღოთ სიტყვების წყვილების სია და დავამატოთ ეს წყვილები X და Y. დროის გულისთვის ჩვენ განვიხილავთ მხოლოდ პირველ 10000 სიახლეს - შეგიძლიათ მარტივად მოხსნათ შეზღუდვა იმ შემთხვევაში, თუ მეტი დრო გექნებათ ლოდინი და გსურთ მიიღოთ უკეთესი ემბედინგები :)

იტვირთება…

ჩვენ ასევე გადავიყვანთ ამ მონაცემებს ერთ მონაცემთა ბაზაში და შევაგროვებთ მას ტრენინგისთვის:

იტვირთება…

ახლა მოდით გავაკეთოთ რეალური ტრენინგი. ჩვენ გამოვიყენებთ SGD ოპტიმიზატორს საკმაოდ მაღალი სწავლის სიჩქარით. ასევე შეგიძლიათ სცადოთ თამაში სხვა ოპტიმიზატორებთან, როგორიცაა Adam. ჩვენ ვივარჯიშებთ 200 ეპოქის დასაწყისისთვის - და შეგიძლიათ ხელახლა მართოთ ეს უჯრედი, თუ გსურთ კიდევ უფრო დაბალი დანაკარგი.

იტვირთება…
გამოტანა
Epoch 1/200
/usr/local/lib/python3.7/dist-packages/keras/optimizer_v2/gradient_descent.py:102: UserWarning: The `lr` argument is deprecated, use `learning_rate` instead.
  super(SGD, self).__init__(name, **kwargs)
2156/2156 [==============================] - 7s 3ms/step - loss: 5.6134
Epoch 2/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.5431
Epoch 3/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.5029
Epoch 4/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.4754
Epoch 5/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.4548
Epoch 6/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.4382
Epoch 7/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.4243
Epoch 8/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.4123
Epoch 9/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.4019
Epoch 10/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3926
Epoch 11/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3843
Epoch 12/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3767
Epoch 13/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3697
Epoch 14/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3632
Epoch 15/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3571
Epoch 16/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3513
Epoch 17/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3459
Epoch 18/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3408
Epoch 19/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3359
Epoch 20/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3312
Epoch 21/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3266
Epoch 22/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3223
Epoch 23/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3181
Epoch 24/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3140
Epoch 25/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3101
Epoch 26/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3062
Epoch 27/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.3025
Epoch 28/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2989
Epoch 29/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2953
Epoch 30/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2919
Epoch 31/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2885
Epoch 32/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2852
Epoch 33/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2819
Epoch 34/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2787
Epoch 35/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2756
Epoch 36/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2725
Epoch 37/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2695
Epoch 38/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2665
Epoch 39/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2636
Epoch 40/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2607
Epoch 41/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2578
Epoch 42/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2550
Epoch 43/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2523
Epoch 44/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2495
Epoch 45/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2468
Epoch 46/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2442
Epoch 47/200
2156/2156 [==============================] - 7s 3ms/step - loss: 5.2416
Epoch 48/200
2156/2156 [==
… (გამოტანა შემოკლებულია)
<keras.callbacks.History at 0x7ff7e52572d0>

ვცდილობ Word2Vec

Word2Vec-ის გამოსაყენებლად, მოდით გამოვყოთ ვექტორები, რომლებიც შეესაბამება ჩვენს ლექსიკაში ყველა სიტყვას:

იტვირთება…

ვნახოთ, მაგალითად, როგორ არის დაშიფრული სიტყვა Paris ვექტორში:

იტვირთება…
გამოტანა
tf.Tensor(
[-0.13308628  0.50972325  0.00344684  0.185389   -0.03176536  0.22262476
 -0.3856765  -0.6854793   0.5185803  -0.7215402  -0.16101503  0.15622072
  0.00653811 -0.14954254  0.03379822 -0.01243829  0.27907634 -0.32538188
  0.21718933  0.31112966 -0.24142407  0.15589055  0.2915561   0.19029242
  0.08425518 -0.0941902  -0.54313695 -0.24854654  0.26196313  0.18027727], shape=(30,), dtype=float32)

საინტერესოა Word2Vec-ის გამოყენება სინონიმების მოსაძებნად. შემდეგი ფუნქცია დააბრუნებს n უახლოეს სიტყვებს მოცემულ შენატანს. მათი საპოვნელად, ჩვენ გამოვთვალეთ $|w_i - v|$-ის ნორმა, სადაც $v$ არის ვექტორი, რომელიც შეესაბამება ჩვენს შეყვანილ სიტყვას და $w_i$ არის $i$-th სიტყვის კოდირება ლექსიკაში. შემდეგ ვახარისხებთ მასივს და ვაბრუნებთ შესაბამის ინდექსებს argsort-ის გამოყენებით და ვიღებთ სიის პირველ n ელემენტებს, რომლებიც შიფრავს ყველაზე ახლო სიტყვების პოზიციებს ლექსიკაში.

იტვირთება…
გამოტანა
['paris', 'philippines', 'seoul', 'jakarta', 'zoo']
იტვირთება…
გამოტანა
['china', 'russia', 'pakistan', 'israel', 'turkey']
იტვირთება…
გამოტანა
['official', 'military', 'office', 'police', 'sources']

Takeaway

ჭკვიანური ტექნიკის გამოყენებით, როგორიცაა CBoW, ჩვენ შეგვიძლია მოვამზადოთ Word2Vec მოდელი. თქვენ ასევე შეგიძლიათ სცადოთ skip-gram მოდელის გაწვრთნა, რომელიც გაწვრთნილი იქნება მეზობელი სიტყვის პროგნოზირებისთვის, რომელიც მოცემულია ცენტრალურში და ნახოთ რამდენად კარგად მუშაობს იგი.

ეს გაკვეთილი არის Microsoft “AI for Beginners” კურსის ქართული თარგმანი, გავრცელებული MIT ლიცენზიით.