2014年7月24日木曜日

留学終了。そして、次のステップへ

6月末で授業が終わり、帰国しました。

語学留学も含めると1年2ヶ月、あっという間でした。
そして、TOEFLやGMATなど留学準備にかなり長い時間かかったので、感慨深いです。

留学して、技術的なことはもちろん、コミュニケーションの面でも多くのことを学んだと思います。
そして何より、日本とは違う生活スタイルや社会インフラを受け入れて、その中で生活することで、日本の良いところを感じたり、一方、アメリカ、サンフランシスコの良さを感じたりすることができました。言葉にすると陳腐ですが、世界が身近になったと思います。

サンフランシスコではデータサイエンティストの需要が引き続き大きく、インターネット系のスタートアップだけでなく、大企業も採用を始めています。そして、シリコンバレーのスタートアップの人たちと話をすると、今後もデータサイエンスのマーケットは大きくなると考えているようです。この流れに乗って、データサイエンスをいろいろなところで活かせる仕事をしていきたいと思っています。

留学が終わったので、このブログの更新も止めたいと思います。
読んでくださった方、ありがとうございました。

2014年6月19日木曜日

(備忘) Amazon AWSを使ってのMapReduce -第1章

Elastic Map Reduce(EMR)を使って簡単な集計をしたときのメモ。
使用データは、wikipediaのtraffic を集めたwikistatsデータ。公になっているデータでサイズは150GBです。
(http://aws.amazon.com/datasets/6025882142118545)

結構調べながらやったこともあり、週末かかりました。もう一度はできないので、メモします。


第一章: データの準備


参考URL
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-public-data-sets.html


1) Amazon EBS Snapshotのコピー

正直なんのこっちゃって感じでしたが、どうやらデータは、Amazon Elastic Block Store(EBS)でサポートされており、EBCとは仮想の外付けHDDのようなものだと理解しています。そして、Amazonが公開しているフリーのデータの多くは、EBCに格納されているようです。

1. まず初めにAWSのマネジメントコンソールから、EC2のページに行きます。

2. 右にあるツールバーから「Snapshots」を選び、 wikistatsのsnapshots ID (US Snapshot ID (Linux/Unix):snap-f57dec9a) を表示させます。EBSはRegion(Virgnia、N. Carifornia, Oregon, Tokyoなどなど)によって分かれており、wikistatsデータは、Virgniaにありました。なので、表示されなかったら、RegionがVirgniaになっているか確認します。

3. N.Virgniaから自分の最寄りのRegionにコピーします(「Actions」から「Copy」を選択すると、ポップアップでどこにコピーするか聞いてきます)。

4. コピーし終わったら、Create Volumeします。

5. 続いて、EC2のインスタンスを起動します。EBSは”外付けHDD"なので、バーチャルマシンであるEC2インスタンスからアクセスすることになります。EC2を立ち上げるときに、コピーで作ったSnap ShotのIDを入力すると、インスタンスが起動したときに、認識してくれます。


6. EC2が起動したら、Snapshotをマウントします。SSHでEC2のインスタンスにログインして、以下を実行します(ec2-userでログインしているが、rootで作業したいのでsudo suします)

$sudo su
#mkdir /mnt/wikidata
#mount /dev/xvdf1/ /mnt/wikidata

ここまで準備の準備・・・・続いて、マウントしたデータをS3にデータを移します。


2) EC2からS3へデータの転送


1) EC2にSSHログインして、sudo suしたら、便利ツール「s3cmd」をインストールします。そして、s3cmd --configure でセッティング。 Access Key、Secret Keyを聞かれますので、AWSのマネジメントコンソール右上のログイン名をクリックし、Security Credentialから確認できます。
$sudo su
#yum --enablerepo=epel install s3cmd
#s3cmd --configure
2) そして、S3でバケット(フォルダ)を用意します。作ったバケットにデータをコピーしていきます。というのも、EMRはS3からデータを読み込むので、ここにインプットするデータを置いておきたいわけです。


3)さて、いよいよデータをEC2からS3に転送します。以下のコマンドでいけるはずです。
#cd /your path to wikistats data/
#s3cmd put --recursive /mnt/wikidata/wikistats/ s3://<your bucket>/wikidata/

それにしても、150GB、約2000のgzipファイルをコピーするので、めちゃ時間かかる・・・

これ以外のs3cmdの用法は、こちら(http://s3tools.org/usage)


(おまけ)

転送中にまさか!!・・・途中でエラーが出てファイルの一括アップロードが止まりました。残り961ファイル・・・そこで、残りのファイルのリストを作り、Perlでs3cmd putを呼び出すone linerコードを準備しました。遠い昔にやった、Perl one linerの記憶を便りに検索しまくりました。。。

#まず、残ったファイルのリストをテキストファイルで保存
ls /mnt/wikidata/wikistats/ | cat | tail -n 961 > filelist.txt

#そして、Perl one-linerで残ったファイルを転送
perl -nle '$from = "s3cmd put /mnt/wikidata/wikistats/".$_; $to = " s3://<your bucket>/wikidata/wikistats/".$_; $cmd = $from.$to; system($cmd);' filelist.txt

ちょっとつかれたので、続きは次回!

2014年5月29日木曜日

いよいよ最終モジュール!

いよいよ5月中旬から最終モジュールが始まりました。私の留学生活も残すところ1ヶ月です。
あっという間だったような、長かったような、不思議な感じです。しかし、多くのことを勉強しましたし、何より旅行ではなく、実際に住んで、サンフランシスコのライフスタイルに触れて、アメリカのことや、日本のことについて考えるようになりました。そのことが大きな収穫だと思っています。

さて、最終モジュールのラインナップについて書きたいと思います。

Application of Analytics
シミュレーションのクラスです。モンテカルロシミュレーションに始まり、MCMCなどをやります。わりと数学重視のクラスです。最終モジュールで疲れてきている身体には応えますが、トピックは実用的かつ重要なので、頑張ってついていきます。


Marketing Analytics
マーケティングに纏わる分析手法を勉強します。コンジョイント分析、LTVの求め方など。先生は元ニールセンの方で、統計学的にどうこうというよりは、統計分析の結果をどうビジネスクライアントに説明するかに力点が置かれています。そして、このクラスの特徴は、SASを使用すること。クラス内では、賛否両論ありますが、私個人としては、SASはRと違って有償ですし、まだまだ大手企業で使っているメジャーなソフトウェアで覚えておいて損はないと思っています。

Web Analytics
これが本モジュール一番期待している授業です。自分でウェブサイトを作って、それにGoogle Analytics等の分析ソフトを導入して、実際に分析していくという流れです。先生は、元Googleのエンジニアの方でこれらのツールを熟知しているのはもちろん、とてもナイスガイなので、多くを学びたいと思います。

Practicum
インターンですね。いよいよ最後!!


最終モジュールで、気が抜けそうですが、なかなかのラインナップだと思います。最後まで楽しんで勉強できそうです。



2014年5月1日木曜日

備忘) Hadoop Streaming PythonでJOIN

もう少し調べておりましたら、Hadoop Streaming + Pythonで2つのファイルをJOINする方法を見つけました。参考にしたのは、こちらのブログ。忘れないようにメモしておきます。

  • http://allthingshadoop.com/2011/12/16/simple-hadoop-streaming-tutorial-using-joins-and-keys-with-python/

1. まずはお試し用データを用意

今回は、あるカスタマーデータがあるとして(customerData.csv)、その中にある県のID(Pref_id) を、県の名前テーブル(pref.csv)を参照して、実際の県の名前(pref_name)をカスタマーデータにくっつける、ということを考えています。


customerData.csv
#ID, Name, Pref_id, good or bad id
1, Taro, 1, 0
2, Jiro, 2, 1
3, Saburo, 3, 0
4, Hanako, 1, 0
5, Ken, 3, 1
6, Nick, 2, 1
pref.csv
#Pref_id, Pref_name
1, Tokyo
2, Osaka
3, Hokaido

2. Hadoop hdfsにアップ

そんでもって、この2つのファイルをcustomerというフォルダにアップします。
$hadoop fs -put pref.csv /user/<your username>/customer/customerData.csv
$hadoop fs -put pref.csv /user/<your username>/customer/pref.csv



3. MapperとReducerを用意

参考にしたブログにもあるように、1つのフォルダに格納されている2つのファイルを出力します。

問題は、ある出力があったときに、それが、どちらのファイルから来たものなのかを判別することが必要になります。ここでは、カンマで区切って配列にしたときの長さで判別しています。

また、Mapperから出力される文字列ですが、すべての要素(この例では、共通項目のPref_id、customerData.csvにあるID, Name, good or bad idの3つ + pref.csvにあるPref_nameの合計5つ)、をくっつけて出力します。

その際、該当する要素がない場合は、NAを意味するフラグを立てて出力させるのがポイントのようです。

Mapper.py
#!/usr/bin/python

import sys

# input comes from STDIN (standard input)
for line in sys.stdin:
    line = line.strip()
    line = line.split(",")

    id = "-1"
    name = "-1"
    pref = "-1"
    pref_name = "-1"
    good = "-1"


    #If length of the line is four, the data comes from customerData
    if len(line) ==4:
        id = line[0]
        name = line[1]
        pref = line[2]
        good = line[3]

    else:
        pref = line[0]
        pref_name = line[1]


    print '%s\t%s\t%s\t%s\t%s' % (id, name, pref, pref_name, good)

Reducerですが、ここでは、県名を入れておく辞書と、カスタマー情報を入れておく辞書を用意して、mapperから出てくる文字列を見て、各行を格納しておきます。

reducer.py
#!/usr/bin/python

import sys

pref_dict ={}
customer_dict={}
for line in sys.stdin:
    line = line.strip()
    id, name, pref, pref_name, good = line.split('\t')

    id = int(id)
    pref = int(pref)
    good = int(good)

    #if id ==-1, it means the data comes from Pref data
    if id ==-1:
        pref_dict[pref] = pref_name
    
    #Oterwise, the data comes from customer data
    else:
        customer_dict[id] = [name,pref,good]

for id in customer_dict.keys():
    pref_name = pref_dict[customer_dict[id][1]]
    name = customer_dict[id][0]
    good = customer_dict[id][2]

    print '%s\t%s\t%s\t%s'% (id, name, pref_name, good)


4. テスト

ターミナルでテストしておきます。
$cat customerData.csv pref.csv | python mapper.py | python reducer.py
1  Taro  Tokyo 0
2  Jiro  Osaka 1
3  Saburo  Hokaido 0
4  Hanako  Tokyo 0
5  Ken  Hokaido 1
6  Nick  Osaka 1


5. 権限を変更して、hadoop jarを実行

chmod でmapper.pyとreducer.pyに実行権限を与えておきます(コマンドは、chmod +x mapper.pyもしくはreducer.py)。最後に、hadoop jar streamingです。
$hadoop jar /usr/lib/hadoop-mapreduce/hadoop-streaming.jar -mapper mapper.py -reducer reducer.py -input /user/<your username>/customer/*.csv -output custoer_pref -file mapper.py -file reducer.py

6. 実行結果の確認
$ hadoop fs -cat /user/ykatada/customer_pref/part-00000
1  Taro  Tokyo 0
2  Jiro  Osaka 1
3  Saburo  Hokaido 0
4  Hanako  Tokyo 0
5  Ken  Hokaido 1
6  Nick  Osaka 1



2014年4月30日水曜日

備忘) Pythonで書くMap Reduce on Hadoop


ここ最近の授業でもPythonのMulti processingのモジュールを使って、Mapper, Partitioner, Reducerを組み合わせて、いろいろ集計したり、回帰分析のプログラムを書いたりしています。 徐々にですが、Map Reduceがどういうもので、どこをパラレルに計算させて、集計とるかみたいな勘がわかってきました。


で、今日は、1ヶ月くらい前にHadoopのセットアップをやりましたが、その後ほったらかしていたので、授業で勉強したことを活かすべく(?)、Hadoopの擬似分散モード上で動くPythonのM/Rのプログラムを書いてみようと思います。

参考にしたブログはこちら。


  • http://www.michael-noll.com/tutorials/writing-an-hadoop-mapreduce-program-in-python/
  • http://blog.matthewrathbone.com/2013/11/17/python-map-reduce-on-hadoop---a-beginners-tutorial.html


まず下準備です。


1. 使用するデータを用意する


こちらのデータは、1行目から順に、ID, 性別, 年齢, 身長(インチ), 体重(ポンド), 自分の体重をどう思うか?(1=太っている、2=痩せている、3=普通), 体重を変えようとしているか?(1=太ろうとしている, 2=痩せようとしている, 3 = 維持しようとしている) というデータです(元データはこちら
:ftp://ftp.cdc.gov/pub/Health_Statistics/NCHS/nhanes/nhanes3/1A/adult.dat)。

このデータを、adult_data.csvと呼びます。
'00003', 1, 21, 72, 180, 3, 1
'00004', 2, 32, 63, 135, 1, 2
'00009', 2, 48, 61, 147, 1, 2
'00010', 1, 35, 70, 205, 1, 2
'00011', 1, 48, 67, 170, 3, 3
'00019', 1, 44, 70, 187, 3, 3
'00034', 2, 42, 63, 128, 1, 2
'00040', 2, 17, 60, 100, 3, 3
'00044', 2, 24, 66, 125, 3, 2
'00045', 2, 67, 64, 147, 3, 3
'00048', 2, 56, 68, 231, 1, 2
'00049', 2, 82, 73, 97, 2, 1
'00051', 1, 44, 71, 300, 1, 2


2. 使用するデータをローカルからHDFS上にアップする

#まずは、testフォルダを作ります
$ hadoop fs -mkdir /user/<your username>/test
#そんでもって、putでデータをローカルからHDFS上にコピーします
$ hadoop fs -put adult_data.csv /user/<your username>/test/adult_data.csv

3. PythonでMapperとReducerを書きます

今回は、性別ごとの平均年齢を出してみます。
まずは、Mapperから。

どうやら、Hadoopのstreaming-jarというもので、データを一行ずつPythonのプログラムに標準入力できるようです。なので、テキストとして読み込んだ一行ずつのデータをstripとsplit(",")でパースしています。例えば、最初の行は、以下のような配列になります。

"'00003', 1, 21, 72, 180, 3, 1" ->['00003', "1", "21", "72", "180", "3", "1"]

そして、1つめの要素(性別)と2つめの要素をピックして、標準出力していきます。 Key Valueのペアは、ただのタブ区切りのテキストとして出力されるというわけです。

Mapper.py
#!/usr/bin/python

import sys

# input comes from STDIN (standard input)
for line in sys.stdin:
    line = line.strip()
    line = line.split(",")

    if len(line) >=2:
        sex = line[1]
        age = line[2]

        print '%s\t%s' % (sex, age)

続いて、Reducerです。 Reducer.pyには、PartitionerとReducerがセットになっています。 Mapperから吐き出されるKey Valueペアのテキストをパースして、辞書にValueを格納、最後に集計というのが大雑把な流れです。

Reducer.py
#!/usr/bin/python
#Reducer.py
import sys

sex_age = {}

#Partitoner
for line in sys.stdin:
    line = line.strip()
    sex, age = line.split('\t')

    if sex in sex_age:
        sex_age[sex].append(int(age))
    else:
        sex_age[sex] = []
        sex_age[sex].append(int(age))

#Reducer
for sex in sex_age.keys():
    ave_age = sum(sex_age[sex])*1.0 / len(sex_age[sex])
    print '%s\t%s'% (sex, ave_age)

3. Pythonのプログラムの権限変更

作ったプログラムに実行権限を追加します。
$ chmod +x mapper.py
$ chmod +x reducer.py

4. テストしてみる

これって、ただのテキストを吐き出して、Mapperで読み込んで、また吐き出して、Reducerでも読み込んで吐き出しているだけなので、ターミナル上でテストできます。例えば、こんな感じで。
$ cat adult_data.csv | python mapper.py | python reducer.py
1 47.597301855
2 47.2906009245


5. 最後にMap Reduce on Hadoop!

ここで、hadoop-streaming.jarというJavaのプログラムをhadoop jarで実行します(参考にしたブログに書いてあった、hadoop-streaming.jarがあるディレクトリと私のディレクトリが違ったので、cdhのバージョ等ンに寄って違うのかもしれませんので、検索して確認したほうが良いかもしれません)。

mapper.pyとreducer.pyのあるディレクトリで以下を実行すると、Map Reduceが始まります(見やすくするために、複数行で書いていますが、実際にやるときは一行で書いてください)。
$hadoop jar /usr/lib/hadoop-mapreduce/hadoop-streaming.jar 
 -mapper mapper.py 
 -reducer reducer.py 
 -input /user/<your username>/test/adult_data.csv 
 -output ave_age 
 -file mapper.py 
 -file reducer.py


6. めでたく結果をゲット

(よくわからないんですが)outputで指定したフォルダに、part-00000というテキストファイルが作られていて、そこに結果が入っています。
$hadoop fs -cat /user/<your username>/ave_age/part-00000 
1 47.597301855
2 47.2906009245

2014年3月24日月曜日

CDH4を使ってのHadoop + HIVE インストール備忘録(Ubuntu 12.10)

新しいモジュールでDistributed Computingの授業があるので、UbuntuにHadoopとHiveを入れておこうと思って始めたのですが、不慣れでかなり手間取ってしまい、丸一日潰してしまいました。。。こういうインフラ系のことって本当に難しいんですね・・・

また同じことはできないと思うので、忘れないように残しておきます。

参考にしたブログや記事です。本当に助かりました。ありがとうございます。


  • https://gist.github.com/YoshihitoAso/9444292
  • http://kakakikikeke.blogspot.jp/search?q=hive



上記を見ながら、「動かない!!なぜだ!??」と試行錯誤しながら、ようやく動くまでに至った経緯です。正直、Hadoopがどうやって動いているのか、hiveがどうして動いているのかわかっていませんが、自分がやったことは以下のとおりです。


まず、インストールするOSですが、Ubuntu12.10の64bitです。

Javaのインストール
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java7-installer
インストールが済んだら、以下のコマンドを叩いてバージョンを確認します。
$ java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)
続いて、JAVA_HOMEを設定します。homeにある隠しファイル「.bashrc」を開いて、以下をファイルの末尾に入力し保存します。
export JAVA_HOME=/usr/lib/jvm/java-7-oracle
export PATH=$PATH:$JAVA_HOME/bin
これをやったら、一度ログアウトして、JAVA_HOMEの変更を反映させるのを忘れないように!(それをやらずに、この後のCDHをインストールしたところ、エラー!って怒られました・・・)

CDH4をインストールします。
$ sudo dpkg -i cdh4-repository_1.0_all.deb
$ curl -s http://archive.cloudera.com/cdh4/ubuntu/precise/amd64/cdh/archive.key | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install hadoop-conf-pseudo
どうやら、インストールしたときに、hdfsユーザーというものが作られているようです。そこで、ここからはhdfsユーザーで作業をします。
$ sudo su hdfs
コマンドラインが、「hdfs@」で始まるようになります。
そして、以下のコマンドを叩いて、Namenodeをフォーマットします。
$hdfs namenode -format
そしたら、コマンドラインに「exit」と入力してhdfsユーザーから抜けます。
続いて、以下のコマンドをターミナルに入力して、HDFSを起動します。ちなみに止めるときはstartの代わりにstopです。
for service in /etc/init.d/hadoop-hdfs-*
do
sudo $service start (止めるときは、ここのstartをstopに変える)
done
startingほにゃららみたいなメッセージが何回か現れると思います。 それを見届けてから、何も考えずに以下を打ち込みます。
$ sudo su - hdfs
$ hadoop fs -mkdir /tmp 
$ hadoop fs -chmod -R 1777 /tmp
$ hadoop fs -mkdir /var/log/hadoop-yarn
$ hadoop fs -chown yarn:mapred /var/log/hadoop-yarn
$ hadoop fs -mkdir /tmp/hadoop-yarn/staging
$ hadoop fs -chmod -R 1777 /tmp/hadoop-yarn/staging
$ hadoop fs -mkdir /tmp/hadoop-yarn/staging/history/done_intermediate
$ hadoop fs -chmod -R 1777 /tmp/hadoop-yarn/staging/history/done_intermediate
$ hadoop fs -mkdir /user/$USER
$ hadoop fs -chown hdfs /user/$USER
そして、HIVEを使うために、/userの権限を変更します。(これをやらなかったために、HIVEを起動して、テーブル作ったときに、Permission Deniedのエラーが出てハマりました。。。。)
$sudo -u hdfs hadoop dfs -chmod 777 /user
上記がうまくの権限変更がうまく行っているか、確認します。
$sudo su hdfs (改めてhdfsでログイン)
$ hadoop fs -ls /
Found 3 items
drwxrwxrwt   - hdfs supergroup          0 2014-03-23 22:13 /tmp
drwxrwxrwx   - hdfs supergroup          0 2014-03-23 22:02 /user
drwxr-xr-x   - hdfs supergroup          0 2014-03-23 18:26 /var
続いて、YARNを起動してみます。
sudo service hadoop-yarn-resourcemanager start
sudo service hadoop-yarn-nodemanager start
sudo service hadoop-mapreduce-historyserver start

そして、HIVEをインストールします。
※これはhdfsユーザーではなくrootユーザーでやります。
$ wget http://mirror.tcpdiag.net/apache/hive/stable/hive-0.11.0.tar.gz
$ tar xzf hive-0.11.0.tar.gz
$ mkdir /usr/local/hive
そしたら、hive-0.11.0の中身を新しく作った/usr/local/hiveに移します。
次に、環境変数を設定します。また、homeにある隠しファイル「.bashrc」を開いて以下をファイルの末尾に追加して保存します。
export HIVE_HOME=/usr/local/hive
export PATH=$HIVE_HOME/bin:$PATH
また、一度ログアウトし、再度ログイン。ターミナルで、$echo $HIVE_HOMEを叩いて、ちゃんと反映されているか確認。続いて、/hive/confに入っている各種テンプレートを本番用に変更します。
$cd $HIVE_HOME
$mkdir logs
$cd /usr/local/hive/conf
$mv hive-log4j.properties.template log4j.properties
$mv hive-env.sh.template hive-env.sh
$chmod 755 hive-env.sh
$mv hive-exec-log4j.properties.template hive-exec-log4j.properties
$mv hive-default.xml.template hive-site.xml
これで、最後にhiveが動くかどうか・・・・
$hive (これはrootユーザーです)
それで、hive>となったら、まずはshow databases;を叩いてみます。

hive> show databases;
OK
default
test
Time taken: 3.108 seconds, Fetched: 2 row(s)
で、create tableなど試してみて、きちんと動いているようであれば、無事インストール終了です。

2014年3月23日日曜日

サンフランシスコの花粉症

花粉症って日本だけだと思っていたら、アメリカにもあるんですね・・・。ゴールデンゲートパークの近くに住んでいるか、くしゃみが止まらない・・・

日本にいるときは、必ずマスクをして外出していたのですが、サンフランシスコではマスクをしている人を見かけないので、ちょっとマスクして出かけにくいなぁと。結構、バス乗っていても、くしゃみしたり、鼻すすっている人多いんですが、マスクはしていないんですよね。。。友達にこのこと言ったら、「怪しまれるからマスクはしない方がいい」って言われたので、しばらく我慢します。

うーん、早く花粉症の季節が終わらないかなぁ。

第4モジュール開始!

1週間の春休みも終了し、新しいモジュールが始まりました。本モジュールは、ソフトな授業が多かった先モジュールとは大きく異なり、統計&プログラミングのお祭りです。

Data and Information Visualization
字のごとく、Rのggplot2を使って、ひたすらグラフを書きまくるクラスの模様です。データの可視化は重要なテーマです。ただ、データの可視化ってかなり個人の嗜好が影響するので、どう教えるんだろうって気もしてします。ただ、先生はデータの可視化を研究している方なので、盗めるところは盗んでいきたいですね。

ただ、そもそも、これまでのビジネスの現場経験からすると、複雑なデータをどうやって折れ線と棒グラフに持ち込むかを考えるほうが重要だと個人的には思っています。

Multivariate Statistical Analysis
多変量解析の授業です。主成分分析、因子分析などなどやるようです。回帰分析、時系列分析から引き続き先生は同じで、数学をかっちりやりつつ、Rで動かすっていう感じになりそうです。

Distributed Computing
おまちかねのMapReduceです。先生は実際に働いている方なので、実務でどうやっているかを学べます。また、学生はAWSのクーポンを持っているので、AWS上でHadoopを動かします。が、AWSで遊んでいるとすぐクーポンがなくなってしまうので、好きな人は、自分のマシンにHadoop入れて遊んだりしています。

Practicum
引き続き、インターンですね!


上記の他に、Kaggleの生みの親でありデータサイエンティストのJeremy Howardのレクチャーがあります(来年はどうかわかりませんが・・・)。彼が実際にKaggleでどんなテクニックを使ってきたのかについて、説明してくれています。彼は本当にすごいです・・・。

とても楽しいモジュールになりそうです!

2014年3月17日月曜日

KAGGLE 備忘録

ここ最近、KaggleのLoan Predictionのコンペに参加していました。結果はTop25%入りでした。(コンペの詳細は、http://www.kaggle.com/c/loan-default-prediction)

このコンペの目的は、名前のとおり債権のデフォルト予測なのですが、多くのデフォルト予測は「デフォルトする・しない」のクラス分類問題です。しかし、このコンペは、デフォルトする・しないの分類だけではなく、デフォルト後の回収率を予測するという数値予測の要素も入っています。

実は、開始当初の数週間は、全てデフォルトしないと予測する「ゼロベンチマーク」を超えられず、かなり苦戦しました。しかし、いくつかブレークスルーがあり、最終的にはTop25%で着地しました。最後の1週間、時間がなくてモデルをアップデートできなかったのが悔やまれますが、まぁ、いろいろと学びがあったので、良しとしましょう!

このコンペの最大の難関は、説明変数約700個の内容が隠されていることです。もし、「利子率」とか「満期までの時間」などがわかればもっと簡単なのでしょうが、データセットの変数のラベルは、f201やf355と付けられているので、どの列が何を意味しているのかわかりません。つまり、Feature Engineeringができないことになります。

また、コンペは、Mean Absolute Error(MAE)で競われることになります。この点も非常に重要なところです。

そして、私がとったアプローチは以下2段階です。

① デフォルトした、しないのフラグを作り、クラス分類のモデルを作る。
② デフォルトしたサブセットのみを対象に、回収率の予測モデルを作る。

①の問題は「どのアルゴリズムを使うか」ということよりも、変数選択です。また、データセット中、デフォルトした債権の本数は約10%なので、かなりアンバランスなデータセットです。

そこで、フォーワードステップワイズ式のロジスティック回帰で、説明変数の絞り込みを行いました。ここで意識したのは、「何」を最大化(最小化)させるようにステップワイズを組むかです。通常のステップワイズでは、新たな変数を加えた時にAICが改善、Devianceが改善するかどうかで行いますが、今回のコンペの目的はクラス分類の精度が重要なわけです。そこで、F1スコア(PrecisonとRecallの調和平均)が最大になる変数を選択するように関数を組みました。この結果、5つの説明変数が選ばれ、F1スコアが約0.85でした。

次に、選ばれた変数を実際にグラフで見てみて、傾向を探り、ある変数と別の変数の差が予測に貢献していそうなことがわかったので、それら2つの変数の差を取ったものを、新たな変数として加えました(元の2変数は削除)。

このうえで、アルゴリズムを変えることでF1スコアが上がるかどうかを試しました。直観的には、ロジスティック回帰で0.85いくのであれば、ランダムフォレスト、ニューラルネットワークでも同等かそれ以上になるだろうということで、この2つを試しました。最終的にはニューラルネットで、F1が0.91にまで上昇しました。これで、①のクラス分類モデルの作成は終了です。

②は、①のモデルを使って、デフォルトする「だろう」と予測されたサブセットを作ります。ここで注意したのは、元データのうち本当にデフォルトしたものだけを抽出するか、①の予測モデルで、デフォルトと予測されるものを抽出するかですが、私は後者を選んでいます。賛否両論あるかと思いますが、①のモデルには誤差があるので、その誤差も含めて、②のステージで予測しようというのが考え方です。

②では、回帰分析で予測モデルを考えました。問題は残差の仮定ですが、最終的にはポアソンで落ち着きました。単純な回帰分析の場合は、被説明変数が0~100と限定されているのに対し、予測値は0以下も100以上も出ますので、予測値を得た後で、丸めなくてはなりません。今回のデータは0~100の整数で、かつ0側に歪んでいる分布だったので、ポアソンにして、残差もチェックしたら悪くない感じでした。ただ、単純に全変数を突っ込んで予測していても、順位が上がらなくなっていたので、2変数の交互作用の全組み合わせを入れて、ステップワイズでMAEを最小化するモデルを選ぶようにしました。

②はえいやー!でやった感は否めず、もう少し時間があれば変数選択をちゃんとできたかもしれませんが、まぁ、結果は悪くないと思っています。

次回も頑張りたいと思います!

2014年1月23日木曜日

春学期 第3モジュールスタート!

今週から新学期!第3モジュールが始まりました。

このモジュールのラインナップはこんな感じです。

Business Strategies for Big Data(週2コマ)
先生は、あるゲーム会社のディレクターで元UCLA Andersonの先生だそうです。主にミクロ・マクロ経済の基礎、アカウンティング、ファイナンス、マーケティングをざーっとやるような感じのようです。このクラスは、MBAのビジネスマネージャーの話を理解できる(馬鹿にされない!)というのがゴールです。

Interview Skills(週1コマ)
Googleでデータサイエンスをやっていた先生が受け持ちます。サンフランシスコもしくはシリコンバレーにある会社に就職するとき、Tech interviewが最初のハードルです。Tech Interviewというのは、例えば「P値って何?」とか「Boostingの疑似コード書いてみて」みたいな質問です。いきなりはできないので、それに対応するための練習をする必要があります。このクラスは、その練習をひたすらやる!というのがゴールです。ちなみに、毎週、Mock Interviewをやります。

Text Mining(週2コマ)
Text Miningといいながら、前モジュールの機械学習の続きのような感じです。ひたすらPythonとRで機械学習のライブラリを呼び続ける!という感じでしょうか。ただ先生は代わって、元々応用数学の人なので、授業は結構数学オリエンテッドです。おそらくこの授業が本モジュールで最もハードになると思われます。

もちろん引き続き週2日のPracticum(企業実習、インターン)がありますので、このモジュールも寝る時間は相当削られそうですが、後半戦も元気にやっていきたいと思います。

2014年1月7日火曜日

Intersession SAS Programming スタート!

さて本日よりIntersession programのSAS Programming のコースが始まりました。このコースは、2週間後のSAS Base programmerの試験の合格を目指します(落ちると何度も受けなおさせられます・・・)。Rに慣れているので、SASは最初わかりにくかったですが、慣れるとふつう(失礼!)ですね。おそらく、R使いの方で、はじめてSASを扱う方は同じような印象を持つのではないでしょうか。

一番とっつきにくいのは、データの操作だと思いますが、その辺はSASのオンラインチュートリアルはわかりやすいと思います。
http://web.utk.edu/sas/OnlineTutor/1.2/en/60476/paths.htm

2014年1月5日日曜日

第2モジュールの振り返り

新年の初投稿です。あけましておめでとうございます。冬休みは一時帰国していましたが、元旦にサンフランシスコに戻ってきました。新年早々、第2モジュールの成績が明らかになってきています。ここらでいちど、第2モジュールの振り返りをしておきたいと思います。


Time Series Analysis for Business and Finance
以前にも書きましたが、第1モジュールでやった回帰分析の続きという位置づけです。自己回帰プロセス(AR process)、移動平均プロセス(MA process)に始まり、GARCHまでがカバー範囲です。授業が数学ヘビーでやりつつも、結構わかりやすく、ここまでのベストレクチャーでした。ただ、あくまで単変量のモデルでやるので、時系列分析入門といったところでしょうか。多変量のモデルも実務では必要となるときがあるでしょうから、そこは自習する必要があります。使用したソフトウェアは、RとSASです。

Machine Learning
カバーした機械学習のアルゴリズムは、
1. 決定木
2. ナイーブベイズ
3. KNN
4. サポートベクターマシーン
5. クラスター分析
6. アンサンブル学習(Random Forest, Bagging, Boosting)
7. アソシエーションルール
8. ニューラルネットワーク
とです。最後まで理論よりでした。アルゴリズムの中で何が起きているのかを理解することが主眼に置かれていたように思います。しかし、今思えば、そういう勉強の仕方は時間がないとできないので、良かったかもと思っています。また、ゲストスピーカーで、Jeremy Howord(KaggleのPresident兼チーフサイエンティストで数々のコンペで優勝)が彼の普段やるデータ分析のやり方などを聞く機会があったのはありがたかったです(この授業だけでなく、以前も来ています)。

Distributed Databases
MySQLのおさらいから、MongoDBでMapReduceの概念を勉強し、最後はAWSでHadoopの使い方、Hiveの使い方を学ぶというものでした。週1の授業でしたので、ざーっと流した感じです。しかし、私はWIndowsになんとかHadoop + Hiveをインストールしようとして一番時間かかったかも。。。

Practicum 1 
会社でインターンをするというもので、週2回出社、週20時間以上の時間と先生からは言われていましたが、もっと時間を使っていたような気がします。なにせデータの量も半端じゃないので処理するのに時間かかります。インターンで感じることは、データ分析で一番大事なことはやっぱり分析結果を使ってもらうことだということです。なので、データ利用者にどうやってわかりやすく説明するか、「お客さんはこんな感じではなからろうか?」とストーリーで話すことの重要性を改めて感じました。また、Take Awayをクリアにしてあげることも重要です。「棒グラフや表などでさえも読みたくない」というのがデータ利用者の本音なのだと感じます。まぁ、私にとっては、実際にアメリカで働いてみたかったので、この授業はありがたいです。

とこんな感じで第2モジュールは終わりました。結構勉強したなぁと思います。そして、週明けからはSAS集中講義があり、2週間後にSAS Base Programmerの試験を受けることになっています。これに受からないと受かるまでやらされる模様なので、一発で合格したいです。

残りは半年!後半戦もがんばらないと!

2013年12月9日月曜日

(自分用メモ)R 時系列分析の関数まとめ

Rには時系列分析用のパッケージがいろいろありますが、授業で使っているパッケージ・関数を備忘のために、まとめておきたいと思います。

まずデータを入手したら

  1. 時系列プロット
  2. 単位根検定(Augmented Dickey–Fuller Test, Phillips-Perron Test for Unit Roots)
    • adf.test(data, alternative ="stationary") (tseries package)
    • PP.test(data)
データが非定常だったら・・・
  1. 移動平均でdetrend
  2. 単位根検定でひっかかったら、diffを取る(ex: Z_t = Y_t - Y_t-1)
  3. Exponential smoothingでdetrend
    • Simple Exponential Smoothing
      • HoltWinters(data,alpha=数字, beta=FALSE, gamma=FALSE) #ARIMA(0,1,1)と同じこと
    • Double Exponential Smoothing
      • HoltWInters(data,alpha=数字, beta=数字, gamma=FALSE) #ARIMA(0,2,2)と同じこと
    • 以下2つを使う場合、dataはtsオブジェクトでfrequencyが定義されてるもの
    • Seasonal Exponential Smoothing without Trend
      • HoltWinters(data,alpha=数字, beta=FALSE, gamma=数字) 
    • Seasonal Exponential Smoothing with trend
      • HoltWinters(data, alpha=数字, beta=数字, gamma=数字)  


データは定常。ではWhite noiseか?
  1. 時系列データがWhite noiseかどうかの検定 (Box Pierce , Box Ljung test)
    • Box.test(data, lag=1 , type = c("Box-Pierce", "Ljung-Box")

White noiseではないようだ。では、ARIMAモデルか?
  1. Sample Auto Correlation, Sample Partial Auto Correlationのプロット
    • acf(data, plot=TRUE)
    • pacf(data,plot=TRUE)
  2. ARMAのパラメータ候補を絞りたい
    • eacf(data) (TSA package)
  3. ARIMA(p,d,q) モデルの推定(dataはtsオブジェクトです)
    • arima(data, order=c(p,d,q),method="ML")
  4. ARIMA(p,d,q) モデルの推定(dataはtsオブジェクトです)
      • arima(data,order=c(p,d,q),seasonal=list(order=c(P,D,Q),period=S),method="ML")

    ARIMAモデルの残差はWhite noiseになったのか?
    1. 残差プロット + Box testでチェック
    2. 残差プロットの中でvolatility clusteringがあれば、ARCH LM testをやってみる

    ARCH/GARCHモデル
    1. garchFit(~arma(p,q)+garch(q,p),data=data) (GARCHのパラメータqはalpha, pのパラメータはbeta)

    予測
    1. arimaで推定したモデルであれば、forecast(arimaクラスのオブジェクト) (forecast library)
    2. garchFitで推定したモデルであれば、predict(fGarchクラスのオブジェクト)

      2013年11月1日金曜日

      第2モジュールスタート!

      さて、先々週から第2モジュールが始まりました!

      第2モジュールは、以下のラインナップです。

      Time Series Analysis for Business and Finance
      前モジュールでやった回帰分析の授業の続きという位置づけですが、まずARプロセス、MAプロセス、ARMA, ARIMA, SARIMAといった時系列のモデルを勉強します。今後、ARCH、GARCHなんかもやるみたいです。今のところ、主には理論をやっていますが、今後はRとSASを使って分析をやっていくようです。

      Machine Learning
      一番思ってたのと違うのが、この授業・・・・。かなり理論寄りです。マシンラーニングは、Rとかで動かすっていうだけだと結構楽しい代物ですが、それなりに数学もやると、そこそこヘビーです。しかも、実際に動かすのは、PythonのScikit-learnです。私はR使いなので、Rでやるほうが楽だったのですが、仕方ない・・・。

      Distributed Databases
      こちらは、SQLから、NoSQLへの発展編です。最初2回は、MySQLのおさらいと少し応用編をやり、次回からはMongoDBを使おうという流れです。MySQLは前期のData Acquisitionの復習に始まり、変数の使い方、Stored procedure, stored functionといった内容をやりました。先生が愉快な方なので、楽しいです。

      Practicum 1 
      強制的に企業とのコラボプロジェクトにアサインされます。会社の希望は出せますが、人を選ぶのは会社側らしく(事前にレジュメを提出します)、必ずしも希望の会社にアサインされるかはわかりません。会社によっては面接したりします。だいたい1週間に2回くらい出社するように言われているクラスメートが多いようです。詳細は書けないのですが、コラボ先企業は、シリコンバレーのベンチャーはもちろん、金融、小売、交通、自治体など多岐に渡ります。

      2013年10月7日月曜日

      Kaggle Hackathon!! ハッカソン!

      先日、サンフランシスコのマイクロソフトで行われたKaggle Hackathonに、クラスメートと参戦してきました。

      結果は8位。上出来です!

      Kaggle Hackathonとは、24時間レースで、機械学習の精度を競い合うコンペです。

      今回のテーマは、あるソーシャルネットワークのサイトのView数、コメント数、投票数を予測するというもので、そのサイトは、ある地域住民が地域の不満や改善してほしい点を投稿し、他のユーザーが、コメントしたり投票したりします。

      そして、投票数が多いものに関しては解決が図られるというものです。たとえば、「道に落書きがあり、汚いから、なんとかして!」みたいな投稿に対して、投票されます。

      うちのチームは人数あ多かったので、24時間の間でもいろいろな手が打てたのも好成績の要因だったと思います。私は、投稿のタイトルをテキストマイニングして、新たなダミー変数を作るということをしてました。表記ゆれ、スペルミスを正規表現で修正していくような感じですね。

      残念ながら、作った変数はあまり予測力向上に役立ちませんでした。



      オンサイトのコンペで良いのは、優勝者と話ができることです。優勝した方と話したら、テキストデータは最初に分析しないと決めていたといってました。データをざっと見て、あまり相関してなさそうだと見たということです。

      さすが、洞察がするどい!自分は、そういう感覚がまだあまり備わっていないなぁと感じてしましました。データをざっと眺めて、最初にplay aroundしたときに、予測する変数と説明変数の間にどんな関係がありそうかを見出すというのが肝心だということです。

      できることが増えると、やってみたい分析をやってしまうという陥りやすい罠にはまってしまうということを学習しました。

      他のKaggleコンペにも参戦しているので、今回の教訓を活かします!でも、チームで8位とれたので、よしとしましょう!

      2013年9月20日金曜日

      (Pythonメモ)Google Financeのニュースヘッドラインを取得するPythonコード

      株価とニュースの関係を分析してみたいなぁと思って、Google Finance (US)を取り込むコードを書いた。

      getHeadkineという関数に、対象となる会社のticker、その会社の属するmarket(NASDAQなど)、検索対象となる開始日と終了日をstartとendというパラメータで指定すると、keyが日付、valueがヘッドラインの辞書を返す。

      from __future__ import unicode_literals
      import urllib2
      import urllib
      import re
      from datetime import datetime,timedelta
      import nltk

      def getHeadline(ticker,market,start,end):
          query = urllib2.quote(ticker+':'+market)
          base = 'https://www.google.com/finance/company_news?q='
          url = base + query + '&startdate='+ start +'&enddate=' + end + '&start=0&num=10000'
          print url
          html = urllib.urlopen(url).read()
          raw = nltk.clean_html(html)
          raw = unicode(raw,errors='ignore')
          data = raw.split('\n')
          data =  data[60:-1]
          while u' ' in data: data.remove(u' ')

          monthDict = {'Jan':'01','Feb':'02','Mar':'03','Apr':'04','May':'05','Jun':'06','Jul':'07','Aug':'08','Sep':'09','Oct':'10','Nov':'11','Dec':'12'}

          news={}

          for i in range(0,len(data),1):

              t = re.match(r'[\s\w0-9/\.,:;\(\)]+\-\s([0-9\w\s]+)\sago\s*',data[i])
              o = re.match(r'[\s\w0-9/\.,:;\(\)]+\-\s(\w+)\s([0-9]+),\s(201[0-3])\s*',data[i])
              if t:
                  hours =  int(t.group(1).split(' ')[0])
                  delta = timedelta(hours=hours)
                  gmt = timedelta(hours=7)
                  d = datetime.today() - delta + gmt
                  year = str(d.year)

                  if d.month <10:
                      month = '0'+str(d.month)
                  else:
                      month = str(d.month)
                  if d.day < 10:
                      day = '0'+str(d.day)
                  else:
                      day = str(d.day)

                  key = year+'_'+month+'_'+day

                  if key in news.keys():
                      news[key].append(data[i-1])
                  else:
                      news[key]=[]
                      news[key].append(data[i-1])

              if o:
                  #Month
                  m = o.group(1)
                  month = monthDict[m]
                  day = o.group(2)
                  year = o.group(3)

                  key = year+'_'+month+'_'+day

                  if key in news.keys():
                      news[key].append(data[i-1])
                  else:
                      news[key]=[]
                      news[key].append(data[i-1])

          return news

      #Example : getHeadline
      #Output is a dictionary like this: { date : [headline1, headline2,.....], date:[headline3],......}
      #the keys (time) is not ordered.Also, time is GMT (I checked the publish time in RSS xml).
      #The function requires 'ticker', 'market name', 'start date'(YYYY-MM-DD) and 'end date' (YYYY-MM-DD)
      print getHeadline('AAPL','NASDAQ','2012-09-01','2013-09-15')

      2013年9月1日日曜日

      秋学期 第1モジュール ここまでの内容

      今週末はLabor Dayで3連休です。


      少しゆっくりできるかと思いきや・・・


      宿題の雨あられですので、気が抜けない状況です。


      ここまでの学校の様子を残しておきます。


      秋学期は8月中旬から12月中旬までの4か月間で、Analytics programは2か月ごとのモジュールに分かれています。最初のモジュールは、


      1. Business Communication for Analytics 【週2】
      2. Linear Regression 【週2】
      3. Data Acquisition (DA) 【週1】
      4. Exploratory Data Analysis (EDA) 【週1】
      の4つの授業があります。これらに加えて、週1回のゲストスピーカーのプレゼンに出席するということになっています。


      Business Communication for Analytics

      International Studentにはもっとも過酷な授業です。授業が始まる前に、Program Directorから、英語をもっと練習しないとついていけないだろうと警告されたくらいです(単に、私の英語力不足ですが)。

      この授業では、「技術的な内容を、それを知らない人に伝える」ということが大きなテーマになっています。なぜなら、分析は、専門でない人にとって難しく見えてしまいます。しかし、多くの場合、専門でない人が意思決定者であり、お客さんです。そのため、いかにインサイトをわかりやすく腹落ちさせるかというところが、非常に重要になるためです。

      もちろん、Data Visualizationなど見た目が華やかでファンシーなコミュニケーション手法もありますが、この授業では、Writing, Speakingがフォーカスになっています。


      Linear Regression

      Boot Campの統計の授業の続きというのが実際の位置づけです。授業の名の通り、ひたすら、回帰分析を勉強しています。ちなみに使用言語はRです。


      ここまでは、最小二乗法による回帰分析とその特性、モデルの診断の仕方を学びました。また、ロバスト回帰などもトピックに上がっています。私にとっては、学部のときには勉強しなかった、Cook's Distanceや、Leverageなんかも勉強できて、ハッピーです。


      Data Acquisition (DA)

      先生は実務で活躍されている方で、内容は実践的です。扱う内容は、分析ではなく、データ取得、クレンジングなどのデータ分析をする手前までのすべてということになります。使用言語はPython。


      ここまでのところ、正規表現、JSONファイルとCSVファイル(マトリックス形式のデータセット)の円コーディング・デコーディングなどを扱っています。今後は、ソーシャルメディアのAPIなどにも触れる模様です。


      Exploratory Data Analysis(EDA)

      先生はシリコンバレーで仕事をしている実務家の方で、かなり実践的です。ちなみに、使用言語は、PythonとRです。
      Data Acquisitionと少しかぶりますが、こちらは、集計、可視化に重きが置かれています。


      今年、出願を検討されている方がいらっしゃいましたら、もっと詳しくお伝えできますので、ぜひご連絡ください!

      ではでは、宿題に戻ります・・・

      2013年8月17日土曜日

      夏休みの思い出

      KAGGLEのコンペだけやっていたわけではありません。

      ちゃんと、友達と小旅行に出かけたので、その記録を残しておきます。



      ①アップルの本社前
      住所が、1 infinite loopというなんとも言えない住所でした。





      ②スタンフォード大学のキャンパス
      きれいです。いい天気です。





      ③ スタンフォード大学内の教会です。
      荘厳です。すごい装飾です。






      ③スタンフォード大学の教室棟?の回廊
      このアーチ型の影、憧れです。



      KAGGLE

      KAGGLEってご存知ですか? 

      データ分析のコンペを行っている会社で、いろいろな会社がテーマとデータを提供し、それに対して参加者が機械学習のモデルを構築し、その精度を競い合うというものです。

      先日、KAGGLEのChief ScientistのJeremy Howard氏がゲストスピーカーで来校して、いろいろとお話しされていたので、ホームページを見てみたところ、面白そう!!ということで、参加してみました。

      KAGGLE
      http://www.kaggle.com/



      私が参加したのは以下の2つのコンペです。

      ・ Yelp(ぐるなびみたいなもの)のリコメンデーションシステムの精度コンペ
      ・ タイタニックの生存予測の精度コンペ



      実際にやってみると、結構はまってしまいまして(あまりに楽しい・・・)、貴重な夏休みをほとんど使ってしまいました。まるで、テレビゲームにはまった子供状態です。


      まだコンペの締切まで時間がありますが、夏休みの宿題をそろそろやり始めないとやばいので、心を鬼にしてRとPythonを閉じました。



      このコンペを通じて、いくつか自分の中で考えないといけないことがあるなぁと思いましたので、忘れないようにまとめておきます。


      課題その1
      参加者平均はいくものの、そこから抜けられない。

      両方のコンペでの課題です。この原因は2つあると思っていて、データ作り・特徴量づくりがイケてないのと、手法の習熟度が低いことです。特に前者が大きな問題だと思っています。

      両方のコンペで、ランダムフォレスト、ニューラルネットワーク、rpartの決定木、ロジスティック回帰などいろいろ試しましたが、精度はランダムフォレスト、ニューラルネット、rpart概ね同じでした。インプットしているデータが判別に役立っていないからでしょう。

      どうやって精度をあげていくか、アメリカにいる間に掴んでいきたいものです。


      課題その2
      モデルの評価をうまく整理できない。


      たくさんモデルを作るなかで、「あれ、さっきのモデル、どの名前だったけ?」ということが起きて、時間をロスしました。

      さらに、精度もRの打ちだしだけで見て確認して、終わり!ってやっていたので、あとで振り返ることができないという事態が発生。。。作成したモデルの管理、評価、改善点がどこかについて、うまく回せるようにしないと、効率悪くて仕方ないです。


      結果は満足できないですが、いろいろと反省点や問題意識も持てたので、楽しい夏休みでした。


      さぁ、マジでリーディングやらないと・・・・

      2013年8月12日月曜日

      Speakingの上達

      こちらにきて、3か月が経とうとしています。語学学校に6週間、USFのAnaluyticsのBoot Camp5週間、と計11週間授業を受けてきました。Speakingが上達してきたね!と先生からも良いフィードバックをいただいて、ご機嫌な今日この頃です。


      Native Speakerの人と話していて、よく What?って聞き返されるときは、イントネーションがおかしなときです。これは先生からもアクセントがストロングだ!と指摘されます。特に、慣れてくると、つい早口になってしまいますが、このときにアクセントがめためただとわかってもらえてないです。

      なるべく丁寧に発音することが大事ですね!

      昨日は飲みすぎたので、今日は一日本でも読んでゆっくりしよ。