BigQuery ML로 이미지 데이터 분류

1. 소개

이 Codelab에서는 BigQuery에서 요가 자세 이미지를 저장 및 분석하고 BigQuery ML로 분류 모델을 구현하여 다른 형식의 코드 없이 SQL 구성만 사용하여 자세에 라벨을 지정하는 사용 사례에 대해 설명합니다.

BigQuery 및 BQML

BigQuery는 운영 오버헤드 없이 바이트에서 페타바이트로 확장할 수 있는 서버리스 멀티 클라우드 데이터 웨어하우스입니다. 따라서 ML 학습 데이터를 저장하는 데 적합합니다. 또한 기본 제공되는 BQML(BigQuery 머신러닝) 및 분석 기능을 통해 SQL 쿼리만 사용하여 코드 없이 예측을 생성할 수 있습니다. 그리고 통합 쿼리를 사용하여 외부 소스의 데이터에 액세스할 수 있으므로 복잡한 ETL 파이프라인이 필요하지 않습니다. BigQuery 페이지에서 BigQuery가 제공하는 모든 것을 확인할 수 있습니다.

지금까지 우리는 BigQuery를 사용자가 구조화된 데이터 및 반구조화된 데이터를 분석하는 데 도움이 되는 완전 관리형 클라우드 데이터 웨어하우스로 알고 있었습니다. 하지만

  • BigQuery는 구조화되지 않은 데이터에 대한 모든 분석 및 ML을 수행하도록 확장되었습니다.
  • SQL 쿼리를 사용하면 추가 코드를 작성하지 않아도 이미지, 동영상, 오디오 등에 대한 통찰력 있는 통계와 분석 및 ML을 대규모로 수행할 수 있습니다.
  • 구조화된 데이터와 구조화되지 않은 데이터가 모두 하나의 테이블에 함께 존재하는 것처럼 결합할 수 있습니다.

다음 섹션에서 다루는 요가 자세 분류 사용 사례에서 이 내용에 대해 알아보겠습니다.

BigQuery ML로 이미지 데이터 분류

구조화된 쿼리를 사용하여 마치 구조화된 데이터인 것처럼 이미지를 처리하고 분석할 수 있는 기능은 업계 최초입니다. 이제 BigQuery ML을 사용하는 머신러닝 분류 모델을 사용하여 결과를 예측할 수도 있습니다. 이해를 돕고자 관련 단계를 5단계로 좁혔습니다.

fe97945bce996e1.jpeg

위의 단계는 라벨로만 볼 경우 복잡할 수 있습니다. BigQuery Dataset, BigLake 연결, Cloud Storage 버킷(컨테이너), 객체 테이블(외부 데이터 소스), BQML 등과 같은 관련된 각 구성요소의 세부 정보는 모두 구현 섹션에 정의되어 있습니다. 따라서 이러한 용어에 아직 익숙하지 않더라도 실망하지 마세요.

빌드할 항목

아래 항목을 다루는 BQML을 사용하여 이미지 데이터 분류 모델을 만듭니다.

  • 테이블 및 모델 구성요소를 포함하는 BigQuery 데이터 세트
  • 모델의 요가 이미지를 저장하기 위한 Google Cloud Storage(GCS) 버킷
  • Cloud Storage 이미지에 액세스하기 위한 외부 테이블
  • GCS의 이미지에 액세스하기 위한 외부 테이블용 BigLake 연결
  • BigQuery ML의 ResNet 모델
  • 만든 모델을 이용한 추론
  • 이미지 데이터 분석을 위한 BigQuery SQL
  • 구조화된 데이터 및 구조화되지 않은 데이터를 함께 쿼리하는 BigQuery SQL

학습할 내용

  • Cloud Storage Bucket 생성 및 이미지 저장 방법
  • BigQuery 데이터 세트, 테이블 및 연결을 만드는 방법
  • BQML을 사용하여 이미지 데이터 분류 모델을 만드는 방법
  • BigQuery ML을 사용하여 만든 모델로 예측하는 방법
  • BigQuery SQL을 사용하여 이미지를 쿼리하고 구조화된 데이터와 결합하는 방법

2. 요구사항

  • 브라우저(Chrome 또는 Firefox 등)
  • BigQuery, Cloud Storage, BigLake 연결 서비스가 포함된 결제가 사용 설정된 Google Cloud 프로젝트
  • 다음 섹션에는 이미지 데이터 분류 애플리케이션을 만드는 단계 목록이 나와 있음

3. 데이터 세트 및 BigLake 연결 만들기

5가지 요가 자세의 이미지 감지 사용 사례의 경우 공개적으로 사용 가능한 데이터 세트를 사용했으며 이 저장소에서 데이터 세트에 액세스할 수 있습니다. 식별하는 요가 자세는 다운독, 여신, 플랭크, 나무, 전사2로 제한됩니다. BigQuery 데이터 세트를 만들려면 먼저 Google Cloud 프로젝트를 선택하거나 만들고 프로젝트에 결제가 사용 설정되어 있는지 확인하세요. BigQuery API 및 BigQuery Connection API를 사용 설정합니다. 이 구현에 사용되는 모든 서비스는 선택한 동일한 리전에 있어야 합니다.

a. 아래 표시된 단계를 사용하여 'yoga_set' 데이터 세트를 만듭니다.

BigQuery 편집기로 이동하여 다음 명령어를 입력합니다.

CREATE SCHEMA `<<project_id>>.yoga_set`;

b. BigLake 연결을 사용하면 세분화된 BigQuery 액세스 제어 및 보안을 유지하면서 외부 데이터 소스를 연결할 수 있습니다. 여기에서는 이미지 데이터용 Cloud Storage입니다. 이 연결을 사용하여 Cloud Storage에서 객체를 읽습니다. BigLake 연결을 만들려면 다음 단계를 따르세요.

BigQuery 페이지의 탐색기 창에서 '데이터 추가'를 클릭합니다.

4cb42b1245bb0ba6.pngBigQuery '외부 데이터 추가' 화면

외부 데이터 소스에 연결을 클릭하고 BigLake 및 원격 기능 옵션을 선택합니다.

9ffec2b2bfcc3cd5.png외부 데이터 소스 연결 구성

연결 ID를 제공하고 연결을 만듭니다. <<SERVICE_ACCOUNT>> 연결이 생성되면 화면에 표시될 서비스 계정 ID를 기록해 두세요. 이 예시에서 연결 ID는 'yoga-pose-conn'입니다. 리전을 기록해 두세요.

4. Google Cloud Storage 버킷 만들기 및 권한 부여

Google Cloud Storage 버킷을 사용하여 모델을 만들려는 요가 자세의 이미지 파일을 포함하겠습니다. 버킷은 분석할 이미지를 포함하는 Cloud Storage 컨테이너입니다.

a. 콘솔에서 검색하여 Google Cloud Storage로 이동한 다음 '버킷'을 클릭하여 버킷 홈페이지로 이동하고 '만들기'를 클릭합니다.

a6f6b26cffb53ae0.pngGoogle Cloud Storage 버킷 페이지

b. 버킷 만들기 페이지에서 버킷 정보(고유한 이름)를 입력하고 계속 진행합니다. 위 단계에서 설명한 데이터 세트 및 연결과 동일한 리전에 있는지 확인하고 '만들기'를 클릭합니다.

1280366a42b7bdf6.pngGoogle Cloud Storage 버킷 만들기 페이지

다음 단계로 이동하기 전에 서비스 계정, 버킷 이름 및 경로를 기록했는지 확인하세요.

c. 버킷이 만들어지면 이미지를 저장하고(콘솔 또는 Cloud Shell 명령어 또는 프로그래매틱 방식으로) 이미지에 액세스하기 위해 연결 서비스 계정(앞서 저장한 계정)에 필요한 권한을 부여합니다.

> export sa=<<"SERVICE_ACCOUNT">>
> gsutil iam ch serviceAccount:$sa:objectViewer "gs://<<bucket>>"

5. 객체 테이블 만들기

만든 연결을 사용하여 버킷의 구조화되지 않은 데이터에 액세스하려면 BigQuery에서 외부 객체 테이블을 만듭니다. BigQuery 편집기에서 아래의 CREATE SQL을 실행합니다.

CREATE OR REPLACE EXTERNAL TABLE `<<dataset>>.<<table_name>>`
WITH CONNECTION `us.<<connection-name>>`
OPTIONS(
object_metadata="SIMPLE", uris=["gs://<<bucket>>/<<folder_if_exists>>/*.jpg"]);

외부 테이블이 아래와 같이 생성됩니다.

bda48f566e0c292f.png

새로 생성된 외부 테이블에서 자세를 빠르게 쿼리해 보겠습니다.

SELECT data , uri
FROM `yoga_set.yoga_poses`
WHERE REGEXP_CONTAINS(uri, 'gs://yoga_images/Downdog')
Limit 1;

아래 스크린샷에서 볼 수 있듯이 비정형 이미지를 구조화된 데이터처럼 생성하고 조작할 수 있습니다.

7d1784122b5013f.png

이제 위의 쿼리 결과를 작은 Python 스니펫으로 내보내 결과를 시각화해 보겠습니다.

'결과 저장'을 클릭하고 'CSV 로컬 파일' 옵션을 선택하여 결과를 내보냅니다. 그 다음 Colab 노트북을 열고(또는 새로 만들고) 아래의 코드를 입력합니다.

from IPython.display import display
from PIL import Image
import io
import pandas as pd
import base64
df = pd.read_csv('/content/sample_data/<<your_csv>>')
imgdata = base64.b64decode(str(df.data[0]))
image = Image.open(io.BytesIO(imgdata))
display(image)

실행하면 아래와 같은 결과가 표시됩니다.

b8edd68cb281786a.png

외부 테이블을 만들고 SQL 쿼리만 사용하여 Cloud Storage에서 이미지에 액세스했으니 분류 모델을 만드는 다음 섹션으로 이동하겠습니다.

6. 모델 만들기 및 Google Cloud Storage에 만든 모델 업로드

이 구현을 위해 선행 학습된 ResNet 50 모델을 사용하여 방금 만든 객체 테이블에서 추론을 실행합니다. ResNet 50 모델은 이미지 파일을 분석하고 이미지가 해당 클래스(logits)에 포함될 가능성을 나타내는 벡터 배치를 출력합니다.

이 단계로 이동하기 전에 필요한 모든 권한이 있는지 확인하세요. 그 다음 아래 단계를 따릅니다.

  1. 위치에서 모델을 다운로드하고 로컬에 저장합니다.
  2. saved_model.pb 및 변수 폴더로 압축을 풀어야 합니다.
  3. 이전 섹션에서 만든 버킷에 이 두 파일(파일 및 폴더)을 업로드합니다.

2629ff3eda214946.pngResNet 모델 파일이 업로드된 Google Cloud Storage 버킷 'yoga_images'

이 단계가 완료되면 모델 관련 파일이 위 이미지에 표시된 이미지와 동일한 버킷에 있어야 합니다.

7. BQML에 모델 로드 및 추론

이 단계에서는 앞에서 만든 외부 테이블과 동일한 BigQuery 데이터 세트에 모델을 로드하고 Cloud Storage의 저장한 이미지에 적용합니다.

a. BigQuery 편집기에서 다음 SQL 문을 실행합니다.

CREATE MODEL `<<Dataset>>.<<Model_Name>>`
OPTIONS(
model_type = 'TENSORFLOW',
model_path = 'gs://<<Bucket>>/*');

실행이 완료되면(데이터 세트에 따라 다소 시간이 걸릴 수 있음) BigQuery의 데이터 세트 섹션에 모델이 나열되는 것을 볼 수 있습니다.

435fa0919aeb57a6.png만든 모델이 나열된 BigQuery 데이터 세트

b. 모델을 검사하여 입력 및 출력 필드를 확인합니다.

데이터 세트를 확장하고 방금 만든 'yoga_poses_resnet' 모델을 클릭합니다. '스키마' 탭을 클릭합니다.

e88928764f10f6ff.pngBigQuery 모델 정의 스키마 탭

라벨 섹션에 출력 필드를 나타내는 'activation_49' 필드가 표시됩니다. 특성 섹션에서 모델에 입력될 것으로 예상되는 필드를 나타내는 'input_1'을 확인할 수 있습니다. '테스트' 데이터에 전달하는 필드로 추론 쿼리(또는 예측 쿼리)에서 'input_1'을 참조합니다.

c. 요가 자세 추론하기!

방금 만든 모델을 사용하여 테스트 이미지 데이터를 분류해 보겠습니다. 모델을 만들었을 때 외부 테이블로 만든 Cloud Storage 버킷에서 식별된 몇 가지 테스트 이미지(요가 자세)가 있는지 확인하세요. 방금 만든 BQML 모델을 사용하여 추론을 수행하기 위해 BigQuery에서 해당 테스트 이미지를 선택적으로 쿼리하겠습니다. 아래 쿼리를 사용하여 테스트를 트리거합니다.

SELECT *
FROM ML.PREDICT(
MODEL yoga_set.yoga_poses_resnet,
(SELECT uri, ML.DECODE_IMAGE(data) AS input_1
FROM yoga_set.yoga_poses where REGEXP_CONTAINS(uri,
'gs://yoga_images/Downdog/00000097.jpg')));

위의 쿼리에서 외부 테이블의 특정 URI 값(00000097.jpg)을 포함하는 것으로 식별된 하나의 테스트 이미지를 선택합니다. 또한 SELECT 부분은 ML.PREDICT 함수가 작동하도록 ML.DECODE_IMAGE 구조를 'input_1' 필드로 사용합니다.

실행이 완료되면 아래와 같이 결과가 표시됩니다.

867018993845e943.png

이제 ResNet 모델에 대해 심도 있게 알고 있는 사람들은 분류를 이해하는 데 도움이 되셨을 것입니다. 그렇지 않다면 분류를 시각적으로 이해하기 위해 작은 스니펫을 코딩해 보겠습니다.

d. 결과 평면화

위 출력을 시각화하는 한 가지 방법은 BigQuery SQL의 UNNEST 구문을 사용하여 activation_49 필드 값을 평면화하는 것입니다. 이전 단계의 결과를 평면화하려면 아래 쿼리를 참조하세요. 결과 클래스에 텍스트 라벨을 추가로 지정하려는 경우 쿼리에서 자리표시자 <<LABEL_LOGIC>> 대신 로직을 도입할 수 있습니다(사용 시 주석 처리 삭제).

with predictions as (
SELECT
Uri, data, SPLIT(uri, "/")[OFFSET(ARRAY_LENGTH(SPLIT(uri, "/")) - 1)] as img,
i as label_i,
<<LABEL_LOGIC>> label,
Score
FROM ML.PREDICT(
MODEL yoga_set.yoga_poses_resnet,
(SELECT data, uri, ML.DECODE_IMAGE(data) AS input_1
FROM yoga_set.yoga_poses
WHERE
REGEXP_CONTAINS(uri,'gs://yoga_images/Goddess/00000007.jpg'))),
UNNEST(activation_49) as score WITH OFFSET i)
SELECT * FROM predictions
ORDER BY score DESC
LIMIT  5;

클래스 라벨 지정 로직이 없으면 쿼리에 대한 출력은 아래와 같습니다.

71f580f41f0811f3.png

하지만 이 경우에서는 샘플 로직을 적용했으며 결과는 다음과 같습니다.

1c6df6ecd14fba1.png

모델에 대해 자세히 읽고 데이터 및 모델 출력에 가장 적합한 로직을 적용할 수 있습니다.

e. 추론 시각화

마지막으로 분류 결과를 시각화하는 빠른 Python 스니펫을 살펴보겠습니다. 위 쿼리 결과를 CSV 파일로 내보내고 Python 코드에서 참조합니다.

68756e7e4b8d7a29.png

위의 이미지 출력은 BQML을 사용한 분류를 위해 ML.PREDICT 쿼리에 전달한 테스트 입력과 정확히 동일한 요가 자세 '다운독'을 나타냅니다!

8. 통합 구조화된 데이터 및 구조화되지 않은 데이터

마지막으로 이 구현에서 제가 가장 좋아하는 부분은 구조화된 관계형 테이블의 필드를 이 구조화되지 않은 이미지 데이터와 통합하는 것입니다. 자세와 건강 관련 데이터를 보관하기 위해 외부 테이블과 동일한 데이터 세트에 구조화된 BigQuery 테이블을 만들었습니다.

125bdf848c86fbe.pngBigQuery 구조화된 테이블 'yoga_health' 스키마

위의 이미지는 'yoga_health'라는 구조화된 데이터 테이블의 스키마를 나타내며 필드는 pose, focus, health_benefit 및 breath입니다. 아래 쿼리는 구조화된 데이터와 구조화되지 않은 데이터를 조인합니다.

SELECT SPLIT(uri, "/")[OFFSET(ARRAY_LENGTH(SPLIT(uri, "/")) - 2)] as pose,
a.health_benefit, breath, focus, data
FROM `abis-345004.yoga_set.yoga_health` a, yoga_set.yoga_poses b
WHERE a.pose = SPLIT(uri, "/")[OFFSET(ARRAY_LENGTH(SPLIT(uri, "/")) - 2)];

결과는 다음과 같습니다.

469bdfcffa9e19fd.png

참고: 이 블로그에서 다룬 모든 쿼리는 BigQuery Magic 명령어를 사용하여 Python 노트북에서 직접 실행할 수 있습니다.

9. 삭제

이 게시물에서 사용한 리소스의 비용이 Google Cloud 계정에 청구되지 않도록 하려면 다음 단계를 수행하세요.

  1. Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.
  2. 프로젝트 목록에서 삭제하려는 프로젝트를 선택한 후 '삭제'를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 후 '종료'를 클릭하여 프로젝트를 삭제합니다.

10. 수고하셨습니다.

수고하셨습니다. BigQuery에서 구조화되지 않은 데이터를 성공적으로 저장하고 쿼리했으며 BQML을 사용하여 분류 모델을 만들고 모델로 테스트 요가 자세를 예측했습니다. 이렇게 구현하려면 Google Cloud 프로젝트를 시작하세요. 또한 Google Cloud의 데이터베이스 또는 기타 엔드 투 엔드 애플리케이션 구현에 대해 자세히 알아보려면 제 블로그를 방문해주세요.