국가별 및 전 세계적 차원의 패턴을 한눈에 보기

이 데이터세트 내에서 시각적 패턴을 빠르고 효율적으로 파악하기 위해, 우리는 아티스트인 Kyle McDonald 씨와 협력하여 전 세계에서 확보한 수천 개의 그림을 오버레이했습니다. 이 작업은 우리가 합성 이미지를 만들고 국가별 추세는 물론 전 세계적인 추세를 파악하는 데에도 도움이 되었습니다. 우리는 이 데이터를 통해 시각적 추세를 찾아낸 방법을 보여 주기 위해 전 세계적으로 확보한 고양이와 의자 그림 1,000개를 각각 겹쳐서 애니메이션을 제작했습니다(아래 참조).

전 세계에서 확보한 1,000개의 그림으로 만든 고양이 모습:
전 세계에서 확보한 1,000개의 그림으로 만든 의자 모습:
고양이(또는 나무, 무지개, 해골 등)와 같이 원래 많이 그려지는 물체를 대강 그린 그림은 여러 문화권에서 대동소이하게 보이는 경우가 많았습니다.
하지만 특정 문화권에서만 친숙하고 다른 문화권에서는 그렇지 않은 물체는 눈에 띄는 차이를 보였습니다. 샌드위치는 윤곽이 뚜렷한 형태를 띠거나 선이 마구 뒤섞인 형태였으며, 머그잔 손잡이는 방향이 서로 반대로 그려지기도 했고, 의자는 정면 방향이나 측면 방향으로 그려져 있었습니다.

모든 상황에 맞는 해답이란 없음

우리는 이러한 합성 그림이 샌드위치에 사용된 빵의 종류부터 커피잔의 모양, 그리고 시각적으로 눈길을 끌도록 물체를 묘사하는 방법을 나타내는 미적 요소에 이르기까지 다양한 지역의 잠재고객 사이에서 관점과 선호 사항이 어떻게 다른지를 드러낼 수 있다는 사실을 깨달았습니다. 예를 들어, 일부 국가에서는 더 간단하게 표현되는 정면 모습을 그리는 일관된 경향이 나타난 반면에, 측면 모습을 그리는 일관된 경향성이 보이는 국가도 있었습니다.

이러한 이미지를 오버레이함으로써 데이터의 다양성이 부족할 때 신경망을 훈련시키는 방식을 개선할 방법도 알 수 있었습니다. 참고로, 데이터 다양성 부족 문제는 전 세계에서 확보한 대규모 오픈 데이터세트에서 조차 나타납니다. 예를 들면, Quick, Draw! 데이터세트에서 115,000개가 넘는 신발 그림을 분석한 결과, 스니커와 비슷한 형태의 단 한 가지 신발 스타일이 압도적으로 많이 표현된 것을 확인했습니다. 이 신발 스타일이 많이 그려졌기 때문에 신경망은 스타일만 '신발'로 인식하도록 학습되었습니다.

하지만 실제 세계에서와 마찬가지로, 데이터 훈련 영역에서도 모든 상황에 맞는 해답이란 건 없습니다. 우리는 '어떻게 하면 일관되면서도 효율적으로 데이터세트를 분석하여 잠재적 편향을 파악할 수 있는 단서를 찾을 수 있을까?' 라고 자문했습니다. 그리고 '팀이 다양성이 부족한 데이터세트를 기반으로 분류기를 만든다면 어떻게 될까?' 라는 질문에 대해서도 생각해 봤습니다.


데이터의 포괄성 진단

Google PAIR 이니셔티브의 일환으로 지난달에 발표한 오픈소스 도구인 Facets를 사용하면 대규모 데이터세트에서 패턴을 신속하게 파악할 수 있습니다. 이 도구의 목표는 Quick, Draw! 데이터세트와 같이 대규모 데이터세트의 대표성을 효율적이고 시각적으로 진단하는 것입니다.

다음은 Facets 도구 내의 Quick,Draw! 데이터세트를 보여 주는 스크린샷입니다. 이 도구는 수천 개의 그림을 국가(최대 100개국까지 지원)와 같은 특징 값을 기준으로 여러 차원에 'faceting' 하여 배치하는 데 도움이 되었습니다. 또한, 10개의 국가를 포함하는 뷰에서 '임의의 얼굴'과 같은 특징을 필터링한 후 100개의 국가로 확장할 수도 있습니다. 이에 따라 국가별 표현이 차지하는 비율을 한눈에 파악할 수 있습니다. 뿐만 아니라, 각각의 개별 그림을 확대하여 세부 사항을 확인함으로써 하나의 데이터 요소를 더욱 상세히 분석할 수도 있습니다. 이는 연구자가 미묘한 차이점 또는 이적인 부분을 찾아내거나 대규모 데이터세트 내에서 나중에 패턴으로 등장할 수 있는 아주 작은 시각적 추세에 대한 플래그 지정을 시작할 수 있도록 하므로, 특히 Quick, Draw!와 같은 대규모 시각적 데이터세트로 작업할 때 유용합니다.


다음은 '임의의 얼굴'에 대한 동일한 Quick, Draw! 데이터가 94개 국가에 대해 faceted되고 또 다른 뷰에 표시된 형태입니다. 아주 잠깐만 봐도 Facets이 그림을 로드한 이 새로운 시각화 형태에서 미국과 유럽 국가를 나타내는 데이터가 압도적으로 많다는 점이 분명히 드러납니다. 이는 Quick, Draw! 게임이 현재 영어로만 제공된다는 점을 간주하면 논리적으로 당연한 결과입니다. 우리는 차츰 언어를 더 추가할 계획입니다. 하지만 이 시각화에서는 데이터 내에서 영어 이외의 언어를 모국어로 사용하는 국가 중 브라질과 태국이 상대적으로 제대로 표현된 국가인 것처럼 보입니다. 이는 디자이너가 인터페이스 디자인의 어느 요소가 이러한 국가에서 제대로 작동했을지 분석할 여지가 있음을 시사했습니다. 그런 다음, 우리는 이 정보를 활용하여 전 세계에서 영어 이외의 언어를 모국어로 사용하는 다른 잠재고객에 대해 다음에 반복해서 이루어질 과정에서 Quick,Draw!를 향상시킬 수 있을 것입니다. 또한, 앞으로의 번역 작업에서 어떤 현지 언어를 우선적으로 처리할 지 결정하는데 도움이 되도록 이처럼 faceted된 데이터를 활용하고 있습니다.


Quick, Draw! 데이터의 포괄성을 진단하는 데 Facets을 사용하여 얻은 또 다른 성과는 누구나 데이터의 다양성을 향상시킬 수 있는 확실한 방법을 파악하고 잠재적인 편향을 확인하는 것이었습니다. 다음과 같은 개선 사항이 포함될 수 있습니다.
  • 데이터가 현지 또는 전 세계인을 더욱 정확하게 나타내도록 데이터 또는 콘텐츠 생성에 대한 인적 평가의 프로토콜 변경
  • 데이터의 하위 그룹을 분석하고 시각적 패턴 내에서 드러나는 '교차성'과 동일한 데이터베이스 식별
  • 더욱 포괄적일 수 있도록 데이터 증대 및 가중치 조정
우리는 이러한 데이터세트와 Facets 등의 도구를 발표함으로써 기계 학습에 더욱 포괄적인 접근 방식 탐구를 촉진하고 이러한 관찰을 혁신을 이룰 수 있는 기회로 바꿀 수 있기를 바랍니다. 우리는 Quick, Draw!와 Facets를 통해 이제 막 통찰력 있는 정보를 도출하기 시작했습니다. 여러분도 우리와 함께 더 많은 결과를 끌어내는 활동에 동참하시기 바랍니다.

감사의 말

Jonas Jongejan, Henry Rowley, Takashi Kawashima, 김종민, Nick Fox-Gieg 씨에게 Google Creative Lab 및 Google의 Data Arts Team과 협력하여 Quick, Draw!를 빌드해 주신 점에 대해 감사의 인사를 드립니다. 기계 학습의 공정성에 대한 동영상을 제작해 주신 Google Creative Lab의 Teo Soares, Alexander Chen, Bridget Prophet, Lisa Steinman 및 JR Schmidt 씨에게도 감사의 말을 전합니다. PAIR의 James Wexler, Jimbo Wilson 및 Mahima Pushkarna 씨에게는 Facets를 설계해 주신 점에 대해, Google Brain 팀의 선임 연구원인 Martin Wattenberg 및 Fernanda Viégas 씨와 UX 연구원인 Jess Holbrook 씨에게는 프로젝트를 이끌어 주신 점에 대해 감사의 인사를 드립니다. Google Cloud 팀의 Ian Johnson 씨에게는 오버레이된 그림에 대한 시각화 작업에 한몫을 해 주신 점에 대해 고맙다는 인사를 드립니다.

왼쪽(안드로이드 O 이전): 시스템 업데이트를 가장한 PHA 설치 화면입니다.
오른쪽(안드로이드  O): PHA가 설치되기 전에 먼저 사용자가 설치를 트리거한 앱에 권한을 부여해야 합니다.

Install unknown apps 권한을 통해, 어떤 앱이 앱 설치를 요청하는지 미리 확인하고, 잠재적인 위험을 줄일 수 있습니다. 이 권한은 다른 런타임 권한과 마찬가지로 설치를 요청하는 앱에 연결됩니다. 그리고 사용자가 해당 권한을 부여해야만, '앱 설치 메시지'를 표시할 수 있습니다. 다시말해, 안드로이드 O 이상 버전에서는 사용자에게 명시 권한을 받기 전에 사용자가 앱을 설치하도록 속일 수 없습니다.

이와 동시에, 사용자가 직접 신뢰할 수 있는 소스로부터 앱 설치를 허용할 수 있도록 간편하고 투명한 제어 기능이 제공됩니다. 설정에서 사용자가 앱 설치 권한을 승인한  앱 목록이 표시됩니다. 사용자는 원하는 경우 언제든지 부여한 권한을 취소할 수 있습니다.

사용자는 원하는 경우 언제든지 알 수 없는 앱 설치를 허용한 앱을 검토할 수 있습니다. 권한 부여 프로세스를 더욱 쉽게 하기 위해, 앱 개발자는 설치 흐름의 일부로 사용자에게 사용자 권한 화면을 표시할 수 있습니다.

개발자가 수행할 변경 작업

패키지 설치 프로그램을 통해 다른 앱을 다운로드하고 설치할 수 있는 기능이 필요한 앱 개발자는 다음 변경 사항을 확인해야 합니다. 앱이 26 이상의 targetSdkLevel을 사용하고 사용자에게 다른 앱을 설치하라는 메시지를 표시하는 경우 다음과 같이 매니페스트 파일에 REQUEST_INSTALL_PACKAGES 권한이 포함되어야 합니다.
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

이 권한을 선언하지 않은 앱은 다른 앱을 설치할 수 없습니다. 이는 다른 앱을 설치할 의도가 없는 앱을 보호할 수 있는 방법이기도 합니다. ACTION_MANAGE_UNKNOWN_APP_SOURCES 인텐트를 사용하여 사용자에게 Install unknown apps 권한 설정 화면을 표시할 수 있습니다. 또한, PackageManager canRequestPackageInstalls() API를 사용하여 이 권한의 상태를 쿼리할 수도 있습니다.

Google Play에서 배포되는 앱에는 Play 정책이 적용된다는 점에 유의하세요. 대부분의 경우 앱 내에서 다른 앱을 직접 다운로드하거나 설치하는 동작은 허용되지 않으며, 대신 Play Store의 앱 목록을 바로가는 딥 링크를 제공해야 합니다.

업데이트된 게시 가이드를 확인하시기 바랍니다. 여기에는 알 수 없는 앱 설치에 대한 자세한 내용이 나와 있습니다. 안드로이드 O에서 보안 강화에 관해 추가로 게시되는 글도 계속해서 살펴보시기 바랍니다.


각각의 기능과 기능을 수행하기 위한 Activity, 및 해당 기능에 진입하기 위한 URL 매핑을 먼저 정의한 후각 진입점에 대한 바이너리 크기를 줄이는 방향으로 리팩터링 작업을 구성하는 것이 좋습니다.

라이브러리를 어떻게 포함할지도 고려해야합니다. 특정 기능 모듈에만 필요한 라이브러리의 경우 기본 기능 모듈에 추가하는 대신, 해당 기능 모듈에만 라이브러리를 포함시킬 수 있습니다. 예를 들어 라이브러리 X, Y, Z에 종속되는 애플리케이션이 있다고 가정해 봅니다. 그러면 모든 종속 사항을 기본 모듈의 gradle.build 파일에 정의하여, 기본 모듈에 모든 라이브러리를 패키징할 수 있습니다. 하지만 기능 모듈의 코드에 라이브러리 Z만 필요한 경우 기본 모듈에서 해당 종속 사항만 기능 모듈로 이동하는 것이 합리적입니다. 여러 기능 모듈이 같은 라이브러리를 사용하는 경우에는 기본 모듈에 라이브러리를 유지하는 것이 좋습니다.



Lint 검사

많은 앱이 앱 내에 정의된 리소스 중 일부만을 사용합니다. 안드로이드 스튜디오에서는 사용되지 않는 리소스에 대한 Lint 검사가 기본적으로 제공됩니다. Alt+Ctrl+Shift+I(Mac OS의 경우 Cmd+Alt+Shift+I)를 누르고, 'unused resources'를 입력한 후 'Unused resources Android|Lint|Performance' 검사를 시작합니다. 이 검사는 설치 가능한 APK의 크기를 줄이는 데도 도움이 됩니다.



문자열 리소스

리소스와 유사하게, 문자열도 주의해야 합니다. 문자열 중에는 사용되고 있지 않은 문자열도 있을 수 있습니다. 일반적으로, 사용되지 않는 문자열 리소스를 제거하면 애플리케이션 크기를 상당히 줄일 수 있습니다. 애플리케이션이 다중 언어를 지원하는 경우 현지화된 리소스의 수를 줄이고자 할 수 있습니다. 그러면 일반적으로 리소스 자산에서 상당히 많은 양이 제거됩니다. 이는 앱이 몇 개의 언어만 지원하는데 여러 언어로 된 메시지를 포함하는 AppCompat 라이브러리를 사용하는 경우 특히 중요합니다. resConfig를 사용하여 특정 리소스 구성만 선택할 수 있습니다.

힌트: 일반적으로 'auto'를 사용하여 타사 라이브러리에서 가져오는 구성을 제한할 수 있습니다.

WebP로 전환

PNG 대신 WebP 이미지로 전환하면 Drawable Resource 크기를 상당히 줄일 수 있습니다. 안드로이드 인스턴트 앱은 WebP 형식의 모든 기능(투명성, 무손실 등)을 지원합니다. 다만, 애플리케이션 런처 아이콘은 PNG 형식을 사용해야 합니다. 일반적으로 앱 아이콘은 mipmap- 디렉토리에 저장됨으로 큰 문제는 없을 것 입니다. 이전 버전과 호환 가능한 솔루션이 필요한 경우, APK 모듈에 원래 PNG 이미지를 포함해야 하며 그러면 WebP 리소스가 자동으로 재정의됩니다(기본 소스 집합이 AAR/기능 모듈의 모든 리소스를 재정의함). [4]




물론, VectorDrawable을 사용하면 훨씬 더 많은 공간을 절약할 수 있지만 VectorDrawable을 사용하는 데는 코드 변경이 필요합니다. 반면, 위에 언급한 인스턴트 앱에는 WebP 이미지를 사용하고 설치 가능한 APK에는 PNG 이미지를 사용하는 트릭의 경우 코드를 수정할 필요가 없습니다.

런타임에 Asset 다운로드

인스턴트 앱 APK에 모든 리소스를 패키징할 필요는 없습니다. 애플리케이션이 실행 중에 추가 Asset을 다운로드할 수 있기 때문입니다. 이 접근 방법을 통해 앱은 필요한 Asset을 다운로드할 수 있습니다. 코드베이스를 상당히 변경해야 할 수 있지만, APK의 크기 감소에 큰 도움이 됩니다. 리소스를 축소해도 앱 기능 모듈 크기가 제한보다 낮게 줄어들지 않는다면, 이러한 방법을 검토해볼 수 있습니다.

네이티브 라이브러리 검토

사용중인 라이브러리에는 인스턴트 앱에서 전혀 사용되지 않는 네이티브 코드가 포함되어 있을 수 있습니다. 따라서 첫 번째 단계로 APK 내에 패키징된 네이티브 라이브러리를 검토하여 인스턴트 앱에 실제로 사용되는 라이브러리만 포함되어 있는지 확인해야 합니다. APK Analyzer(Build -> APK Analyzer…)를 사용하여 컴파일된 APK를 살펴봐야 합니다. [5]



외부 라이브러리 검토

다음으로, 앱의 코드와 연결된 모든 외부 라이브러리의 목록을 검토합니다. 의존성 전이 (transitive dependencies)에 의해 몇몇 예기치 않은 항목이 포함되어 있을 수 있습니다. 의존성 전이는 프로젝트가 참조하는 라이브러리가 다른 라이브러리를 참조하고 있는데, 그 다른 라이브러리가 또 다른 라이브러리에 종속될 수 있을 때 발생합니다. 때로는 이러한 의존성 전이 과정에서 전혀 필요하지 않은 라이브러리(예: 코드에서 절대 사용하지 않는 JSON 처리 라이브러리) 같은 예기치 않은 항목이 포함될 수 있습니다. 자세한 내용은 Gradle 사용자 가이드의 '의존성 전이 항목 제외' 섹션을 참조하세요.
안드로이드 스튜디오에는 프로젝트의 외부 종속 항목 분석에 사용할 수 있는 여러 가지 유용한 도구가 포함되어 있습니다. 어떠한 경우든 Project 뷰부터 살펴보면 도움이 됩니다.



'Project' 뷰에는 'External libraries'라는 섹션이 표시됩니다. 여기서 의존성 전이 항목을 포함하여 프로젝트에서 사용되는 모든 라이브러리를 볼 수 있습니다.


기본 기능 모듈의 크기를 더 줄이려면 코드 종속 항목과 외부 라이브러리에 유의해야 합니다. 'Project' 뷰를 확인하고 프로젝트에 필요하지 라이브러리를 찾습니다. 또한, 같은 기능을 제공하는 라이브러리도 찾습니다(예: 이미지 로드/캐싱을 지원하는 여러 라이브러리). [4]

APK Analyzer 도구를 사용하여 여러 빌드를 비교할 수도 있습니다. 이는 인스턴트 APK에도 효과가 있습니다.



마지막으로, 의존성 전이 항목을 검토하고 필요하지 않은 항목을 제외합니다. gradle -q :MODULE:dependencies --configuration compile 명령어를 사용하여 종속 항목 그래프를 검토합니다. 자세한 내용은 Gradle 문서에서 확인할 수 있습니다.

기타 팁

안드로이드 스튜디오 3.0에는 App Links Assistant 도구가 포함되어 있습니다. 이 도구는 필요한 인텐트 필터를 생성하는 데 도움이 될 수 있으며 프로젝트를 여러 모듈로 분할하는 데도 도움이 됩니다. [3]





크기 제한을 초과하지 않는 크기의 인스턴트 앱 번들을 구축했으면 이제는 빌드 프로세스가 최신 상태인지 확인하세요. 애플리케이션 패키지와 인스턴트 앱 APK가 'APK Signature Scheme v2'를 사용하여 서명되었는지 확인합니다. 최신 버전의 SDK 도구를 사용하여 APK를 서명하면 모든 작업이 자동으로 수행됩니다. 하지만 빌드 아티팩트를 수동으로 서명하는 경우에는 jarsigner를 사용하지 말고 그 대신 apksigner로 전환해야 합니다.

또한, 인스턴트 런타임 환경에 맞게 앱 코드를 변경하는 데 활용할 수 있는 유용한 팁이 몇 가지 있습니다. InstantApps.isInstantApp(...)을 기반으로 인스턴트/설치 가능한 애플리케이션에 대해 작은 코드 분기를 구성할 수 있습니다. 또한, 공유 인텐트를 사용할 때는 코드가 기기에 설치된 애플리케이션을 명시적으로 열거하지 않는지 확인하세요. 인스턴트 앱 보안 모델에서 이를 허용하지 않습니다. 간단히 일반 Intent.createChooser()를 사용하여 가능한 모든 작업 목록을 사용자에게 표시하면 됩니다.

기존 안드로이드 애플리케이션용 인스턴트 앱을 개발하는 데 필요한 작업은 개발자에 따라 다르며, 애플리케이션이 현재 구성된 방식에 따라 상당한 영향을 받습니다. 몇몇 경우, 프로젝트가 이미 다중 모듈로 구성되어 있으므로 쉬울 것입니다.

다른 개발자의 안드로이드 인스턴트 앱 사용 사례

끝으로, 인스턴트 앱을 이미 적용한 개발자들이 공유한 다음 정보를 참고해보시기 바랍니다.
안드로이드 개발자 웹사이트를 방문하여 안드로이드 인스턴트 앱 작업을 시작해 보고 다른 개발자가 들려주는 인스턴트 앱 성공 사례를 더 확인해 보시기 바랍니다.

예제 모델

이러한 기능을 살펴보기 위해 모델을 빌드하고 관련 코드 스니펫을 보여드리겠습니다. 훈련 및 테스트 파일을 얻기 위한 지침을 비롯하여, 전체 코드는 여기서 확인할 수 있습니다. 참고로, 이 코드는 Datasets와 Estimators가 기능적으로 작동하는 방식을 보여 주려고 작성한 것일 뿐, 최대의 성능을 고려하여 최적화한 코드는 아닙니다.

이 훈련된 모델은 네 가지 식물적 특징(꽃받침 길이, 꽃받침 너비, 꽃잎 길이, 꽃잎 너비)을 기준으로 붓꽃을 분류합니다. 추론 과정 중에 위의 네 가지 특징에 대한 값을 제공할 수 있으며, 모델에서는 꽃이 다음 세 가지 아름다운 변종 중 하나라고 예측하게 됩니다.
왼쪽에서 오른쪽으로: Iris setosa(제공: Radomil, CC BY-SA 3.0), Iris versicolor (제공: Dlanglois, CC BY-SA 3.0) 및 Iris virginica(제공: Frank Mayfield, CC BY-SA 2.0).

아래와 같은 구조로 심층 신경망 분류자를 훈련시킬 것입니다. 모든 입력 값과 출력 값은 float32이며, 여기서는 각 개별 붓꽃 종류의 확률을 예측하려는 것이므로 출력 값의 합계는 1이 됩니다.

예를 들어, Iris Setosa, Iris Versicolor, Iris Virginica에 대한 출력 결과가 각각 0.05, 0.9, 0.05일 수 있을 것입니다. 이는 Iris Versicolor일 확률이 90%임을 나타냅니다.

좋습니다! 이제 모델을 정의했으므로 Datasets와 Estimators를 사용하여 모델을 훈련시키고 예측하는 방법을 살펴봅시다.


Datasets 소개

Datasets는 TensorFlow 모델에 대한 입력 파이프라인을 만드는 새로운 방식입니다. 이 API는 feed_dict 또는 대기열 기반 파이프라인을 사용하는 것보다 훨씬 더 성능이 좋고 더욱 깔끔하며 사용하기 쉽습니다. Datasets는 종전과 같이 1.3에서도 tf.contrib.data에 있지만 1.4에서는 이 API를 코어로 옮길 예정입니다. 따라서 지금이 바로 이것을 시험해볼 최적의 시점입니다.

개략적으로 설명하자면 Datasets는 다음 클래스로 구성됩니다.

클래스 설명:
  • Datasets: 데이터세트를 생성하고 변환하는 메서드를 포함한 기본 클래스입니다. 이 클래스를 사용하여 메모리 내 데이터 또는 Python 생성기에서 데이터세트를 초기화할 수도 있습니다.
  • TextLineDataset: 텍스트 파일에서 줄을 읽어옵니다.
  • TFRecordDataset: TFRecord 파일에서 레코드를 읽어옵니다.
  • FixedLengthRecordDataset: 바이너리 파일에서 고정 크기 레코드를 읽어옵니다.
  • Iterator: 한 번에 하나의 데이터세트 요소에 액세스하는 방식을 제공합니다.

사용할 데이터세트

시작 단계로서, 먼저 모델을 피드하는 데 사용할 데이터세트를 살펴보도록 하겠습니다. CSV 파일에서 데이터를 읽어올 것이며, 행마다 5개의 값과 4개의 입력 값, 그리고 레이블을 포함하게 됩니다.

레이블은 다음과 같이 지정됩니다.
  • 0 - Iris Setosa
  • 1 - Versicolor
  • 2 - Virginica

데이터세트 표현

데이터세트를 설명하기 위해, 먼저 특징 목록을 생성합니다.
feature_names = [
    'SepalLength',
    'SepalWidth',
    'PetalLength',
    'PetalWidth']

모델을 훈련시킬 때는 입력 파일을 읽어와서 특징 및 레이블 데이터를 반환하는 함수가 필요합니다. Estimators를 사용하려면 다음 형식의 함수를 만들어야 합니다.
def input_fn():
    ...<code>...
    return ({ 'SepalLength':[values], ..<etc>.., 'PetalWidth':[values] },
            [IrisFlowerType])

반환 값은 다음과 같이 두 요소로 구성된 튜플로 구성되어야 합니다.
  • 첫 번째 요소는 각 입력 특징이 키이고 그 다음이 훈련 배치에 대한 값의 목록인 dict여야 합니다.
  • 두 번째 요소는 훈련 배치에 대한 레이블 목록입니다.

여기서는 입력 특징과 훈련 레이블로 구성된 배치를 반환할 것이므로 이는 반환문에 포함되는 모든 목록의 길이가 같을 것이라는 의미입니다. 기술적으로 설명하자면, 여기서 '목록'이라고 지칭한 것은 실제로는 1차원 TensorFlow 텐서를 의미합니다.

input_fn을 간단히 재사용할 수 있도록 몇 가지 인수를 추가하겠습니다. 이를 통해 각각 설정이 다른 입력 함수를 만들 수 있습니다. 이러한 인수는 꽤 간단합니다.
  • file_path: 읽어올 데이터 파일입니다.
  • perform_shuffle: 레코드 순서를 무작위로 할지 여부입니다.
  • repeat_count: 데이터세트에서 레코드에 대해 반복할 횟수입니다. 예를 들어, 1을 지정하면 각 레코드를 한 번만 읽어옵니다. None을 지정하면 영구적으로 계속 반복됩니다.

다음은 Dataset API를 사용하여 이 함수를 구현하는 방법입니다. 이후에 Estimator 모델을 피드할 때 적합한 '입력 함수'에 이 함수를 래핑합니다.
def my_input_fn(file_path, perform_shuffle=False, repeat_count=1):
   def decode_csv(line):
       parsed_line = tf.decode_csv(line, [[0.], [0.], [0.], [0.], [0]])
       label = parsed_line[-1:] # Last element is the label
       del parsed_line[-1] # Delete last element
       features = parsed_line # Everything (but last element) are the features
       d = dict(zip(feature_names, features)), label
       return d

   dataset = (tf.contrib.data.TextLineDataset(file_path) # Read text file
       .skip(1) # Skip header row
       .map(decode_csv)) # Transform each elem by applying decode_csv fn
   if perform_shuffle:
       # Randomizes input using a window of 256 elements (read into memory)
       dataset = dataset.shuffle(buffer_size=256)
   dataset = dataset.repeat(repeat_count) # Repeats dataset this # times
   dataset = dataset.batch(32)  # Batch size to use
   iterator = dataset.make_one_shot_iterator()
   batch_features, batch_labels = iterator.get_next()
   return batch_features, batch_labels

다음 사항을 참고하세요.
  • TextLineDataset: Dataset API는 파일 기반 데이터세트를 사용할 경우 많은 메모리 관리 작업을 자동으로 수행합니다. 예를 들어, 메모리보다 훨씬 큰 데이터세트 파일을 읽어오거나 목록을 인수로 지정하여 여러 파일을 읽어올 수 있습니다.
  • shuffle: buffer_size 레코드를 읽은 후 순서를 셔플(무작위 배정)합니다.
  • map: 데이터세트의 각 요소를 인수로 삼아 decode_csv 함수를 호출합니다(TextLineDataset를 사용하므로 각 요소가 CSV 텍스트의 한 줄이 됨). 그런 다음, 각 줄에 decode_csv 를 적용합니다.
  • decode_csv: 각 줄을 필드로 분할하고 필요한 경우 기본값을 제공합니다. 그런 다음, 필드 키 및 필드 값과 함께 dict를 반환합니다. 그러면 map 함수가 dict를 사용하여 데이터세트의 각 elem(줄)을 업데이트합니다.

지금까지 Datasets를 소개해 드렸습니다. 이제 재미 삼아 이 함수를 사용하여 첫 번째 배치를 인쇄 출력해 볼 수 있습니다.
next_batch = my_input_fn(FILE, True) # Will return 32 random elements

# Now let's try it out, retrieving and printing one batch of data.
# Although this code looks strange, you don't need to understand
# the details.
with tf.Session() as sess:
    first_batch = sess.run(next_batch)
print(first_batch)

# Output
({'SepalLength': array([ 5.4000001, ...<repeat to 32 elems>], dtype=float32),
  'PetalWidth': array([ 0.40000001, ...<repeat to 32 elems>], dtype=float32),
  ...
 },
 [array([[2], ...<repeat to 32 elems>], dtype=int32) # Labels
)

실제로 모델 구현을 위해 Dataset API에서 필요한 건 이게 전부입니다. 하지만 Datasets에는 많은 기능이 있습니다. 이 게시물의 끝부분에 추가 리소스를 모아 두었으므로 확인해 보세요.


Estimators 소개

Estimators는 이전에 TensorFlow 모델을 훈련시킬 때 작성해야 했던 상용구 코드를 상당히 줄여주는 상위 수준 API입니다. Estimators는 유연성도 매우 뛰어나므로, 이를 통해 모델에 특정한 요구 사항이 있을 경우 기본 동작을 재정의할 수 있습니다.

Estimators를 사용하여 모델을 빌드할 수 있는 방법으로는 다음 두 가지가 있습니다.
  • 미리 만든 Estimators - 미리 정의된 Estimators로, 특정 유형의 모델을 생성하려고 만든 것입니다. 이 블로그 게시물에서는 미리 만든 Estimators로서 DNNClassifier라는 것을 사용하겠습니다.
  • Estimator(기본 클래스) - model_fn 함수를 사용하여 모델 생성 방법을 완벽히 제어할 수 있습니다. 이 작업을 수행하는 방법은 별도의 블로그 게시물에서 설명해드릴 예정입니다.

다음은 Estimators의 클래스 다이어그램입니다.

향후 릴리스에서는 미리 정의된 Estimators를 더 많이 추가하려고 합니다.

여러분도 아실 수 있겠지만, 모든 Estimators가 Estimators에 입력 데이터를 제공하는 input_fn을 사용합니다. 여기서는 이런 목적으로 정의한 my_input_fn을 재사용하도록 하겠습니다.

다음은 붓꽃 종류를 예측하는 Estimator를 인스턴스화하는 코드입니다.
# Create the feature_columns, which specifies the input to our model.
# All our input features are numeric, so use numeric_column for each one.
feature_columns = [tf.feature_column.numeric_column(k) for k in feature_names]

# Create a deep neural network regression classifier.
# Use the DNNClassifier pre-made estimator
classifier = tf.estimator.DNNClassifier(
   feature_columns=feature_columns, # The input features to our model
   hidden_units=[10, 10], # Two layers, each with 10 neurons
   n_classes=3,
   model_dir=PATH) # Path to where checkpoints etc are stored

이제 훈련을 시작할 수 있는 Estimator가 생성되었습니다.


모델 훈련

다음과 같이 TensorFlow 코드 한 줄로 훈련을 수행할 수 있습니다.
# Train our model, use the previously function my_input_fn
# Input to training is a file with training example
# Stop training after 8 iterations of train data (epochs)
classifier.train(
   input_fn=lambda: my_input_fn(FILE_TRAIN, True, 8))

여기서 잠깐, 위의 "lambda: my_input_fn(FILE_TRAIN, True, 8)"은 도대체 무엇일까요? 바로 Datasets를 Estimators와 연결한 부분입니다! Estimators가 훈련, 평가 및 예측 작업을 수행하려면 데이터가 필요하며, input_fn을 사용하여 데이터를 가져옵니다. Estimators는 인수 없이 input_fn만 필요로 하므로, lambda를 사용하여 인수 없이 함수를 생성합니다. 이는 원하는 인수 file_path, shuffle setting,repeat_count를 사용하여 input_fn을 호출합니다. 여기서는 my_input_fn,을 사용하여 이를 전달합니다.
  • FILE_TRAIN - 훈련 데이터 파일입니다.
  • True - Estimators에 데이터를 셔플하도록 지시합니다.
  • 8 - Estimators에 데이터세트를 8회 반복하도록 지시합니다.

훈련된 모델 평가

좋습니다. 이제 훈련된 모델이 생성되었습니다. 이 모델이 얼마나 잘 작동하는지 어떻게 평가할 수 있을까요? 다행히도, 모든 Estimator에 evaluate 메서드가 포함되어 있습니다.
# Evaluate our model using the examples contained in FILE_TEST
# Return value will contain evaluation_metrics such as: loss & average_loss
evaluate_result = estimator.evaluate(
   input_fn=lambda: my_input_fn(FILE_TEST, False, 4)
print("Evaluation results")
for key in evaluate_result:
   print("   {}, was: {}".format(key, evaluate_result[key]))

여기서는 약 93%의 정확도를 달성했습니다. 물론, 이 정확도를 높일 수 있는 다양한 방법이 있습니다. 한 가지 방법은 프로그램을 단순히 계속 반복해서 실행하는 것입니다. 모델 상태는 위에서 다룬 model_dir=PATH 내에서 유지되므로 안정화될 때까지 더 많이 반복 훈련할수록 모델이 개선됩니다. 또 다른 방법은 숨겨진 계층의 수나 각각의 숨겨진 계층에 포함된 노드 수를 조정하는 것입니다. 이 방법을 마음대로 실험해 보시기 바랍니다. 단, 변경할 때 model_dir=PATH에 지정된 디렉토리도 제거해야 한다는 점에 유의하세요. DNNClassifier의 구조가 변경되기 때문입니다.

훈련된 모델을 이용한 예측

그게 전부입니다! 이제 훈련된 모델이 있으므로, 평가 결과에 만족한다면 이를 사용하여 몇 가지 입력 값을 기준으로 붓꽃을 예측할 수 있습니다. 훈련 및 평가와 마찬가지로, 단일 함수 호출을 사용하여 예측합니다.
# Predict the type of some Iris flowers.
# Let's predict the examples in FILE_TEST, repeat only once.
predict_results = classifier.predict(
    input_fn=lambda: my_input_fn(FILE_TEST, False, 1))
print("Predictions on test file")
for prediction in predict_results:
   # Will print the predicted class, i.e: 0, 1, or 2 if the prediction
   # is Iris Sentosa, Vericolor, Virginica, respectively.
   print prediction["class_ids"][0] 

메모리 내 데이터를 기반으로 하는 예측

위에 나와 있는 코드에서는 파일에 저장된 데이터를 기반으로 예측을 수행하도록 FILE_TEST를 지정했지만, 다른 소스, 예를 들어 메모리에 있는 데이터를 기반으로 예측하려면 어떻게 해야 할까요? 짐작하실 수 있겠지만, 이를 위해 실제로 predict 호출을 변경할 필요는 없습니다. 대신, 다음과 같이 메모리 구조를 사용하도록 Dataset API를 구성하면 됩니다.
# Let create a memory dataset for prediction.
# We've taken the first 3 examples in FILE_TEST.
prediction_input = [[5.9, 3.0, 4.2, 1.5],  # -> 1, Iris Versicolor
                    [6.9, 3.1, 5.4, 2.1],  # -> 2, Iris Virginica
                    [5.1, 3.3, 1.7, 0.5]]  # -> 0, Iris Sentosa
def new_input_fn():
   def decode(x):
       x = tf.split(x, 4) # Need to split into our 4 features
       # When predicting, we don't need (or have) any labels
       return dict(zip(feature_names, x)) # Then build a dict from them

   # The from_tensor_slices function will use a memory structure as input
   dataset = tf.contrib.data.Dataset.from_tensor_slices(prediction_input)
   dataset = dataset.map(decode)
   iterator = dataset.make_one_shot_iterator()
   next_feature_batch = iterator.get_next()
   return next_feature_batch, None # In prediction, we have no labels

# Predict all our prediction_input
predict_results = classifier.predict(input_fn=new_input_fn)

# Print results
print("Predictions on memory data")
for idx, prediction in enumerate(predict_results):
   type = prediction["class_ids"][0] # Get the predicted class (index)
   if type == 0:
       print("I think: {}, is Iris Sentosa".format(prediction_input[idx]))
   elif type == 1:
       print("I think: {}, is Iris Versicolor".format(prediction_input[idx]))
   else:
       print("I think: {}, is Iris Virginica".format(prediction_input[idx])

Dataset.from_tensor_slides()는 메모리에 적합한 작은 데이터세트용으로 설계되었습니다. 훈련 및 평가를 위해 그랬듯이 TextLineDataset를 사용하는 경우 메모리가 셔플 버퍼와 배치 크기를 감당할 수 있는 한 원하는 만큼 큰 파일을 사용할 수 있습니다.

덤으로 주어지는 이점

DNNClassifier와 같이 미리 만든 Estimator를 사용하면 많은 이점을 누릴 수 있습니다. 미리 만든 Estimators는 사용하기 쉬울 뿐 아니라 기본 제공 평가 측정항목도 제공하고, TensorBoard에서 확인할 수 있는 요약 정보도 생성합니다. 이러한 보고 내용을 보려면 다음과 같이 명령줄에서 TensorBoard를 시작하세요.
# Replace PATH with the actual path passed as model_dir argument when the
# DNNRegressor estimator was created.
tensorboard --logdir=PATH 

다음 다이어그램에 TensorBoard에서 제공하는 일부 데이터가 나와 있습니다.


요약

이 블로그 게시물에서는 Datasets와 Estimators에 대해 살펴봤습니다. 이들은 입력 데이터 스트림을 정의하고 모델을 만들기 위한 중요한 API이므로 시간을 투자하여 배워둘 만한 가치가 분명히 있습니다!

자세한 내용을 보려면 다음을 확인하시기 바랍니다.

하지만 이게 끝이 아닙니다. 곧 이러한 API의 작동 방식을 설명하는 글을 추가로 게시할 예정이오니 계속 관심을 가지고 지켜봐 주세요!

그때까지 TensorFlow 코딩을 즐기시기 바랍니다!


ARCore는 자바/OpenGL, Unity 및 Unreal과 연동되며 다음 세 가지 사항에 중점을 둡니다.

ARCore와 더불어, 우리는 개발자들이 뛰어난 AR 환경을 구축하는 데 더 많은 지원을 제공할 앱과 서비스에도 투자하고 있습니다. 우리는 BlocksTilt Brush를 빌드하여 누구나 쉽게 AR 앱에 사용할 수 있는 뛰어난 3D 콘텐츠를 신속하게 만들 수 있도록 했습니다. I/O에서 언급한 것처럼, 우리는 단순히 개발 플랫폼 상에서 이루어지는 환경을 훨씬 뛰어넘어 실제 생활 환경에서 AR을 경험할 수 있도록 해주는 서비스인 VPS(가상 위치 지정 서비스)에 대한 작업도 수행하고 있습니다. 또한, 웹이 AR의 미래에 중요한 구성요소가 될 것으로 생각하여 웹 개발자를 위한 프로토타입 브라우저도 출시할 예정입니다. 따라서 웹 개발자도 AR 관련 실험을 시작할 수 있습니다. 개발자는 이러한 맞춤형 브라우저를 사용해 AR로 향상된 웹사이트를 만들어 안드로이드/ARCore 및 iOS/ARKit에서 실행할 수 있습니다.

ARCore는 Google이 AR을 모든 사람에게 제공하기 위해 내딛는 다음 발걸음이며, 올해 말에 더 많은 정보를 공유하겠습니다. 의견이 있으시면 GitHub를 통해 알려주시고 새롭게 선보이는 AR 실험 쇼케이스에서 무엇이 가능한지 보여 주는 몇 가지 재미있는 예시들을 확인해 보시기 바랍니다. 직접 빌드한 AR 제작물이 있으시면 소셜 미디어에 #ARCore를 해시태그로 사용하여 올려주세요. 그중에 훌륭한 것을 골라 다시 공유하도록 하겠습니다.
Share on Twitter Share on Facebook



1. 구글의 최신 기술을 사용한 프로젝트 전시

Google HackFair 2017에서 구글의 최신 기술을 우리의 실생활에서 직접 사용할 수 있도록 적용한 다양한 프로젝트들을 경험해 보세요. 사용된 기술 목록 및 간단한 프로젝트 소개는 아래를 확인해 주시기 바랍니다.


2. 국내 최대 규모의 메이커 페어 서울과의 콜라보

직접 만든 프로젝트를 서로 공개하고 체험해볼 수 있는 국내 최대의 메이커 축제 메이커 페어 서울 2017과 함께 합니다. Google HackFair 전시팀 뿐만 아니라 약 100개 팀이 직접 만든 흥미로운 프로젝트를 한 곳에서 체험해 보시기 바랍니다. (Maker Faire Seoul 2017 입장을 위해 관람료가 발생됩니다. ▶자세한 내용 보기)


페이스북 게시글 공유 이벤트!

GDG Korea 페이스북의 을 여러분의 타임라인에 공유해 주세요. 총 20분을 선정해 Google HackFair 2017 초대권을 2매씩 발송해 드립니다.
Share on Twitter Share on Facebook


[소개글]

Google Play는 한국의 인디 게임 개발자 여러분들이 열정과 창의력으로 제작한 게임을 한국뿐 아니라 전세계 플레이어 및 업계 전문가들에게 널리 알리고, 나아가 비즈니스의 성공을 지원하기 위해 이번 대회를 개최하게 되었습니다.

오는 10월21일(토), Indie Games Festival 2018의 성공적인 참여를 위한 인디 게임 개발사 대상 킥오프 이벤트 겸 대회 설명회를 개최하오니, 아래 웹사이트를 통해 참가신청도 하시고 Indie Games Festival 2018의 일정을 확인해 보시기 바랍니다.


킥오프 이벤트 참가신청 / Indie Games Festival 2018 상세 보기

[주요 일정]

  • 2017년
    • 10월 21일: 킥오프 이벤트 개최 (자세한 사항은 여기를 참조)
  • 2018년
    • 2월 1일: 게임 참가 접수 시작. 상품, 심사위원, 파이널 이벤트 개최 일정 및 장소 등 발표. 일반 참가자 접수 시작
    • 3월 25일: 게임 참가 접수 마감
    • 4월초: Top 20 파이널 리스트 발표
    • 4월 21일: Indie Games Festival 2018 파이널 이벤트 개최
* 상기 일정은 변경될 수 있습니다.
* 상세 참가 자격조건 / 수상자에게 주어지는 다양한 혜택 / 결승행사 관람 및 세부 진행과정은 홈페이지를 통해 확인해 주시기 바라며, 인디 게임 개발사들의 많은 관심과 참여 바랍니다.
Share on Twitter Share on Facebook

  • 앱에 두세 개의 개별 기능이 있는 경우 여러 앱 런처를 사용합니다. 예를 들어, 앱이 다양한 옵션, 작업 및 뷰를 포함한 활동 추적과 추적된 활동에 대한 기간별 분석 및 관리를 모두 지원하는 경우, 이러한 작업을 처리하는 데 여러 앱 런처를 사용할 수 있습니다. 또한, 앱에 단순한 홈 화면이 있는 경우 이러한 기능을 홈 화면 맨 아래에 일렬로 배치할 수 있습니다.
  • 작업 창 맨 위에 피킹을 사용하여 기본 작업에 신속하게 액세스할 수 있도록 합니다. 뷰와 연결된 기본 작업이 없는 경우 기본 동작을 재정의하고 그 대신에 오버플로 버튼 피킹을 강제 적용하여 오버플로 버튼을 탭할 때 뷰 맨 아래에 모든 작업이 노출되도록 합니다.

  • 안드로이드 웨어 2.0을 사용하는 기기의 경우, 앱이 이러한 새로운 UI 패턴을 활용하여 일관된 사용자 환경을 제공하도록 하세요. 안드로이드 웨어 탐색 및 작업에 대한 추가 교육 리소스와 탐색작업 창에 대한 머티리얼 디자인 사양을 확인해 보세요.

    알림

    안드로이드 웨어 2.0에서는 알림 작업을 표시하는 데 가로 스와이프 동작을 사용하지 않고 더욱 단순한 세로 탐색 패턴을 사용합니다. 알림 작업은 이제 알림 맨 아래에 단일 기본 작업(해당하는 경우)으로 표시됩니다. 기본 작업이 없는 경우 알림을 확장하면 세로로 스크롤 가능한 단일 뷰에 옵션이 표시됩니다.

    알림은 1.x 및 2.0 기기에서 모두 많은 내용을 변경할 필요 없이 제대로 작동하지만, 표시되는 형태는 꽤 다릅니다.

    안드로이드 웨어 2.0 기기용 앱을 만들 때 다음 모범 사례를 적용하여 알림과 관련한 사용자 환경을 개선해보세요.
    1. 확장 가능한 알림 지원: BigTextStyle을 사용하면 사용자가 시계에서 더 많은 콘텐츠를 볼 수 있습니다.
    2. 축소된 형태의 알림 뷰 사용(해당하는 경우): 해당하는 경우 setContentIntent()를 사용하여 알림에 대한 기본 작업을 축소된 형태의 알림 뷰에 추가합니다.
    3. 메시지 앱의 경우 MessagingStyle 사용: 이 스타일을 사용하면 확장된 알림에서 기능이 풍부한 채팅 앱과 같은 환경을 제공할 수 있습니다.
    4. 안드로이드 웨어 1.0과 관련한 사용자 지침 업데이트: 사용자가 가로로 스와이프하여 카드 작업을 수행하도록 지시하는 텍스트를 모두 제거합니다(안드로이드 웨어 1.x 패턴).
    5. 인라인 작업을 사용하도록 알림 개선: 이 작업을 구현하면 사용자가 탭할 필요 없이 확장된 알림 세부 사항을 볼 수 있게 됩니다. 메시지 알림에 대한 작업은 스마트 회신 사전 설정, 음성 및 키보드 입력을 포함하여 여러 다양한 입력 방법을 사용할 수 있습니다. 이러한 기능을 활용하여 추가 기능을 제공하고 사용자에게 쾌적한 사용 환경을 제공해 보세요.

    웨어러블 기능을 알림에 추가하는 방법에 대한 자세한 내용을 확인해 보시기 바랍니다.

    정보 표시

    안드로이드 웨어 2.0의 Complications API는 시계 모드 개발자 및 타사 데이터 제공자가 사용자가 원하는 중요한 정보를 한눈에 파악할 수 있도록 제공하기 더욱 쉽게 해줍니다. 이 API를 지원하는 시계 모드는 시계에 설치된 데이터 제공자를 임의로 사용하도록 구성하는 동시에 그 모습을 계속 완벽하게 제어할 수 있습니다. Complication API를 지원하는 앱을 통해 정보 표시를 지원하는 모든 시계 모드에서 앱의 데이터에 액세스할 수 있습니다. 이러한 정보 표시는 데이터 제공자가 구성한 내용과 시계 모드에 할당된 공간의 양에 따라 다양한 형태(짧은 텍스트, 아이콘, 범위 지정 값, 긴 텍스트, 작은 이미지 및 큰 이미지)로 구현될 수 있습니다.

    정보 표시가 시계 모드의 전체 디자인에 적합하고 해당 데이터 형식을 제대로 처리하도록 하려면 정보 표시 지원 기능을 추가할 때 시계 모드 작성자가 다음을 수행하는 것이 좋습니다.
    1. 안드로이드 웨어 2.0 SDK에서 제공되는 TextRenderer 클래스를 사용합니다. 이 클래스는 텍스트를 축소하거나, 줄바꿈을 동적으로 지원하거나, 문자열이 텍스트 기반 정보 표시의 경계를 벗어날 때 문자열에 줄임표를 추가하여 줄이는 방법으로 정보 표시 내 텍스트가 경계에 맞게 조정되도록 합니다.
    2. ComplicationDrawable 클래스를 사용하여 정보 표시를 위한 배경 색상, 모양, 테두리 및 글꼴 옵션을 설정합니다. 이 클래스를 사용해 정보 표시가 시계 모드에 대해 렌더링되는 방식을 완벽히 제어할 수 있습니다.
    3. 사용자가 설정 메뉴를 통해 시계 모드에서 정보 표시를 구성하거나 조정할 수 있는 방법을 제공하도록 시계 모드를 디자인합니다. 이러한 설정을 생성하는 자세한 방법은 GitHub에 있는 시계 모드 샘플을 참조하세요.
    4. 데이터 제공자 테스트 모음 앱을 사용하여 더미 데이터를 시계 모드 정보 표시 기능에 피드합니다. 그러면 모든 정보 표시가 제대로 렌더링되고 해당 글꼴이 경계에 맞게 서식 지정되어 있는지 확인할 수 있습니다.
    5. 정보 표시 데이터 제공자로서, ComplicationProviderService를 사용하여 관련 데이터를 노출합니다. 앱이 정보 표시를 위해 제공할 수 있는 ComplicationData의 유형을 간단히 정의하고 구성하기만 하면 됩니다.

    안드로이드 웨어 기기의 독립 실행형 기능

    1. 앱이 android.hardware.type.watch 하드웨어 기능 플래그를 사용할 때 도우미 앱이 설치되어 있지 않은 경우 자체적으로 처리 가능하도록 합니다. 이 기능을 사용하면 도우미 휴대폰 앱을 설치할 필요 없이 안드로이드 웨어 기기에서 바로 앱을 검색하고 설치할 수 있게 됩니다. 따라서 앱이 혼동을 주거나 부실한 사용자 환경을 제공하지 않도록 자체적으로 처리 가능하도록 해야 합니다.
    2. 웨어러블 앱이 로그인/인증 또는 기본 기능을 제공하는 데 휴대폰 앱에 의존하지 않도록 합니다. 웨어러블 앱에서 인증을 위해 복잡한 입력(예: 비밀번호 입력)을 요구할 때 도우미 휴대폰을 이용하도록 가리킬 수 있지만, 앱보다는 계정/비밀번호 입력을 위한 웹 UI를 사용해야 합니다.
    3. 도우미 앱이 몇몇 다른 이유로 앱을 지원하기 위해 휴대폰에서 제공되어야 하는 경우 앱은 CapabilityApi를 사용해야 합니다. 누락된 앱을 설치하도록 도우미 기기에서 사용자를 Play Store 목록 페이지로 올바로 안내하기 위해 이를 사용해야 합니다. 그렇지 않은 경우, 이 앱은 안드로이드 웨어에 내장된 Wi-Fi, GPS 또는 기타 연결 기능을 사용하여 자체적으로 작동해야 합니다.
    4. Play Store 목록 설명 내에 도우미 앱 요구 사항과 관련한 문구를 포함하거나 안드로이드 웨어 앱이 작동해야 하는 방식을 간단히 설명합니다. 그러면 기대치를 정하고 사용자에게 가능한 한 최상의 환경을 이용할 수 있도록 올바른 앱 설치를 안내하는 데 도움이 됩니다.
    5. 웨어러블 앱이 어떠한 휴대폰 도우미 상호작용 없이도 작동할 수 있는 경우 com.google.android.wearable.standalone 플래그를 매니페스트에 포함합니다. 이 플래그는 웨어러블 앱이 설치 가능하며 Android 또는 iOS 도우미 휴대폰에 페어링되지 않은 경우에도 완벽하게 작동함을 나타냅니다.

    여기서 많은 사항을 다루었지만 앱 또는 게임이 최적화되어 있고 안드로이드 웨어에서 최신 패턴 및 기능을 사용하는지 확인하는 데 참고할 수 있는 추가 자료가 있습니다. 안드로이드 웨어용으로 뛰어난 앱을 빌드하려면 품질 가이드라인을 검토하고 개발자 교육 문서를 확인하여 웨어러블 앱 개발웨어러블 앱 디자인 관련 모범 사례를 자세히 살펴보세요.
    Share on Twitter Share on Facebook

    Fast Fetch는 Delayed Fetch에 비해 50 백분위수에서 850밀리초 더 빠르고 90 백분위수에서는 2.7초 더 빠릅니다.

    AMP 광고에 대한 협업적 렌더링 

    광고 응답이 AMP 형식(AMP 광고)이면 AMP 런타임이 광고를 즉시 렌더링합니다. 응답이 일반 광고인 경우 페이지에서 나머지 콘텐츠가 로드될 때까지 런타임이 대기해야 합니다. 이는 AMP 광고 성능을 자신할 수 있게에 가능한 방식입니다. 그러나 비 AMP 광고에서는 그런 보장이 없습니다.


    AMP 광고는 DoubleClick 및 AdSense 시험을 기반으로 50 백분위수에서 최대 1.6초, 90 백분위수에서 최대 5초 더 빠르게 로드됩니다.

    광고가 화면에 더 빠르게 나타날수록 광고의 노출도가 더 높아집니다. 이는 브랜드를 더욱 폭넓은 잠재고객에게 노출시켜 주므로 브랜드 광고주에게 유리합니다. 노출도가 더욱 높아지면 사용자가 광고와 상호작용할 가능성도 증가하게 되므로 실적을 중시하는 광고주에게도 이익이 됩니다.

    Fast Fetch를 위한 새로운 기능 출시 

    다수의 게시자는 자신의 운영 웹사이트에 콘텐츠를 제공하는 데 사용할 형식으로 AMP를 실험 중입니다. 이러한 작업을 수행하는 게시자를 지원하기 위해 Fast Fetch에서는 향후 AMP에 다음과 같은 고급 광고 기능을 추가로 제공할 예정입니다.

    게시자(또는 광고주)인 경우: 

    DoubleClick 및 AdSense 덕분에 AMP 페이지에서 광고 요청이 발생할 때 적합한 광고가 AMP로 자동 변환됩니다. 더 많은 형식을 AMP로 변환할 수 있게 됨에 따라 이러한 광고 물량이 늘어날 것으로 기대할 수 있으며, 결과적으로 어떠한 변경 작업도 수행할 필요 없이 페이지에 제공되는 광고의 노출도와 클릭률이 더 높아지는 이점을 누릴 수 있습니다.


    광고를 개발하는 광고주(또는 게시자)인 경우: 

    (게시자든 광고주든 상관없이) 광고를 개발하는 경우 AMP 광고로 전환하여 높은 노출도와 뛰어난 사용자 환경을 갖춘 더욱 신속한 광고의 이점을 누리시기 바랍니다. 먼저, 사내 광고 개발자에게 이 AMP 광고 개발자 FAQ를 살펴보도록 하세요.

    광고 자산의 개발 작업을 아웃소싱하는 경우 AMP 광고 제작을 전문으로 하는 JoyStick Interactive와 같은 업체를 이용할 수 있습니다. 광고 개발 도구를 사용하여 자산을 빌드하는 데 익숙하다면, Celtra의 광고 제작 프로그램을 이용하여 AMP 광고를 제작해 보시기 바랍니다. Google Web Designer와 같은 다른 도구를 위한 AMP 광고 지원도 곧 제공할 예정입니다.

    광고 기술 플랫폼인 경우: 

    DoubleClick 및 Adsense 광고 태그는 Fast Fetch를 사용하며 지연 시간을 대폭 단축하는 효과를 보고 있습니다. 모든 광고 네트워크가 Fast Fetch로 전환하기를 기대합니다. 자세한 내용은 가이드를 참조하시기 바랍니다. AMP 광고 서명의 경우, Cloudflare와 협력하여 Cloudflare에서 제공하는 Firebolt 서비스를 사용할 수 있습니다. 또는 AMP 광고를 직접 서명하고 싶다면 Github에서 제공하는 콘텐츠를 참조하시기 바랍니다.

    Cloudflare의 제품 전략 책임자인 Dane Knecht 씨는 "Cloudflare Firebolt는 광고 네트워크가 추가로 개발해야 할 작업이 거의 없이 전역적으로 광고에 서명하고 쉽게 광고를 제공할 수 있게 해줍니다. 우리의 사명인 더 나은 인터넷 환경의 빌드에 도움을 드리기 위한 노력의 일환으로, Firebolt는 글로벌 AMP 광고 환경을 더욱 향상시켜 광고 환경을 더욱 신속하고 안전하게 만들고 결과적으로 더 나은 전환율을 실현합니다"라고 말합니다.

    AMP 광고는 이제 DoubleClick Ad Exchange에서도 지원되며(Real Time Bidding을 통해), DSP는 RTB를 통한 AMP 광고 제공을 지원하는 작업을 시작할 수 있습니다.

    우리는 AMP 광고 부문에서 먼 여정을 거쳐왔으며, 이제 제3단계를 앞두고 큰 기대에 부풀어 있습니다. 여기에는 다음 작업이 포함됩니다.

    늘 그렇듯이, 함께 더 나은 웹 환경을 구축할 수 있도록 위 사항과 관련하여 좋은 의견이나 이를 구현할 기회가 있으시면 꼭 알려주시기 바랍니다.
    Share on Twitter Share on Facebook