Използвайте вграждания на документи в BigQuery за сходство на документи и задачи за клъстериране

BigQuery предлага възможност за зареждане на TensorFlow SavedModel и извършване на прогнози. Тази възможност е чудесен начин да добавите текстово базирано сходство и групиране върху вашето хранилище за данни.

Следвайте, като копирате и поставяте заявки от моят бележник в GitHub. Можете да изпробвате заявките в конзолата BigQuery или в бележник на AI Platform Jupyter.

Storm съобщава данни

Като пример ще използвам набор от данни, състоящ се от доклади за вятъра, изпратени в офисите на Националната метеорологична служба от „наблюдатели на бури“. Това е публичен набор от данни в BigQuery и към него може да се направи заявка, както следва:

SELECT 
  EXTRACT(DAYOFYEAR from timestamp) AS julian_day,
  ST_GeogPoint(longitude, latitude) AS location,
  comments
FROM `bigquery-public-data.noaa_preliminary_severe_storms.wind_reports`
WHERE EXTRACT(YEAR from timestamp) = 2019
LIMIT 10

Резултатът изглежда така:

Да кажем, че искаме да изградим SQL заявка за търсене на коментари, които изглеждат като „захранване на електропровод в дом“.

стъпки:

  • Заредете модел за машинно обучение, който създава вграждане (по същество компактно числено представяне) на някакъв текст.
  • Използвайте модела, за да генерирате вграждането на нашата дума за търсене.
  • Използвайте модела, за да генерирате вграждането на всеки коментар в таблицата с отчети за вятъра.
  • Потърсете редове, където двете вграждания са близо едно до друго.

Зареждане на модел за вграждане на текст в BigQuery

TensorFlow Hub има редица модели за вграждане на текст. За най-добри резултати трябва да използвате модел, който е обучен на данни, които са подобни на вашия набор от данни и който има достатъчен брой измерения, за да улови нюансите на вашия текст.

За тази демонстрация ще използвам вграждането „Swivel“, което е обучено в Google News и има 20 измерения (т.е. доста е грубо). Това е достатъчно за това, което трябва да направим.

Слоят за вграждане на Swivel вече е наличен във формат TensorFlow SavedModel, така че просто трябва да го изтеглим, да го извлечем от tarred, gzipped файл и да го качим в Google Cloud Storage:

FILE=swivel.tar.gz
wget --quiet -O tmp/swivel.tar.gz  https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1?tf-hub-format=compressed
cd tmp
tar xvfz swivel.tar.gz
cd ..
mv tmp swivel
gsutil -m cp -R swivel gs://${BUCKET}/swivel

След като файлът на модела е в GCS, можем да го заредим в BigQuery като ML модел:

CREATE OR REPLACE MODEL advdata.swivel_text_embed
OPTIONS(model_type='tensorflow', model_path='gs://BUCKET/swivel/*')

Изпробвайте модел за вграждане в BigQuery

За да изпробваме модела в BigQuery, трябва да знаем неговата входна и изходна схема. Това биха били имената на слоевете Keras, когато е бил експортиран. Можем да ги получим, като отидем в конзолата на BigQuery и прегледаме раздела „Схема“ на модела:

Нека изпробваме този модел, като получим вграждането за известна реч от август, като извикаме входния текст като изречения и знаем, че ще получим изходна колона с име output_0:

SELECT output_0 FROM
ML.PREDICT(MODEL advdata.swivel_text_embed,(
SELECT "Long years ago, we made a tryst with destiny; and now the time comes when we shall redeem our pledge, not wholly or in full measure, but very substantially." AS sentences))

Резултатът има 20 числа, както се очаква, първите няколко от които са показани по-долу:

Търсене на сходство на документи

Дефинирайте функция за изчисляване на евклидовото квадратно разстояние между двойка вграждания:

CREATE TEMPORARY FUNCTION td(a ARRAY<FLOAT64>, b ARRAY<FLOAT64>, idx INT64) AS (
   (a[OFFSET(idx)] - b[OFFSET(idx)]) * (a[OFFSET(idx)] - b[OFFSET(idx)])
);
CREATE TEMPORARY FUNCTION term_distance(a ARRAY<FLOAT64>, b ARRAY<FLOAT64>) AS ((
   SELECT SQRT(SUM( td(a, b, idx))) FROM UNNEST(GENERATE_ARRAY(0, 19)) idx
));

След това изчислете вграждането за нашата дума за търсене:

WITH search_term AS (
  SELECT output_0 AS term_embedding FROM ML.PREDICT(MODEL advdata.swivel_text_embed,(SELECT "power line down on a home" AS sentences))
)

и изчислете разстоянието между вграждането на всеки коментар и term_embedding на думата за търсене (по-горе):

SELECT
  term_distance(term_embedding, output_0) AS termdist,
  comments
FROM ML.PREDICT(MODEL advdata.swivel_text_embed,(
  SELECT comments, LOWER(comments) AS sentences
  FROM `bigquery-public-data.noaa_preliminary_severe_storms.wind_reports`
  WHERE EXTRACT(YEAR from timestamp) = 2019
)), search_term
ORDER By termdist ASC
LIMIT 10

Резултатът е:

Спомнете си, че търсихме „прекъснат електропровод вкъщи“. Имайте предвид, че първите два резултата са „прекъснат електропровод в къщата“ — вграждането на текст е било полезно за разпознаването, че домът и къщата са сходни в този контекст. Следващият набор от най-добри съвпадения са изцяло за електропроводи, най-уникалната двойка думи в нашия термин за търсене.

Групиране на документи

Клъстерирането на документи включва използването на вгражданията като вход към алгоритъм за клъстериране, като K-Means. Можем да направим това в самия BigQuery и за да направим нещата малко по-интересни, ще използваме местоположението и деня от годината като допълнителни входове към алгоритъма за клъстериране.

CREATE OR REPLACE MODEL advdata.storm_reports_clustering
OPTIONS(model_type='kmeans', NUM_CLUSTERS=10) AS
SELECT
  arr_to_input_20(output_0) AS comments_embed,
  EXTRACT(DAYOFYEAR from timestamp) AS julian_day,
  longitude, latitude
FROM ML.PREDICT(MODEL advdata.swivel_text_embed,(
  SELECT timestamp, longitude, latitude, LOWER(comments) AS sentences
  FROM `bigquery-public-data.noaa_preliminary_severe_storms.wind_reports`
  WHERE EXTRACT(YEAR from timestamp) = 2019
))

Вграждането (output_0) е масив, но BigQuery ML в момента иска наименувани входове. Работата е да преобразувате масива в структура:

CREATE TEMPORARY FUNCTION arr_to_input_20(arr ARRAY<FLOAT64>)
RETURNS 
STRUCT<p1 FLOAT64, p2 FLOAT64, p3 FLOAT64, p4 FLOAT64,
       p5 FLOAT64, p6 FLOAT64, p7 FLOAT64, p8 FLOAT64, 
       p9 FLOAT64, p10 FLOAT64, p11 FLOAT64, p12 FLOAT64, 
       p13 FLOAT64, p14 FLOAT64, p15 FLOAT64, p16 FLOAT64,
       p17 FLOAT64, p18 FLOAT64, p19 FLOAT64, p20 FLOAT64>
AS (
STRUCT(
    arr[OFFSET(0)]
    , arr[OFFSET(1)]
    , arr[OFFSET(2)]
    , arr[OFFSET(3)]
    , arr[OFFSET(4)]
    , arr[OFFSET(5)]
    , arr[OFFSET(6)]
    , arr[OFFSET(7)]
    , arr[OFFSET(8)]
    , arr[OFFSET(9)]
    , arr[OFFSET(10)]
    , arr[OFFSET(11)]
    , arr[OFFSET(12)]
    , arr[OFFSET(13)]
    , arr[OFFSET(14)]
    , arr[OFFSET(15)]
    , arr[OFFSET(16)]
    , arr[OFFSET(17)]
    , arr[OFFSET(18)]
    , arr[OFFSET(19)]    
));

Получените десет клъстера могат да се визуализират в конзолата на BigQuery:

Как изглеждат коментарите в клъстер #1? Запитването е:

SELECT sentences 
FROM ML.PREDICT(MODEL `ai-analytics-solutions.advdata.storm_reports_clustering`, 
(
SELECT
  sentences,
  arr_to_input_20(output_0) AS comments_embed,
  EXTRACT(DAYOFYEAR from timestamp) AS julian_day,
  longitude, latitude
FROM ML.PREDICT(MODEL advdata.swivel_text_embed,(
  SELECT timestamp, longitude, latitude, LOWER(comments) AS sentences
  FROM `bigquery-public-data.noaa_preliminary_severe_storms.wind_reports`
  WHERE EXTRACT(YEAR from timestamp) = 2019
))))
WHERE centroid_id = 1

Резултатът показва, че това са предимно кратки, неинформативни коментари:

Какво ще кажете за клъстер #3? Повечето от тези доклади изглежда имат нещо общо с проверка с радар!!!

Наслади се!

Връзки

TensorFlow Hub има няколко модела за вграждане на текст. Не е нужно да използвате Swivel, въпреки че Swivel е добър избор за общо предназначение.

Пълните заявки са в моят бележник в GitHub. Можете да изпробвате заявките в конзолата BigQuery или в бележник на AI Platform Jupyter.