2016年7月6日水曜日

Microsoft Translatorを利用した日本語→英語翻訳サンプルプログラム

Microsoft Translatorを使う準備
1.Microsoftアカウントを作成します。これはMicrosoft Azure Marketplaceにサインインするために必要になります。
2.Microsoft Azure Marketplace(以下のURL)でサブスクリプション登録を行います。2,000,000文字/月までのデータであれば無償で使えます。
https://datamarket.azure.com/dataset/1899a118-d202-492c-aa16-ba21c33c06cb
3.以下のページからアプリケーションを登録し、「クライアントID」と「顧客の秘密」を取得します。アプリケーションは未作成で問題ありません。
https://datamarket.azure.com/developer/applications/

サンプルプログラムは以下になります。なお、CallMSTranslatorクラスのfromLangとtoLang変数を変更することで、別の言語間の翻訳が可能です。
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Web;
using System.Runtime.Serialization.Json;

namespace MSTranslatorApp
{
    class Program
    {
        //MS Translationへの接続情報
        // clientIdには、事前に登録した「クライアントID」を設定
        // clientSecretには、事前に登録した「顧客の秘密」を設定
        private const string CLIENTID = "<クライアントID>";
        private const string CLIENTSECRET = "<顧客の秘密>";

        static void Main(string[] args)
        {
            // 翻訳前のテキストをコマンドライン引数から取得
            string originalText = args[0];

            CallMSTranslator callMSTranslator = new CallMSTranslator(CLIENTID, CLIENTSECRET);

            // 翻訳語のテキストを取得
            string translatedText = callMSTranslator.TranslateMethod(originalText);

            Console.WriteLine("元のテキスト:" + originalText);
            Console.WriteLine("翻訳テキスト:" + translatedText);
            Console.WriteLine();
            Console.WriteLine("何かキーを押してください...");
            Console.ReadKey();
        }
    }

    class CallMSTranslator
    {
        private string authToken;
        private string clientId;
        private string clientSecret;
        private string baseUrl = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=";

        private string fromLang = "ja";
        private string toLang = "en";
        private string translatedText;

        public CallMSTranslator(string clientId, string clientSecret)
        {
            // Microsoft Translator APIを呼び出す準備
            this.clientId = clientId;
            this.clientSecret = clientSecret;

            AdmAuthentication admAuth = new AdmAuthentication(clientId, clientSecret);
            AdmAccessToken admToken = admAuth.GetAccessToken();
            authToken = "Bearer " + admToken.access_token;
        }

        public string TranslateMethod(string originalText)
        {
            // Microsoft Translator APIを呼び出して、日本語→英語の翻訳を実行
            string uri = baseUrl + System.Web.HttpUtility.UrlEncode(originalText) + "&from=" + fromLang + "&to=" + toLang;
            HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
            httpWebRequest.Headers.Add("Authorization", authToken);
            WebResponse response = null;

            try
            {
                response = httpWebRequest.GetResponse();
                using (Stream stream = response.GetResponseStream())
                {
                    System.Runtime.Serialization.DataContractSerializer dcs = new System.Runtime.Serialization.DataContractSerializer(Type.GetType("System.String"));
                    translatedText = (string)dcs.ReadObject(stream);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                    response = null;
                }
            }

            return translatedText;
        }
    }

    public class AdmAccessToken
    {
        public string access_token { get; set; }
        public string token_type { get; set; }
        public string expires_in { get; set; }
        public string scope { get; set; }
    }

    public class AdmAuthentication
    {
        private static readonly string DatamarketAccessUri = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13";
        private string clientId;
        private string clientSecret;
        private string request;
        private AdmAccessToken token;
        private Timer accessTokenRenewer;

        // アクセストークンの再生成間隔(アクセストークンは10分で失効する)
        private const int RefreshTokenDuration = 9;

        public AdmAuthentication(string clientId, string clientSecret)
        {
            this.clientId = clientId;
            this.clientSecret = clientSecret;

            // クライアントIDと顧客の秘密をエンコード
            this.request = string.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=http://api.microsofttranslator.com", HttpUtility.UrlEncode(clientId), HttpUtility.UrlEncode(clientSecret));
            this.token = HttpPost(DatamarketAccessUri, this.request);

            // アクセストークンの再生成
            accessTokenRenewer = new Timer(new TimerCallback(OnTokenExpiredCallback), this, TimeSpan.FromMinutes(RefreshTokenDuration), TimeSpan.FromMilliseconds(-1));
        }

        public AdmAccessToken GetAccessToken()
        {
            return this.token;
        }

        public void RenewAccessToken()
        {
            AdmAccessToken newAccessToken = HttpPost(DatamarketAccessUri, this.request);

            //アクセストークンの入れ替え
            this.token = newAccessToken;
            Console.WriteLine(string.Format("Renewed token for user: {0} is: {1}", this.clientId, this.token.access_token));
        }

        public void OnTokenExpiredCallback(object stateInfo)
        {
            try
            {
                RenewAccessToken();
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("Failed renewing access token. Details: {0}", ex.Message));
            }
            finally
            {
                try
                {
                    accessTokenRenewer.Change(TimeSpan.FromMinutes(RefreshTokenDuration), TimeSpan.FromMilliseconds(-1));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(string.Format("Failed to reschedule the timer to renew access token. Details: {0}", ex.Message));
                }
            }
        }
        public AdmAccessToken HttpPost(string DatamarketAccessUri, string requestDetails)
        {
            // OAuthリクエストの準備 
            WebRequest webRequest = WebRequest.Create(DatamarketAccessUri);
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.Method = "POST";
            byte[] bytes = Encoding.ASCII.GetBytes(requestDetails);
            webRequest.ContentLength = bytes.Length;

            using (Stream outputStream = webRequest.GetRequestStream())
            {
                outputStream.Write(bytes, 0, bytes.Length);
            }

            using (WebResponse webResponse = webRequest.GetResponse())
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AdmAccessToken));
                AdmAccessToken token = (AdmAccessToken)serializer.ReadObject(webResponse.GetResponseStream());
                return token;
            }
        }
    }
}

2016年7月4日月曜日

Polybaseを使用して、Blob StorageからSQL DWへCSVファイル形式のデータをロードする方法

Polybaseを使用して、Blob Storageに格納されているCSVファイル形式のデータをSQL DWにロードする手順です。
基本は以下のドキュメントに従って実行しています。
https://azure.microsoft.com/ja-jp/documentation/articles/sql-data-warehouse-load-from-azure-blob-storage-with-polybase/

なお、今回の手順ではファイル名は「simple_benchmark.csv」、データ形式は「TestId, TextNumber」で、ともに整数データとしています。
また、CSVファイルはストレージアカウント「testdatastorage」、コンテナ「testdata」に格納しています。

1.資格情報を作成
CREATE MASTER KEY;

CREATE DATABASE SCOPED CREDENTIAL AzureStorageCredential
  WITH
    IDENTITY = 'testdatastorage',
    SECRET = '<アクセスキー>';

2.外部データソースの作成
CREATE EXTERNAL DATA SOURCE AzureExtStorage
  WITH (
    TYPE = HADOOP,
    LOCATION = 'wasbs://testdata@testdatastorage.blob.core.windows.net',
    CREDENTIAL = AzureStorageCredential
  );

3.データ形式の構成
CREATE EXTERNAL FILE FORMAT CSVFileFormat
  WITH (
    FORMAT_TYPE = DELIMITEDTEXT,
    FORMAT_OPTIONS (
      FIELD_TERMINATOR = ','
    )
  );

4.データベースのスキーマを作成
CREATE SCHEMA [tst];

5.外部テーブルを作成
CREATE EXTERNAL TABLE [tst].[SimbleExtTab1] 
  (
    [TestId] [int] NOT NULL,
    [TestNumber] [int] NULL
  )
  WITH (
    LOCATION = '/simple_benchmark.csv',
    DATA_SOURCE = AzureExtStorage,
    FILE_FORMAT = CSVFileFormat
  );

6.データをSQL DWにロード
CREATE TABLE [tst].[SimpleTab1]
  WITH (
    DISTRIBUTION = HASH([TestId])
  )
  AS
    SELECT * FROM [tst].[SimbleExtTab1];

7.列ストア圧縮の最適化
ALTER INDEX ALL ON [tst].[SimpleTab1] REBUILD;

8.統計の最適化
CREATE STATISTICS [stat_tst_SimpleTab1_TestId] ON [tst].[SimpleTab1]([TestId]);
CREATE STATISTICS [stat_tst_SimpleTab1_TestNumber] ON [tst].[SimpleTab1]([TestNumber]);