基本情報技術者試験 No.001
基本情報技術者試験の秋期試験を受けようと思っています。
昨年から受けようと思っていたのですが、なかなか読み進めることができなくて。
kindleの本もずっと積読状態でした。という訳でさっそくはじめます。
2進数からです。
10進数 | 2進数 |
0 | 0 |
1 | 1 |
2 | 10 |
3 | 11 |
4 | 100 |
5 | 101 |
6 | 110 |
7 | 111 |
8 | 1000 |
9 | 1001 |
10 | 1010 |
11 | 1011 |
12 | 1100 |
という風に10進数での3は、2進数では11です。読み方は、10は「いちぜろ」、1101は「いちいちぜろいち」です。
2進数の1桁を「ビット(bit)」といいます。binary digitの略語です。
2進数の8桁を「バイト(byte)」といいます。
ですから、8bit = 1 byteとなります。
10111001 | 8桁 | 8ビット | 1バイト |
1001011110110100 | 16桁 | 16ビット | 2バイト |
10010101101010000111010101010100 | 32桁 | 32ビット | 3バイト |
コンピュータ内部では、情報を2進数の数値で表します。通常、数値でない情報を数値に置き換えて表したものを「符号」、「コード(code)」といいます。
1ビットで表せるのは0か1の2通り、2ビットで表せるのは00、01、10、11の4通りです。nビットなら、2^{n}通りです(普段ならTeXを使いますが省略)。
1ビット | 0, 1 | 2通り |
2ビット | 00, 01, 10, 11 | 4通り |
3ビット | 000 ~ 111 | 8通り |
4ビット | 0000 ~ 1111 | 16通り |
5ビット | 00000 ~ 11111 | 32通り |
・・・ | ・・・ | ・・・ |
8ビット(1バイト) | 00000000 ~ 11111111 | 256通り |
8ビット(1バイト)では、256通りの符合が表すことができ、半角英数字や半角カナを表すのにちょうどいいのです。1バイトを半角1記号に割り当てる文字コードが多いです。
コンピュータ内部ではデータを格納する箱のサイズがあらかじめ決められています。小さな情報が大きい箱に割り当てられると、上位桁が0で埋められます。
たとえば、8ビットの箱に、2ビットのデータを入れるとこうなります。
0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
たとえ、2ビットのデータでも4ビットの箱を使うのであれば、0000、0001、0010、0011という風に表します。
大きな数と小さな数を表すときには単位を変えます。
K(キロ) | 10^{3} |
M(メガ) | 10^{6} |
G(ギガ) | 10^{9} |
T(テラ) | 10^{12} |
m(キロ) | 10^{-3} |
μ(マイクロ) | 10^{-6} |
n(ナノ) | 10^{-9} |
p(ピコ) | 10^{-12} |
2進数の代用表現として16進数と8進数が使用されます。たとえば、2進数での010010110110は、16進数では4B6で、8進数では2266です。
10進数を2進数に変換するように変換を行うことを「基数変換」といいます。基数とは基準になる数のことです。
たとえば、10進数で123を2進数に基数変換する場合、このように変換する基数(この場合2)で割り、その商を再度基数で割り、それを繰り返して割れなくなったとき、その余りを逆から並べると基数変換した値が求まります。
123÷2=商61 | 余り1 |
61÷2=商30 | 余り1 |
30÷2=商15 | 余り0 |
15÷2=商7 | 余り1 |
7÷2=商3 | 余り1 |
3÷2=商1 | 余り1 |
1÷2=商0 | 余り1 |
10進数の123を2進数に基数変換すれば、1111011となります。
次に、2進数の111011を10進数に基数変換する場合は、2進数の各桁とそれに対応する重みを掛けて、それを足し合わせて求めます。重みは、1桁目は1、2桁目は2、3桁目は4、4桁目は8という風に、2進数の1、10、100、1000に対応した数値になります。
64 | 32 | 16 | 8 | 4 | 2 | 1 | ・・・ | 桁の重み |
× | × | × | × | × | × | × | ||
1 | 1 | 1 | 1 | 0 | 1 | 1 | ・・・ | 2進数の桁の数 |
= | = | = | = | = | = | = | ||
64 | 32 | 16 | 8 | 0 | 2 | 1 | = | 123 |
最後の数を足し合わせて、64+32+16+8+2+1=123となります。
(64*1)+(32*1)+(16*1)+(8*1)+(4*0)+(2*1)+(1*1)という訳です。
そもそも、123という10進数を10進数に変換すると、(100*1)+(10*2)+(1*1)という風に桁の重みを掛けると求めることができるのと同様です。
16進数は、1から15までを1桁で表します。したがって、1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10...と数えます。Aは10、Fは15のことです。
8進数は、1,2,3,4,5,6,7,10と数えます。
16進数と8進数は2進数の代用表現として使用されます。16進数の1桁が2進数の4桁に対応するからです。扱える情報が16とおりで一緒になります。
2進数 | 16進数 | 2進数 | 16進数 |
0000 | 0 | 1000 | 8 |
0001 | 1 | 1001 | 9 |
0010 | 2 | 1010 | A |
0011 | 3 | 1011 | B |
0100 | 4 | 1100 | C |
0101 | 5 | 1101 | D |
0110 | 6 | 1110 | E |
0111 | 7 | 1111 | F |
2進数と8進数の場合、2進数の3桁と8進数の1桁が対応します。扱える情報は8で一緒です。
2進数 | 8進数 |
000 | 0 |
001 | 1 |
010 | 2 |
011 | 3 |
100 | 4 |
101 | 5 |
110 | 6 |
111 | 7 |
2進数を16進数に変換するには、下位の桁を4つずつ区切って、16進数に変換する方法があります。これまでと同様に重みづけをしていきます。
たとえば、01101100という2進数を16進数に変換する場合、
0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | ・・・ | 4桁ずつ区切る |
× | × | × | × | × | × | × | × | ||
8 | 4 | 2 | 1 | 8 | 4 | 2 | 1 | ・・・ | 2進数の桁の重み |
= | = | = | = | = | = | = | = | ||
0 | 4 | 2 | 0 | 8 | 4 | 0 | 0 | = | 足し合わせる |
最初の4+2=6、8+4=12=Cですので、2進数の01101100は16進数では6Cとなります。 同様に、2進数を8進数に変換する場合、2進数を3桁で区切って重みづけを行います。11011011という2進数を8進数に変換してみます。
1 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | ・・・ | 3桁ずつ区切る |
× | × | × | × | × | × | × | × | × | ||
4 | 2 | 1 | 4 | 2 | 1 | 4 | 2 | 1 | ・・・ | 2進数の桁の重み |
= | = | = | = | = | = | = | = | = | ||
4 | 2 | 0 | 4 | 2 | 1 | 0 | 2 | 1 | = | 足し合わせる |
4+2=6, 4+2+1=7, 2+1=3ですから、8進数に変換すると673となります。
反対に、16進数を2進数に変換する場合、さっきと逆に16進数の各桁を4桁の2進数に分けて考えます。
先ほどの例でいえば、6Cという16進数は、6とCに分けて、2進数の各重み1,2,4,8をどのように組み合わせれば、6とCを作れるか考えるとわかります。
6なら2と4で、Cは12のことですので、8と4だと分かります。したがって、2と4は0110、8と4は1100ですから、01101100と2進数に変換できます。
次に、8進数を2進数に変換する場合は、16進数と考え方は一緒です。8進数の場合は上位の桁から3桁ずつに区切ります。先ほどの、673の場合は、2進数の各重みの1,2,4の組み合わせで考えると、6は2+4、7は1+2+4、3は1+2ですから、110、111、011を合わせて、110111011という2進数に変換されます。
8ビットの2進数で表せる情報は、00000000~11111111までの256通りです。これを10進数に変換すると、256通りの0以上のプラスの整数になります。これを符号なし整数と言います。
正負に分けたい場合は、256をプラス128通り、マイナス128通りの2通りに分けます。これを符号あり整数と言います。
符号あり整数の場合、最上位ビットが0ならプラス、1ならマイナスを表します。
0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 |
1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 |
上がプラスで、下がマイナスです。上の例でいえば、00000000~011111111がプラスで、11111111~10000000がマイナスを表します。
符号あり整数でマイナスを表現する方法に、2の補数表現があります。8ビットで111111に00000001を足すと、本来10000000(9ビット)になりますが、データの入れ物の大きさが8ビットに決まっている場合、00000000になります。00000001(1)を足して00000000(0)になるから、11111111は-1とみなすことができます。
つまり、足すと0になる数を求めて、それをマイナスと表現します。00000100は-4です。
小数点は.(ドット)を使わずに、0と1だけで表現します。固定小数点形式はあらかじめ、小数点を入れる位置を決めておくもので、たとえば、01011011を0101.1011と小数点とみなします。
小数点の2進数を10進数になおす場合は、各桁に重みづけをして集計する方法で変わりありません。0.1、0.01、0.001は、10^{-1}、10^{-2}、10^{-3}で重みづけをするように、2進数の場合は、2^{-1}、2^{-2}、2^{-3}、つまり、0.5、0.25、0.125、0.0625と重みづけをします。たとえば、0101.1010の場合、整数は4+1=5、小数点は0.5+0.125=0.625で、5.625となります。
許可ダイアログの表示
android6.0(marshmallow)以降では、permissionについて明示的な許可が必要になります。googleのdeveloper向けのサイトを元に、不完全なのですが、このように許可を作ってみました。stackoverflowには独自メソッドをつくるやり方もあったのですが・・・
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CONTACTS) || ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_PHONE_STATE)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}
}
最初に公開してきた時から、色々と変更していますので、あらためて一部のクラスを自分の備忘録として書いておきます。
MainActivity.java
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private final int MY_PERMISSIONS_REQUEST_READ_CONTACTS = 10;
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
}
return;
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CONTACTS) || ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_PHONE_STATE)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}
}
Button instructionButton = (Button) findViewById(R.id.instruction);
assert instructionButton != null;
instructionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplication(), Instruction.class);
startActivity(intent);
}
});
Button instruction2Button = (Button) findViewById(R.id.instruction2);
assert instruction2Button != null;
instruction2Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplication(), Instruction2.class);
startActivity(intent);
}
});
Button instruction3Button = (Button) findViewById(R.id.instruction3);
assert instruction3Button != null;
instruction3Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplication(), Instruction3.class);
startActivity(intent);
}
});
Button instruction4Button = (Button) findViewById(R.id.instruction4);
assert instruction4Button != null;
instruction4Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplication(), Instruction4.class);
startActivity(intent);
}
});
PackageInfo packageInfo = null;
TextView textView = (TextView)findViewById(R.id.version);
try {
packageInfo = getPackageManager().getPackageInfo("com.rnma2ri.saftyapp", PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
assert textView != null;
assert packageInfo != null;
textView.setText("versionCode : "+packageInfo.versionCode+" / "+"versionName : "+packageInfo.versionName);
}
}
MyDialog.java
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import java.util.ArrayList;
import java.util.List;
public class MyDialog extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_my_dialog);
List<String> list = new ArrayList<String>();
list.add("風邪で声が変わったは詐欺!");
list.add("電話番号が変わったは詐欺!");
list.add("医療費還付金があるは詐欺!");
list.add("詐欺の電話に注意しましょう!");
final CharSequence[] charSequences = list.toArray(new String[list.size()]);
AlertDialog.Builder alert = new AlertDialog.Builder(this, R.style.Theme_AppCompat_DialogActivity);
alert.setTitle(R.string.dialog_title)
.setIcon(R.mipmap.btn1)
.setItems(charSequences, new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int item) {
String string = charSequences[item].toString();
}
})
.setPositiveButton(R.string.dialog_button, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
MyDialog.this.finish();
}
});
alert.create().show();
}
}
PhoneReceiver.java
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
class PhoneReceiver extends PhoneStateListener {
private int totalCount = 0;
private Context context;
PhoneReceiver(Context context) {
this.context = context;
}
// 通話状態の変化に応じて表示を変更する
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
// 着信時の処理内容
case TelephonyManager.CALL_STATE_RINGING:
// ContentResolverを使って、端末内の番号を取得し、着信中の番号と突き合わせる
Cursor addressTable = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
try {
if (addressTable != null) {
while (addressTable.moveToNext()) {
String phoneNumber = addressTable.getString(addressTable.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
for (int i = 0; i < addressTable.getCount(); i++) {
int count = BooleanSum(PhoneNumberUtils.compare(phoneNumber, incomingNumber));
totalCount += count;
}
}
}
} finally {
assert addressTable != null;
addressTable.close();
}
if (totalCount < 1) {
Intent i = new Intent(context.getApplicationContext(), MyDialog.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.getApplicationContext().startActivity(i);
}
break;
}
}
// PhoneNumberUtilメソッドのBoolean型の戻り値をint型(0 or 1)に変換するメソッド
private int BooleanSum(Boolean exchanger) {
if (exchanger) return 1;
else {
return 0;
}
}
}
PhoneStateReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class PhoneStateReceiver extends BroadcastReceiver {
// 各フィールドの定義
TelephonyManager manager;
PhoneReceiver phoneStateListener;
static boolean listener = false;
// intent情報を処理する
@Override
public void onReceive(Context context, Intent intent) {
// PhoneReceiverインスタンスの生成
phoneStateListener = new PhoneReceiver(context);
// TelephonyManagerインスタンスの生成
manager =((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE));
if(!listener) {
manager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
listener = true;
}
}
}
MainActivity.javaの最後では、versioncodeを表示するようにしています。
まだまだ不完全ですが、一応これでひと段落です。間違いや効率的なやり方があれば教えていただけると助かります。
時系列データ解析 07 ~ ARMA過程
沖本先生の本の続きです。MA過程、AR過程ときて、続いてはARMA過程です。
ARMA(自己回帰移動平均)過程は、AR過程とMA過程の両方を含んだ過程です。(, )次のARMA過程、つまりARMA(p,q)過程は、
と記述されます。AR過程、MA過程、両方の性質のうち強い方がARMA過程の性質になります。
たとえば、MA過程は常に定常となりますが、AR過程は常に定常であるとは限らないので、ARMA過程も定常になるとは限りません。
ARMA過程の性質は下記のとおりです。
q+1次以降の自己共分散()と自己相関()は、が従うARMA過程のAR部分と同一の係数をもつp次差分方程式(ユール・ウォーカー方程式)に従います。
ARMA過程の自己相関は指数的に減衰する。
q+1次以降の自己共分散と自己相関は、ユール・ウォーカー方程式を解くことにより逐次的に求めることができる一方で、q次まではMA過程の影響があるため、表現することは難しいそうです。
ARMA過程は、AR過程が定常とは限らない点、MA過程は常に定常である一方で任意のMA過程に同一の期待値と自己相関構造をもつ異なるMA過程が複数存在する点など問題点があります。
自己相関構造のモデル化という点で、MAモデルを選択する基準が必要になるのですが、それが反転可能性という概念です。
AR過程の定常性は、差分方程式と関連があり、AR過程と同一の係数をもつ差分方程式が安定的になる場合に、AR過程は定常になります。まず、AR(p)過程を再度記述します。
AR(p)過程の定常条件は前回記述した
のすべての解の絶対値が1より大きいとき、AR過程は定常になります。この方程式は、AR特性方程式と呼ばれ、左辺の多項式はAR多項式と呼ばれます。沖本先生の例で言いますと、AR(1)過程
の定常性条件は、AR(1)過程のAR特性方程式
の解はとなりますから、のとき、となるので、となります。
また、AR(2)過程
の場合の特性方程式は
となりますので、解は-2と1となります。つまり、このAR(2)過程は非定常であることが分かります。
MA過程は常に定常ですが、同一の期待値と自己相関構造をもつ異なるMA過程が存在することは既に上で話をしました。時系列モデルを利用する目的は、データの平均的な挙動と自己相関構造をモデル化することです。そのため、同一の期待値、自己相関構造をもつMAモデルが複数存在するときには、どのモデルを用いるかを決める基準として、MA過程の反転可能性があります。
MA過程がAR(∞)過程に書き直せるとき、MA過程は反転可能といわれます。
MA過程が反転可能であるとき、は過去のの関数として表現でき、過去のを用いてを予測した時の予測誤差とも解釈できます。そのため、反転可能表現に伴うをの本源的な撹乱項と呼ぶこともあります。
この本源的な撹乱項を用いた場合、パラメータの推定や予測を自然な形で行うことができるので、同一の期待値、自己共分散構造をもつMA過程のうち、反転可能な過程を選択する方が望ましいということになります。
同一の構造をもつMA(q)過程は一般的に個存在することが知られていますが、反転可能なものは1つしか存在しません。MA(q)過程の反転可能条件は、AR過程の定常条件と同様のものです。
というMA特性方程式を用いて、この特性方程式のすべての解の絶対値が1より大きいとき、MA過程は反転可能となります。
ARMA過程の定常性は、MA過程が常に定常であるので、ARMA過程はAR過程が定常であれば、定常なAR過程とMA過程の和として表現できるため、定常になります。したがって、AR過程の部分が定常であることが確認できればよいので、AR特性方程式のすべての解が1より大きければ、ARMA過程は定常になります。
同様に、ARMA過程の反転可能性は、MA過程が反転可能性あればよいということになります。したがって、MA過程の部分のMA特性方程式のすべての解の絶対値が1より大きいとき、ARMA過程は反転可能となります。
安心アプリ
安心アプリ - Google Play の Android アプリ
いよいよアプリを公開しました。
アプリの内容ですが、知らない電話番号、電話帳に登録されていない番号から着信が入ると、AlertDialogが起動して、注意喚起をするという簡単なつくりです。
主な目的は振り込め詐欺被害の防止です。
電話帳に登録されているかを調べますので、電話帳、電話に対するpermissionが必要ですが、アプリ自体に通信機能がありません。ですから、電話帳のデータがリークすることはありません。
よろしければ、おじいちゃん、おばあちゃんにおすすめしていただけると力を発揮できると思います。
プライバシー・ポリシー
当サイトおよびアプリでは、以下のとおり個人情報保護方針を定め、個人情報保護の仕組みを構築し、個人情報の保護を推進致します。
- 個人情報の管理
当サイトおよびアプリでは、お客さまの個人情報を正確に保ち、個人情報への不正アクセス・紛失・破損・改ざん・漏洩などを防止するため、セキュリティシステムの維持・管理体制の整備の徹底等の必要な措置を講じ、安全対策を実施し個人情報の厳重な管理を行ないます。
- お問合せ
当サイトおよびアプリは、苦情及び個人情報取扱い窓口を設置し適正かつ迅速に対応いたします。以下メールにてお問い合わせください(お手数ですが、必要な個所を@に置き換えてください)。
crimsonbach [at mark] yahoo.co.jp
時系列データ解析 06 ~ 自己回帰過程
沖本先生の本の続きです。MA過程の次はAR過程です。
自己回帰(AR)過程は、過程が自己の過去に回帰されたモデルで表現されるものです。1次のAR過程、AR(1)は、
で定義され、 と表記されます。
AR過程は代表的な弱定常過程である
に、 が追加された形をしていて、そのため と が相関をもつことになります。
AR過程の確率的変動は、MA過程と同様、撹乱項のホワイトノイズ によって決まります。 が決まり、続いて が決まっていきます。
AR過程では初期値の決定が問題になります。 が分布が定まっている場合は、その分布に従う確率変数とし、 の分布が定まっていない場合は、ある定数とすることが一般的です。ただ、定常過程では、初期値の影響は時間とともになくなるので、大きな問題にはなりません。
沖本先生の本のとおり、具体例を示します。次のようなAR(1)を考えます。
初期値を として、 、 とします。このときに順番に解いていくと、
となります。
ここで、MA(1) 過程と同様に、パラメータを調整したAR(1)過程をグラフ化してみます。RのコマンドについてはMA(1)で多少説明していますので、必要な部分のみ解説します。
以下の6つのパラメータのAR(1)過程をグラフ化します。
Rのコードです。arima.sim関数の第2引数ですが、今回はAR過程なので、order=c(1, 0, 0) となっています。ちなみに、MA過程の時はorder=c(0, 0, 1) でした。次にAR過程の係数はar=c(0.8)として指定します。
set.seed(1) d1 <- arima.sim(n=100, model=list(order=c(1, 0, 0), ar=c(0.8)), sd=1) +2 plot(d1, main="(a) c=2, Φ=0.8, σ=1") set.seed(1) d2 <- arima.sim(n=100, model=list(order=c(1, 0, 0), ar=c(0.3)), sd=0.5) - 2 plot(d2, main="(b) c=-2, Φ=0.3, σ=0.5") set.seed(1) d3 <- arima.sim(n=100, model=list(order=c(1, 0, 0), ar=c(-0.3)), sd=2) plot(d3, main="(c) c=0, Φ-=0.3, σ=2") set.seed(1) d4 <- arima.sim(n=100, model=list(order=c(1, 0, 0), ar=c(-0.8)), sd=1) - 2 plot(d4, main="(d) c=-2, Φ=-0.8, σ=1") set.seed(1) d5 <- arima.sim(n=100, model=list(order=c(1, 0, 0), ar=c(1)), sd=1) + 2 plot(d5, main="(e) c=2, Φ=1, σ=1") set.seed(1) d6 <- arima.sim(n=100, model=list(order=c(1, 0, 0), ar=c(1.1)), sd=1) + 2 plot(d6, main="(f) c=2, Φ=1.1, σ=1")
まず、(e)と(f)ですが、係数が以上の場合、AR過程は定常ではなくなるため、エラーで出力されません。そのため、グラフも出力されません。
AR過程はMA過程と違い、パラメータの値によって定常か非定常かが変わります。先ほど、係数が以上と書きましたが、正確には係数の時に非定常となります。
ここではAR(1)過程が定常という場合のみを解説していきます。
AR(1)過程の期待値についてです。グラフでは概ね期待値と定数項が一致しているようにも見えますが、実際は期待値と定数項は一致しません。(a)あたりでは定数項はですが、やや下の方に過程の期待値があるようです。AR(1)過程の期待値をみています。
ここで、ホワイトノイズの性質により です。また、は定常過程ですから、
です。よって、AR(1)過程の期待値
が得られます。
次に分散ですが、MA過程と同様に過程の分散は撹乱項の分散と異なります。MA(1)過程で使用した(a)のグラフと今回の(a)のグラフを比べてみます。ちなみに左側はMA(1)過程、右側がAR(1)過程です。
撹乱項の分散はですが、過程の変動幅は違います。AR(1)過程の方がやや大きいです。つまり、AR(1)過程の分散は撹乱項のそれより大きくなります。では分散を見ていきます。
ここで、が定常であれば、ですので、AR(1)過程の分散は、
となります。
最後に自己相関をみてみましょう。先ほどのMA(1)過程のグラフ(a)とAR(1)過程のグラフを比べると、係数( と はともに)は同じでもAR(1)過程のグラフがより滑らかであることがわかります。
これは、この場合のように係数が同じとき、1次自己相関の絶対値はAR(1)過程の方が大きくなることと、AR(1)過程は2次以降の相関係数もすべて正になることの2点によるからです。
AR過程のk次の自己共分散はこのようになります。
ここで、両辺を で割ると、
となり、これはユール・ウォーカー方程式と呼ばれます。ユール・ウォーカー方程式は、AR過程の自己相関が、 が従うAR過程と同一の係数 をもつ差分方程式に従うということを表しています。
ユール・ウォーカー方程式とを用いて、AR過程の自己相関は順番に求めることができます。また、ユール・ウォーカー方程式により、AR(1)過程の一般的な自己相関は、
となります。また、[ より、AR(1)過程の自己相関の絶対値は指数的に減衰していきます。コレログラムを描いてみます。
set.seed(1) d1 <- arima.sim(n=100, model=list(order=c(1, 0, 0), ar=c(0.8)), sd=1) acf(d1, main="(a) θ1=0.8, θ2=0") set.seed(1) d2 <- arima.sim(n=100, model=list(order=c(1, 0, 0), ar=c(-0.8)), sd=1) acf(d2, main="(a) θ1=0.8, θ2=0")
コレログラムを描くacf()関数とarima.sim()関数は以前に説明していますのでここでは割愛します。AR(1)過程の自己相関の絶対値は指数的に減衰していくことが、(a)と(b)からよくわかると思います。AR(1)過程のコレログラムはの符号によって、減衰していくことが確認できます。
AR(1)過程を一般化したp次のAR過程AR(p)はこのように記述されます。
AR(p)過程はy_{t} を定数と自身のp期過去の値に回帰したモデルになります。AR(1)同様にAR(q)もパラメータにより定常となるか非定常となるか変わってきます。定常AR(p)過程の性質は、
であり、特にはユール・ウォーカー方程式と呼ばれます。そして、自己相関が指数的に減衰していきます。
ここで、AR(2)過程のユール・ウォーカー方程式は、このようになります。
これに、を代入し、とから
が得られます。これを変形すると、
となります。次に、を代入すると、
となり、 を求めることができます。AR(2)過程の場合は、特にの一般的な
という2次方程式が異なる2つの解をもつとき、その解の逆数を、とすれば
で自己相関係数が得られます。
AR(p)の場合、からまでは、ユール・ウォーカー方程式と、から次の連立方程式を解いて求めることができます。
AR(2)過程のコレログラムを図示します。
set.seed(1) d3 <- arima.sim(n=100, model=list(order=c(2, 0, 0), ar=c(0.5, 0.35)), sd=1) acf(d3, main="(a) θ1=0.5, θ2=0.35") set.seed(1) d4 <- arima.sim(n=100, model=list(order=c(2, 0, 0), ar=c(0.1, 0.5)), sd=1) acf(d4, main="(a) θ1=0.1, θ2=0.5") set.seed(1) d5 <- arima.sim(n=100, model=list(order=c(2, 0, 0), ar=c(0.5, -0.8)), sd=1) acf(d5, main="(a) θ1=0.5, θ2=-0.8") set.seed(1) d6 <- arima.sim(n=100, model=list(order=c(2, 0, 0), ar=c(0.9, -0.8)), sd=1) acf(d6, main="(a) θ1=0.9, θ2=-0.8")
AR(1)同様に自己相関の絶対値は指数的に減衰しています。パラメータの組み合わせによって、多様な自己相関構造が記述できます。(e)と(f)をみると、AR(2)が循環的な自己相関構造を記述できることがわかると思います。先ほどの
が共役な複素数を解にもつときに、自己相関は循環的になります。そして、その周期は
となります。これは、AR(p)過程にも拡張でき、
が共役な複素数を解にもつときにも同様の循環成分をもちます。AR(p)の自己相関は、最大個の循環成分を持つことができるのです。
時系列データ解析 05 ~ 移動平均過程
沖元先生の本の続きです。ここでは、移動平均モデルについての話からです。
まず、1次MA過程(以下、MA(1)過程)はこのようにモデル化されます。
移動平均過程は、ホワイトノイズの線形和になります。
ホワイトノイズはすべての時点において期待値が で、分散が一定の確率過程です。また、自己相関をもたないので、弱定常過程となります。
が、移動平均過程に従うことを、 とあらわします。
もっとも基本的な弱定常過程は
ですから、移動平均過程はこの過程に、 という項が追加されたものになります。
また、期のMA(1)過程と 期のMA(1)を比較してみます。
この二つのモデルは、 という項を共通にもちます。そのため、 と に相関が生じます。
そして、MA(1)過程は、弱定常過程と比べて、 というパラメータが多くなっています。このパラメータが、自己相関の強さを決定づけます。
MA(1)過程の確率変動は、ホワイトノイズ によって決まります。まず、 が決まり、続いて が決まっていきます。沖本先生の本では、具体例として、
というMA(1)過程で、 、 、 とすれば、
という順番で が決められることが示されています。
ここで、 を正規ホワイトノイズとして、それぞれのパラメータの組み合わせたMA(1)をグラフ化してみます。
Rを使って、シミュレーションをしてみます。Rにはさまざまなツールが用意されていまして、ここではARIMAを例にMA(1)過程をみていきます。ちなみに、ARIMA過程はこのようなコードで記述します。ARIMA過程そのものについては次回以降に説明します。
d <- arima.sim(n=100, model=list(order=c(2, 0, 4), ar=c(0.1, 5), ma=c(-0.2, 0.3, 0.4, -0.5)), sd=1)
arima.simの引数について説明します。n=100がシミュレーションの数です。今回の話の流れでは、時系列のデータを まで実験してみるということです。
第2引数は、model=list()となっていますが、中身をみていきます。order=()の引数は、自己回帰過程、和分過程、移動平均過程の次数になります。自己回帰過程、和分過程は後述します。ar=()の引数は、係数で、ma=()も同様です。
第3引数については、分散の大きさといいますか、上の例では分散も標準偏差(標準誤差)も です。
それでは、シミュレーションしてみます。沖本先生の例にならって6パターンにします。
ついでにコードも記述します。
set.seed(1) d1 <- arima.sim(n=100, model=list(order=c(0, 0, 1), ma=c(0.2)), sd=1) plot(d1, main="(a) μ=0, θ=0.8, σ=1") set.seed(1) d2 <- arima.sim(n=100, model=list(order=c(0, 0, 1), ma=c(0.5)), sd=0.5) + 2 plot(d2, main="(b) μ=2, θ=0.5, σ=0.5") set.seed(1) d3 <- arima.sim(n=100, model=list(order=c(0, 0, 1), ma=c(0.3)), sd=2) - 2 plot(d3, main="(c) μ=-2, θ=0.3, σ=2") set.seed(1) d4 <- arima.sim(n=100, model=list(order=c(0, 0, 1), ma=c(-0.3)), sd=1) plot(d4, main="(d) μ=0, θ=-0.3, σ=1") set.seed(1) d5 <- arima.sim(n=100, model=list(order=c(0, 0, 1), ma=c(-0.5)), sd=0.5) + 2 plot(d5, main="(e) μ=2, θ=-0.5, σ=0.5") set.seed(1) d6 <- arima.sim(n=100, model=list(order=c(0, 0, 1), ma=c(-0.8)), sd=2) - 2 plot(d6, main="(f) μ=-2, θ=-0.8, σ=2")
ar=()については省略しています。plot()はグラフに表示するコマンドです。main=""はグラフのタイトルのようなものです。set.seet(1)は、乱数種を指定して乱数を発生させる関数です。すべて同じ乱数を発生させてシミュレーションしています。
グラフ化するとこうなります。
グラフから確認できることは、系列が の周りを変動していることです。つまり、MA(1)過程の期待値は になります。
次にMA(1)過程の分散は、撹乱項 の分散 に等しいと既に説明しました。しかし、グラフを見ると分かるとおり、撹乱項の分散が同じでも若干変動幅が異なることが分かると思います。
つまり、MA(1)過程分散は、撹乱項の分散よりも大きくなるのです。
したがって、MA(1)過程の分散は だけ、撹乱項の分散よりも大きくなります。
また、グラフの滑らかさは が大きくなるにしたがって、より滑らかになります。(a)が一番滑らかであり、(f)が一番ギザギザしているます。これは、MA(1)過程の自己相関が でないためです。MA(1)過程をもう一度見てみましょう。
が 正の場合、 の と の が同じ正の符号になるため、 と が同じ方向に動く傾向をもちます。
その結果、1次の正の自己相関が生じて、その自己相関は の値が に近づくほど強くなります。
逆に、 が負の場合は、 と は逆に動く傾向があり、1次の負の自己相関が生まれます。そのため、グラフはよりギザギザになります。
次に、MA(1)過程の自己共分散を求めます。
これは、ホワイトノイズ の 次の自己共分散が であり、分散が であることから導けます。
よって、MA(1)過程の1次自己相関を求めると、
となります。MA(1)過程の自己相関が のとき、 になります。したがいまして、1次の自己相関の絶対値が より大きいMA(1)過程はモデル化できません。
MA(1)過程の2次以降の自己共分散は、
となります。つまり、MA(1)過程の2次以降の自己相関は ということです。そのため、MA(1)過程は1次の自己相関をモデル化できますが、2次以降の自己相関を記述することはできません。
以上のとおり、期待値も分散も によらず、定常性の性質を満たすことがわかりました。
最後に、MA(1)過程のコレログラムを確認してみます。まずRのコードを記載しておきます。
set.seed(1) d1 <- arima.sim(n=100, model=list(order=c(0, 0, 2), ma=c(0.2, 0)), sd=1) acf(d1, main="(a) θ1=0.8, θ2=0") set.seed(1) d2 <- arima.sim(n=100, model=list(order=c(0, 0, 2), ma=c(-0.8, 0)), sd=1) acf(d2, main="(b) θ1=-0.8, θ2=0") set.seed(1) d3 <- arima.sim(n=100, model=list(order=c(0, 0, 2), ma=c(0.8, 0.3)), sd=1) acf(d3, main="(c) θ1=0.8, θ2=0.3") set.seed(1) d4 <- arima.sim(n=100, model=list(order=c(0, 0, 2), ma=c(0.3, 0.8)), sd=1) acf(d4, main="(d) θ1=0.3, θ2=0.8") set.seed(1) d5 <- arima.sim(n=100, model=list(order=c(0, 0, 2), ma=c(0.8, -0.3)), sd=1) acf(d5, main="(e) θ1=0.8, θ2=-0.3") set.seed(1) d6 <- arima.sim(n=100, model=list(order=c(0, 0, 2), ma=c(-0.8, -0.3)), sd=1) acf(d6, main="(f) θ1=-0.8, θ2=-0.3")
acf()は自己相関関数、つまりコレログラムを表しています。先ほどのarima.sim()の中身ですが、今回はMA(1)過程のオーダーを2にしていますので、ma=c()中に指定する係数も2つになっています。
まず、それぞれの係数 [tex \theta] を見るとコレログラムが係数に応じて変化しているのがわかると思います。(a)、(b)については、1次のみ有意な自己相関があり、2次以降は有意な自己相関はありません。
一般化した 次移動平均過程は、
と表現でき、MA(q)過程と書きます。MA(q)過程は、現在とq期間の過去のホワイトノイズの線形和に定数 を加えたものになります。
MA(q)過程の性質は、
であり、重要なことはMA過程は定常過程であり、MA(q)過程のq+1次以降の自己相関は ということです。したがいまして、q次の自己相関構造をモデル化するには、q個のパラメータが必要になります。長期間の自己相関のモデル化はあまりに多くのパラメータが必要になるため、望ましいことではありません。
次回は自己相関過程の話に移ります。