備忘録とか日常とか

学んだこととかを書きます。

k-Medoids Clusteringを実装した【python】

教師なし学習の非階層的クラスタリング手法としてk-Meansが一般的であるが、その拡張であるk-Medoidsを実装した。

動機

SIFT, SURFを使ったBOVWで何かできないかなーと考えていたが、特許の問題でSIFT, SURFが使えないと知った。(python2なら使えるのかも?)

[追記 2019/9/11]----------------------
python3 にてSIFTが使用可能なopencv-contrib もあった

pip install opencv-contrib-python==3.4.2.17

これ以降のverでは以下のエラーが出て使用できない。オプション設定してビルドし直せば使えるらしい。

error: OpenCV(4.1.0) /io/opencv_contrib/modules/xfeatures2d/src/sift.cpp:1207: error: (-213:The function/feature is not implemented) This algorithm is patented and is excluded in this configuration; Set OPENCV_ENABLE_NONFREE CMake option and rebuild the library in function 'create'

以下参考。
opencv - sift = cv2.xfeatures2d.SIFT_create() not working even though have contrib installed - Stack Overflow
pythonからopencvを使うときは大抵ビルド済みバイナリを取ってくるが、このページで履歴を追える。
あくまでビルド済みバイナリは有志によって提供されているため、non-free-algorithm使いたきゃ自分でビルドしろ、というスタンス↓
Include non-free algorithms · Issue #126 · skvark/opencv-python · GitHub

[追記終わり]-------------------------


じゃあopencvでタダで使える特徴量はあるのか調べたところ

  • BRISK
  • ORB
  • KAZE
  • AKAZE

あたりが候補らしい。KAZE以外はバイナリ特徴量ということで、何も考えずユークリッド距離によるk-meansに突っ込むと望まない結果になりそう。
対策としては以下二つくらい。

  • ユークリッド距離以外の基準を使用できるk-meansを実装する
  • k-Medoidsを実装する

距離の基準を変更したk-meansは探すといくつか実装が出てきたが、k-Medoidsを初めて聞いたのもあり、せっかくなので実装してみた。

k-Medoidsとは

k-means, k-Medoidsの考え方の発展は以下のページがわかりやすかった。
(実装もかなり参考にした)
www.dskomei.com

簡単にいうと、k-meansではサンプルの重心をクラスタ中心とするのに対し、k-Medoidsではサンプル自身をクラスタ中心とする。
k-Medoidsではクラスタ中心をcentroidではなくmedoidと呼ぶ。

1. ランダムにk個のサンプルを選択し、medoidとする
2. 全てのサンプルを最近傍のmedoidのクラスタに割り当てる
3. 各クラスタ内で、二点間の距離の総和が最小となるようにmedoidを割り当てる
4. 2, 3を、一定回数medoidを更新する or medoidの変化量が一定値以下になる まで繰り返す

というのがざっくりした流れ。

利点

  • 外れ値に強い
  • 重心を定義する必要がない

ということが挙げられる。
特に二つ目は、k-meansでは距離尺度に応じて逐一重心(平均)を定めてやる必要があるが、k-Medoidsではその必要がなくなる。

欠点

  • k-meansより計算量が多い(k-meansはO(Nk), k-MedoidsはO(N^2 k) )
  • k-means同様、初期値の影響を強く受ける

クラスタ内の平均を求めるには単純計算でrange(0, N)のループで済むのに対し、距離の総和が最小となるmedoidを選ぼうとすると二乗オーダの計算量となる。
下記の実装では行列演算で単純なループを回避することもできるようにしたが、メモリの使用量がバカにならないのでN, kが大きくなると使えない。

初期値に関してはk-meansも同じ問題を抱えており、最初に選択されたクラスタセンタが近い距離にあるとうまくいかない。
これの対策として、初期値のクラスタ中心がなるべく固まらないように選択するk-means++という方法が広く使われている。(詳細は上記サイトを参考に)
scikit-learnのk-meansはこれに加え、初期値を複数計算してその中でもっともクラスタ中心の偏りがない(=クラスタ中心とサンプルの距離の総和が最小となる)初期値を選択する、という処理が行われている。小さいデータで何回か試して見たところ、この「最も良さげな初期値を選択する」という操作でクラスタリング結果がかなり向上することがわかった。大規模な実データではどうなるか不明だが、k-means++に加えて実用上では必須テクな気がする。


そんなわけで、k-means++の初期化と初期値選択も実装した。
初期値選択は並列演算で実施できるようにしたが、言うまでもなくメモリをバカ喰いするので実際に使う際はn_jobs=1にするしかない。アーメン。
(もっと工夫すれば省メモリでうまいことできるのかもしれないが力尽きた)



k-medoids

初期化による違いやk-Medoidsの検証はこのサイトが詳しいので割愛・・・
自分で何回か試したところ、k-means++でも初期値選択を行わなければ良い結果にならないことが確認できた。
あくまで確率分布にしたがって初期化しているため、一回の初期化だけでは十分に良い結果が得られない。

BOW用ラッパーも書いたので、そちら方面で検証したいところである。

汎用ポインタ( Void * )によるキャストについて【C/C++】

汎用ポインタと呼ばれる(Void *)の用途について調べたのでメモする。(主にC言語としての用途)

任意のポインタを受けるため

これがほぼ全てだと思うが、(Void *)でキャストすれば任意のポインタを受け取り、変数に格納することができる。
型を指定せずに関数の引数として受ける際によく使われるっぽい。

void test(const void * number){
    const int * a = (int *) number;
}

でもこう書くと実質型チェックがなくなるわけだから、信頼性とか可読性の観点から言うと望ましくないような気がする・・・
現場でどれくらい使われているかは疑問です。

汎用ポインタ型はキャストしないと参照できないので注意。

共通データ型→汎用ポインタ→任意の型 変換

様々なコンポーネントで使用する共通のデータ型を定義しておき、各処理の中で好きな型に変換して利用することで、
構造体の参照渡しを統一的に表現する(?)ような使い方を見た。

typedef struct CommonInst {  /* 共通データ型を用意 */
   const void  *SomeData;  
}ST_ComInst;

typedef struct A_Struct {  /* FuncAの機能用構造体 */
  int  hoge1;
  int  hoge2;
}ST_A;

void FuncA(const ST_ComInst *Instance) {   /* 共通データ型のポインタを受け取り、Void型をかませて任意のポインタにキャストして使用 */
	const  ST_A *A_Inst= (const ST_ComInst_t *)(const Void *)Instance;
}

みたいな。
変数のスコープをうまく管理できればgetter/setterみたいなことも実現でき、オブジェクト指向ちっくにかける、と思う。
直接キャストすると何か不都合があるのだろうか。警告とか出るのかな?ちょっと不明。

mallocの戻り値

mallocの戻り値は汎用ポインタなので、なんにでもキャストできる。
キャストしない場合は汎用ポインタの変数を使用する必要があるのだろう。そんなことしないような気もするけど。


まとめると

  • 任意の型からアドレスを受け取れる(参照渡し引数に使える)
  • 何かにキャストしないと参照できない
  • 型変換の間にかませる

といった用途になるか。

キーバインドをカスタムして全能感を手に入れる【AutoHotKey, ChangeKey】

「こいつらExcel好きすきだろ・・・」と思いながら日々仕事してます。

業務時間の大部分をExcelに費やしているわけが、

  • カーソル移動が煩わしい
  • よく使うショートカットが押しにくい

という問題があったため、改善してみた。
多くの操作をキーボードで完結させることができると、クソつまんない仕事のモチベーションも多少は上がる、と思いたい。

ここでは二つのツールを使用する。

レジストリレベルで設定する「Change Key」

forest.watch.impress.co.jp

レジストリを編集してキーバインドを変えられる。非常駐なのでリソース圧迫しない。
windows7対応となっているが、2019/4/21現在でwindows10でも使用できているので問題はない。
ただし念の為レジストリのバックアップはとっておいたほうがよいかも。

www.ask-mswin.com

ChangeKeyでは特定のキーを他のキーに割り当てられる。
管理者権限でChgKey.exeを実行すると、以下のような画面が表示される。

f:id:may46onez:20190421001453p:plain:w650

ここから変更したいキーを選択し、次の画面でどのキーに変更するかを選択する。

f:id:may46onez:20190421001603p:plain:w650

自分の場合は以下のように設定している。

  • CapsLock -> 左Ctrl
  • 半角・全角 -> Esc
  • Insert -> 右windows

CapsLockはほぼ必須、というか誤爆しやすい人は使わなくても変えておくと捗ると思う。
Esc多用するときは若干遠いので、半角全角キーを変更している。IMEオンオフはCtrl+Spaceで。
Insertはまあなくてもいいけど、右手でwindowsキー押せたらうれしい場面がたまにあるので。(キーボードに右windowsがない)

AutoHotKey」で理想のキーマップを手に入れる

autohotkey.com

ご存知キーボードリマップツール。実はマウスコマンドも設定できるらしい。可能性は無限大。
こちらは常駐型となるが、それでも余りあるメリットを享受できる。
インストール後に.ahkという拡張子で書かれたスクリプトを実行することで、
設定したキーマップを使用できるようになる。

自分の要望としては、
1. ホームポジションから動かずにカーソル移動したい
2. ファンクションキー遠いのでなんとかしたい
3. ホームポジションを崩す必要があるショートカットを変更したい
という要求をまず満たしたい。

方法としては、変換・無変換のキーと同時押しを割り当てることで各種機能を実現する。
そのため変換・無変換キーを他の用途に使うことはできなくなるが、
まあ普通の人ならほぼ使わないと思う。
自分は以前の記事でこれら二つのキーにIMEオン・オフを割り当てていたので、そこを根性で矯正した。

変換・無変換は本来の機能で使わなくなるので、IMEの設定で切っておくことをお勧めする。
f:id:may46onez:20190421003954p:plain:w650

以下に自分のスクリプトを貼っておく

; ウィンドウを閉じる
!q::Send, !{F4}

; Chrome等、進む・戻る用設定
vk1D & ,::Send, !{Left}
vk1D & .::Send, !{Right}

; ウィンドウ移動
vk1C & Tab::Send, #+{Right}
; ウィンドウ操作
vk1C & i::Send, #{Up}           ; 最大化
vk1C & j::Send, #{Left}         ; 左寄せ
vk1C & l::Send, #{Right}        ; 右寄せ
vk1C & k::Send, #{Down}         ; 最小化

; 仮想デスクトップ切り替え
vk1C & f::Send, #^{Right}
vk1C & d::Send, #^{Left}

;無変換+jkil = 上下左右
;無変換+shift+上下左右 = shift+上下左右

;無変換+j→左
vk1D & j::
    if GetKeyState("shift", "P") && GetKeyState("ctrl", "P"){
        Send, +^{Left}
    }else if GetKeyState("shift", "P"){
        Send, +{Left}
    }else if GetKeyState("ctrl", "P"){
        Send, ^{Left}
    }else{
        Send, {Left}
    }
    return
;無変換+k→下
vk1D & i::
    if GetKeyState("shift", "P") && GetKeyState("ctrl", "P"){
        Send, +^{Up}
    }else if GetKeyState("shift", "P"){
        Send, +{Up}
    }else if GetKeyState("ctrl", "P"){
        Send, ^{Up}
    }else{
        Send, {Up}
    }
    return
;無変換+i→上
vk1D & k::
    if GetKeyState("shift", "P") && GetKeyState("ctrl", "P"){
        Send, +^{Down}
    }else if GetKeyState("shift", "P"){
        Send, +{Down}
    }else if GetKeyState("ctrl", "P"){
        Send, ^{Down}
    }else{
        Send, {Down}
    }
    return
;無変換+l→右
vk1D & l::
    if GetKeyState("shift", "P") && GetKeyState("ctrl", "P"){
        Send, +^{Right}
    }else if GetKeyState("shift", "P"){
        Send, +{Right}
    }else if GetKeyState("ctrl", "P"){
        Send, ^{Right}
    }else{
        Send, {Right}
    }
    return

; PageUp
vk1D & u::
    if GetKeyState("ctrl", "P"){
        Send,^{PgUp}
    }else{
        Send,{PgUp}
    }
    return

; PageDown
vk1D & o::
    if GetKeyState("ctrl", "P"){
        Send,^{PgDn}
    }else{
        Send,{PgDn}
    }
    return

; ファンクションキー置き換え
vk1C & 1::Send, {F1}
vk1C & 2::Send, {F2}
vk1C & 3::Send, {F3}
vk1C & 4::Send, {F4}
vk1C & 5::Send, {F5}
vk1C & 6::Send, {F6}
vk1C & 7::Send, {F7}
vk1C & 8::Send, {F8}
vk1C & 9::Send, {F9}
vk1C & 0::Send, {F10}
vk1C & -::Send, {F11}
vk1C & ^::Send, {F12}

; 右クリック
vk1D & 0::Send, +{F10}


ホットキー設定するだけなら単純で、::の左に登録したいキー組み合わせ、右にSend, と送信したいキーを書く。shift, ctrl, alt, windowsキーはそれぞれ修飾キーと呼ばれ、+^!#で表現する。二行目はalt + qalt + F4に置き換えている。vk1Cvk1Dはそれぞれ変換と無変換のキーを表す。


少々面倒だが、登録したホットキーと別のキーの同時押しは対応できないため、すべて登録しておく必要がある。上の例でいえば無変換+jキーで矢印左が入力できるが、shiftを押しながらの範囲選択はできない。なので::の後に場合分けを入れ、矢印キーと同時に修飾キーが押された場合をすべてホットキーとして登録している。


詳しい使用方法はwikiに書かれている。正直機能が多すぎて扱いきれる気がしない。
AutoHotkey Wiki
wikiのキーリストに各キーをスクリプト上でどう表現するかが書かれているが、少し内容が古いのでそこだけは注意。vkXXscYYみたいなキーはscYYを除いた部分を表記すれば動く。(Invalid HotKey みたいなエラーが出る)
詳細は下の記事を参照
qiita.com


自分好みのスクリプトが作れたらスタートアップに登録しておくとよい。
windowsキー+r で出る窓にshell:startupと入力し、出てくる場所に.ahkを置くだけで起動時にホットキーが有効になる。

後日談

これはこれで満足しているが、変換・無変換を多用するので使うキーボードが若干限られるという問題に直面した。スペースキーが長いものだと親指がちょっとしんどい。
realforceの新しいやつが欲しかったのにスペースキーが伸びてて悲しい・・・

「プログラムはなぜ動くのか」を読んだ

朝出社したら自分のデスクにおもむろに置いてあったので読んだ。

プログラムはなぜ動くのか 第2版 知っておきたいプログラムの基礎知識

プログラムはなぜ動くのか 第2版 知っておきたいプログラムの基礎知識

この「なぜ」シリーズは2001年から刊行されており、他にも「コンピュータはなぜ動くのか」「ネットワークはなぜつながるのか」等の書籍がある。
昔から入門とか情報工学の基礎知識を身に着けるために読まれている本らしい。

ネットワークはなぜつながるのか 第2版 知っておきたいTCP/IP、LAN、光ファイバの基礎知識

ネットワークはなぜつながるのか 第2版 知っておきたいTCP/IP、LAN、光ファイバの基礎知識



ちなみに「プログラムはなぜ動くのか」第二版の1刷は2007年なので、内容としてはかなり古い。メモリ512MBとかの時代。江戸時代かっつの。。
それでもアセンブリの基礎に触れる機会など、かなり限られた業種やニッチな趣味でもしてない限りないと思われるので勉強にはなった。ハード寄りな部分の挙動は昔から劇的に変化することもなさそうなので、多少古くても問題ないのかもしれない。

以下各章の内容とひとこと要約・感想。

1. プログラマにとってCPUとは何か

CPU内の大まかな構造とレジスタについての説明。
種々のレジスタがそれぞれどのような役割を果たし、条件分岐、繰り返し、関数呼び出し等がどのように実現されているかを簡単に解説している。突き詰めればCPUは非常に単純な処理しか行っていない、らしい。

2. データを2進数でイメージしよう

コンピュータは2進数ですべてを扱っており、そのほうが都合がいい理由などのお話。
情報系の分野に疎い人のための易しめな解説。

3. コンピュータが小数点数の計算を間違える理由

引き続き2進数の話、浮動小数点がどう表現するかなど。
情報系の分野に(略)

4. 四角いメモリを丸く使う

メモリを使ってどのようにデータを表現するか、というお話。
char, int, longのメモリ確保みたいなところから、配列の実現方法(スタック、キュー、リスト、2分木探索)等の説明。メモリーICの物理的な仕組みみたいなところも。pushとかpopとかqueueとか待ち行列とか、情報工学の基本用語なんかも解説してくれて情報量は多い。

C言語初学者はこの章を読むとポインタやメモリに関する理解が深まると思う。

5. メモリーとディスクの親密な関係

モリーに対して、ディスクはどのような役割を担うかみたいな話。
ディスク上のデータはメモリに一度格納されてからしか使えないという原則から、キャッシュ、仮想記憶(ページング方式・セグメント方式)、DLL、スタティックリンク、ディスクの物理構造(セクタ単位で扱われる)など。

中でも_stdcall呼び出しというのは初めて知った。

スタックはさまざまな場面で再利用されるメモリー領域なので、使い終わったら元の状態に戻す処理が必要になります。

このスタックのクリーンアップ処理を、何度も呼び出される関数の側で行うようにすれば、呼び出す側で行う場合よりもプログラム全体のサイズを小さくできます。

通常mainで呼び出した関数のクリーンアップ処理は呼び出し側で行われるため、何回も同じ関数を呼び出すとその分だけクリーンアップ処理部分のコードが冗長になる。じゃあ関数側に処理を書いたら節約になるじゃん、ということらしい。

計算資源の制約が厳しかった時代の涙ぐましい努力が伺えて面白かった。今でも組み込みとかでは使うのか…?
どちらかというとコンパイラとか作る人のための知識な気がする。

6. 自分でデータを圧縮してみよう

急に毛色が変わって圧縮の話。
ランレングス法、ハフマン法のアイディアから基本アルゴリズムの説明と、可逆・非可逆圧縮等の説明。
普段使っているzipのLHA圧縮がハフマン法の応用だと初めて知った。こういうの思いつける人は天才だと思う。

7. プログラムはどんな環境で動くのか

OSの偉大さを説く話。
APIを提供してくれることでハードに依存しないプログラムを作成できるということを、歴史的経緯と一緒に説明してくれる。MS-DOS時代って大変だったんだね。

さらにJava仮想マシンBIOSについても少し触れてる。Javaコンパイルバイトコード生成→OS毎のJava仮想マシン→ネイティブコードという流れでOSの違いを吸収する、とか。
ブートローダの語源がまじのブーツだったとは思わなかった。

8. ソース・ファイルから実行可能ファイルができるまで

コンパイラによって実行可能ファイルができるまでの流れの話。
ソースをコンパイルして.objファイルができ、スタートアップやライブラリからも.objを引っ張ってきてリンクして出来上がり。
実行時にDLL呼び出して使うとか。

再配置情報、スタック、ヒープなんかもこの章で解説がある。

9. OSとアプリケーションの関係

ハードを意識せずプログラムを作成できるのはOSのおかげだよ、という話。
また、Windows OSの基本機能(マルチタスクとかデバイスドライバの自動設定とか)についてちょっとだけ説明。

10. アセンブリ言語からプログラムの本当の姿を知る

Cのソースとアセンブリを見比べて、CPUが実際はどのような挙動をしているのかを見る話。この本で最も内容が濃い章かもしれない。
1章でさらっと触れた分岐や関数呼び出しの仕組みを、アセンブリ言語を追いかけながら実際に理解を深めることを目的としており、勉強になる。

研修で実際のアセンブリ(といっても超単純なプログラムだが)を見る機会はあったが、意味不明すぎて結局ちゃんと見ずにCのソースしかいじってなかった。
もう少し早く読んでおけば学ぶこともあったかもしれない。

11. ハードウェアを制御する方法

CPUやメモリと違い、外部接続のハードウェアがどのように制御されているかという話。
IN、OUT命令とポートを使ってデータのI/Oを実現している。加えて、割り込み処理やDMA(Direct Memory Access)などを解説。
組み込みの基本みたいなとこか。

12. コンピュータに「考え」させるためには

プログラムに人間的な考えや勘を盛り込んでみよう、というお話。(この章は若干の蛇足感がある…)
じゃんけんプログラムをつくるのだが、括弧つきで書いてるように、実際に考えてるわけでない。あくまで「それっぽく」動くようにするために経験に基づいてif-thenルールをひたすら盛り込んでいる。

今のAI時代に下手に「コンピュータが考える」とか「知能を実装する」とか言っちゃうと、「知能とは何か」みたいな話まで行ってしまうので、まあ昔の本ということでご愛敬である。

終わりに

教養として知っておいて損はない内容が多かった。
アセンブリ言語に興味を持つ入り口にはなるかもしれない。自分はちょっとしんどいので無理ですごめんなさい。
入門書的な扱いだが、全くIT知識のない人が読むには少々つらいかもしれない。
大学一年の電気・情報系学部の教養の授業とかで扱うといいんじゃないかな。と思いました。

応用情報技術者試験に合格したので振り返り

タイトルの通り、合格できました。午前90点、午後73点という結果に。
「わーい」と手放しに喜ぶこともできるけど、実際本番でかなり焦った部分などあるので今後のために振り返り。
しょうもない新人研修でPDCAがどうとか教わったので、それになぞらえてみる。

あくまで自分はこうだったという振り返りでしかないので、合格法を指南するものではないです。参考程度に。

結論

  • 参考書はリファレンス程度に使用し、過去問をメインで解く(なんなら参考書買わなくてもいい)
  • 午後問題はすべての分野を一問は解いてみる(そのあと絞る)
  • 午後試験過去問を、問題選択する時間を入れて本番の制限時間で解く
  • 外乱に動じない鋼の心を持って試験に臨む

Background

  • 高校からずっと理系
  • 学部で電気電子、大学院で情報工学を専攻
  • 暗記はあまり得意ではない
  • IPA試験の受験経験なし、いきなり応用情報受けてみる

自分のバックグラウンドはこんな感じ。
「基本情報はだいたい受かるし応用受けたほうがいいで」という先輩の挑発(?)にまんまと乗せられ、いきなり応用を受けてみた。人によっては応用のほうが受かりやすいという話も聞くが、午後試験が記述になるので自分には難しく感じた。


ネット上には「〇〇時間で合格!」や「午後対策はしなくていい」等の記事が散見されますが、ぶっちゃけ人によります。
がっつり業務でシステム構築等に携わっている人や情報科学出身の人は簡単に感じるかもしれないし、文系未経験SEの人には難しく感じるかもしれない。自分は普通に午後対策しました。

他の資格試験と比べても受験する層が幅広いと思うので、余計難易度は測りにくいと思う。難易度に関する評判はあまりあてにしないほうがいい。

Plan

  • 試験の約三か月前に応募、書籍購入
  • 午前対策二か月、午後対策一か月 を目安に
  • 午前・午後いずれも過去問から取り組む(重要)
  • 一日0.5 - 1時間くらい、週5時間以上を目標に


実は学生の時に一回受けようとして参考書を買ったのだが、5ページくらい読んで本棚の肥やしになっていた。
「お前それ計画破綻しとるやんけ」と言われればその通りなのだが、
ここから得られた知見が一つ

参考書を最初から読んで勉強するのは無理

ということ。
当時買ったのは公式の参考書(ただし平成28年度版)↓

平成31年【春期】/01年【秋期】応用情報技術者 合格教本

平成31年【春期】/01年【秋期】応用情報技術者 合格教本

出題範囲の各分野を網羅的に紹介・解説しており、これまでの出題傾向から最新のトピックなども取り上げられているらしい。これを読めば試験対策は万全…と思ったが、よほど忍耐力がないと半分も読み切れない。それくらい応用情報は出題範囲が広い。

なので何もわからない状態でも過去問から取り組み、間違えた問題を覚えていくという手順のほうが知識が身についた実感があるので捗る。
参考書はわからない部分を調べる辞書的な使い方が望ましいと考え、そのように運用した。というか最後らへんはググって調べてたのでもはや買う必要もないかもしれない。。

午前対策

午前の過去問は以下のアプリと過去問道場で、毎日通勤時間(40分くらい)問題を解く。
アプリは有料だが解説が見やすい&UIがシンプルで使いやすくておすすめ。
収録問題数が若干少ないので、ある程度覚えたら過去問道場でさらに固めるとなおよい。

応用情報技術者 午前 一問一答問題集 - Appliv
応用情報技術者過去問道場|応用情報技術者試験.com

午後対策

ネットで評判の緑の本で勉強。解説が充実している&問題数が多いのでおすすめ。

2019応用情報技術者午後問題の重点対策 (重点対策シリーズ)

2019応用情報技術者午後問題の重点対策 (重点対策シリーズ)

Do

  • ひたすら隙間時間で午前問題を勉強
  • 選択問題はすべての選択肢について理解することに努める
  • 午後試験は最初から問題を絞って勉強(ダメなパターン)


隙間時間って大事で、朝家出る前に10分、通勤片道で40分、昼休みに10分、とするだけで1時間使える。午前問題なら解説読む時間含めても一問3,4分程度なので、毎日15問は解ける。継続は力なり。

午前の4択問題も、全ての選択肢に対して説明できるくらいまでやりこむのがベスト。言わずもがなだが答えだけ覚えるのは良くない。
正直午前だけなら丸暗記でも解けなくはないが、午後試験に使える知識が身につかないのでやめたほうがいい。午前午後は出題形式が違うだけで範囲や深度は同じようなものです。

午前試験に関しては上記やり方でひたすら実行したが、午後試験対策の三つめはあまり良くなかった。後述。

Check

  • 午後の問題選択にてこずった
  • 一問に長く時間を使いすぎた(アルゴリズム)
  • その結果、解答欄を間違える凡ミスを犯した(アルゴリズム)
  • 外乱に集中を乱された

午前試験

午前に関しては特に問題なく解けた。
パッと見わからなくても、頑張って考えて2択ぐらいまで絞り込んだ結果正解した問題も多かったので、
「諦めたらそこで試合終了ですよ」の精神を胸に秘めておくとよい。

午後試験

午後は選択問題であり、10問ある中から最も点を取れそうな分野の問題を4問選ぶ。(+必答問題一問で計5問解く)
自分はハナから5分野(アルゴリズム、システムアーキテクチャ、ネットワーク、組み込み、情報システム開発)に絞って勉強し、本番で4つ選ぼうとしていたのだが、その考えは甘かった。本番で解けないとめちゃくちゃ焦ってしまう。

個人的な感想でいうと、ネットワークは前提とする知識が多いため高得点が難しいように感じる(業務で扱っている人は余裕だと思う)。本番で「あ、これ無理」ってなったので、必然的に勉強していた残り四つの分野に取り組むことになるのだが、システムアーキテクチャも問題文が全然頭に入ってこない。
苦し紛れにプロジェクトマネジメントを解いて結果事なきを得たが、午後は得点率が公表されないので真相は闇の中である。。

得意としていたアルゴリズムも焦りのせいですんなり解けず、他問題を手早く済ませて時間ギリギリまで粘ってやっと解けたが、小問の解答欄を間違えるという凡ミスを犯した。焦りは本番最大の敵である。


こういう不測の事態のためにも、全ての分野の問題を一度は解いておくことが大事だと感じた。
あと各分野の勉強はしても、自分が得点できそうな分野の問題を時間内に見極める訓練もあったほうがよく、そのためには一度時間を図って午後問題を解いてみることをおすすめします。


余談だが、本番になるといろんなものが集中力を削いでくる。具体的には開始30分でいびきかいて寝るやつとか、尋常じゃないスピードで退出していくやつとか(たぶんどっちも問題解けてない)。
そういった外乱に惑わされずに問題を解く心構えをしておくと良いかもしれない。

Action

  • 高度区分試験受ける…?

高度試験まで受けるかどうか未定だが、応用情報取得後2年くらいは高度区分の午前試験が免除になるので、受けてみてもいいかもしれない。でもあんまり旨みを感じない…


以上、駄文を読んでいただき感謝します。これから受験予定の方は頑張ってください!