BigQuery 원격 함수를 사용한 Object Table Label Detection

김민형·2023년 5월 29일
0

GCP - AI,ML

목록 보기
5/14

BigQuery 원격 함수

BigQuery 원격 함수는 Cloud Functions 및 Cloud Run과 BigQuery의 직접적인 통합을 제공하여 BigQuery 외부 소프트웨어에서 GoogleSQL 기능을 사용할 수 있는 것이다.
원하는 언어로 Cloud Functions 또는 Cloud Run을 구성하여 함수를 배포한 후 BigQuery에서 쿼리문을 통해 호출할 수 있다.

아래와 같은 강아지 이미지에 대한 객체 테이블을 생성하고 원격 함수에서 Vision API를 사용해 Label Detection을 진행해볼 것이다.

이미지 예시
보더콜리

퍼그

아키텍처

데이터셋 생성

데이터셋은 Stanford Dogs Dataset 여기에서 다운받았다.

무수히 많은 강아지들에 대한 이미지 데이터들이 있다.

보더콜리와 퍼그에 대한 데이터만 따로 사용해볼 것이다.

사전 작업

  • Cloud Storage 보더콜리와 퍼그 이미지를 저장할 버킷 및 폴더 생성
  • BigQuery에 객체 테이블 및 Function이 들어갈 데이터셋 생성
# 샘플 추출
mkdir sample
mv n02106166-Border_collie/ sample/
mv n02110958-pug/ sample/
cd sample/
gsutil cp -r n02106166-Border_collie/ gs://<버킷명>/<강아지 폴더>/<보더콜리 폴더>
gsutil cp -r n02110958-pug/ gs://<버킷명>/<강아지 폴더>/<퍼그 폴더>

BigQuery 객체 테이블은 외부 테이블로 Cloud Storage의 데이터와 커넥션을 맺어서 생성할 수 있다. 때문에 먼저 Cloud Storage와 맺을 커넥션을 생성해줘야 한다.

Cloud Storage의 버킷 리전과 동일해야 한다.

객체 테이블 생성

CREATE OR REPLACE EXTERNAL TABLE
  `<데이터셋>.<테이블>`
WITH CONNECTION 
  `<리전>.<커넥션 이름>` 
OPTIONS(
  object_metadata="SIMPLE",
  uris=["gs://<버킷명>/<강아지 폴더>/*"]
);

이런 메타데이터들이 포함된 객체 테이블이 생성됐다.

Cloud Functions 생성

HTTP를 통해 트리거링을 해줌으로써 BigQuery에서 이 HTTP url을 통해 Functions을 호출할 것이다.

런타임 : Python 3.11
진입점 : label_detection
main.py

import urllib.request

import flask
import functions_framework
from google.cloud import vision

@functions_framework.http
def label_detection(request: flask.Request) -> flask.Response:
    try:
        client = vision.ImageAnnotatorClient()
        calls = request.get_json()['calls']
        replies = []
        for call in calls:
            content = urllib.request.urlopen(call[0]).read()
            results = client.label_detection({'content': content})
            replies.append(vision.AnnotateImageResponse.to_dict(results))
        return flask.make_response(flask.jsonify({'replies': replies}))
    except Exception as e:
        return flask.make_response(flask.jsonify({'errorMessage': str(e)}), 400)

requirements.txt

Flask==2.2.2
functions-framework==3.3.0
google-cloud-vision==3.2.0

원격 함수 생성 및 호출

원격함수 생성

CREATE OR REPLACE FUNCTION 
  `<데이터셋>.<테이블>` (signed_url_ STRING) 
RETURNS 
  JSON REMOTE
WITH CONNECTION
  `<리전>.<커넥션 이름>`
OPTIONS(
  endpoint = '<트리거 URL>',
  max_batching_rows = 1
);

BigQuery에 루틴이 생성되고 아래와 같은 함수가 생성된다.
(루틴은 BigQuery에서 저장 프로시져, 원격 함수를 포함한 UDF, 테이블 함수를 포함하는 리소스 유형)
이제 이 함수를 쿼리문으로 호출함으로써 Label Detection을 해볼 것이다.

원격 함수 호출

SELECT 
  uri, <데이터셋>.<원격 함수>(signed_url)
FROM
  EXTERNAL_OBJECT_TRANSFORM(
    TABLE `<데이터셋>.<객체 테이블>`,
    ["SIGNED_URL"]
  )
WHERE REGEXP_CONTAINS(
  uri,
  r'<정규식>'
)
LIMIT 5;

이 간단한 쿼리문으로 Vision API를 통해 이미지에 대한 Label Detection이 수행된다. 여기선 보더콜리 이미지로 테스트 해봤다.
'Dog' 라벨을 발견할 수 있었고 score는 accuracy라고 생각하면 되는데 중간중간 이미지에 따라서 불분명하게 나온 것도 있지만 상당히 높은 편이다.

위의 과정을 수행하면서 발생할 수 있는 권한 에러가 두가지 있다.
해결 법은 아래와 같다.
1. Cloud Storage에 대한 권한 부족

Access Denied : BigQuery BigQuery:Permission denied while gobbling file pattern. <서비스 계정> does not have storage.object.list access to the Google Cloud Storage bucket. Permission 'storage.object.list' denied on resource (or it may not exist). Please make sure 'gs://<버킷명>' is accessible via appropriate IAM roles, e.g. Storage Object Viewer or Storage Object Creator.

Cloud Storage에 위의 에러에서 표시된 서비스 계정에 대한 storage.object.list 권한을 부여해주면 된다.

2. 외부 테이블에 대한 커넥션이 Cloud Functions에 권한이 없는 경우

Access Denied : BigQuery Biguery: Received response code 403 from endpoint https://<리전>.<프로젝트 ID>.cloudfunctions.net/label_detection; Make sure the service account associated with the connection <프로젝트 ID>.<리전>.<커넥션 이름>is granted the cloudfunctions.functions.invoke permission (e.g., via the Cloud Functions Invoker role) on your Cloud Function endpoint,or the run.routes.invoke permission (e.g., via the Cloud Run Invoker role) on your Cloud Run endpoint. Please allow 60 seconds for the permission change to propagate before retrying.

IAM에서 커넥션이 사용하는 서비스 계정에 대해 Cloud Functions Invoker 권한을 부여해주면 된다.

[BigQuery 원격 함수를 사용한 Object Table Label Detection 참고]
https://qiita.com/kosuke21/items/18fe7fea9fd7d265578c

profile
Solutions Architect (rlaalsgud97@gmail.com)

0개의 댓글