見出し画像

#29 【情報工学科】取って良かったなって講義

こんにちは、まりなです。

長らく更新が途絶えてしまいました。特段忙しかったわけでもネタが無かったわけでもないのですが完成まで辿り着ける記事が無く、気づけば7ヶ月も経ってしまいました。

さて私は現在某国立大学工学部情報工学科の学生なのですが先日3年後期を終え必要単位数を取り終えました(ちゃんと全講義単位出ていればですが…)。大学での勉強は自分が高校生の頃思っていたよりずっと楽しく、関心がある分野の知識のインプットの面白さに気づくことができました。今や「ずっと3年生でいたいなあ…」と思うようになってしまいました。研究にはまた違った楽しさがあるのかもしれませんが。

3年生を終えた今、履修して良かったなと思った講義5つを紹介してみることにしました。来期から専門科目が本格的に始まる新2年生の方や情報工学科って何やってるの?って思っている他学部他学科の方や高校生に読んでもらえると嬉しいです。


1. アルゴリズムとデータ構造

この講義を受けたのは2年の前期でした。まさに情報工学、といった内容で受けていて楽しかったのを覚えています。情報工学徒でない方には「アルゴリズム」も「データ構造」もあまりイメージがつかない言葉かと思います。誤解を恐れず超簡略化して説明するなら「アルゴリズム」は「問題の解き方」で、「データ構造」は「データのしまい方」です。
2010年代後半からのAIブームでAIはそれ以前に比べ出来ることが格段に増えました。それを「コンピュータが凄くなったから」だと思っている人も多いかと思いますが本質はそうではないのです。AIを支えるニューラルネットワークや深層学習といった数学的な「アルゴリズム」が凄いのです。(もちろんそういったアルゴリズムを実現できるほどコンピュータが凄くなったから、という側面もありますが…)

私が最近ハマって拝聴しているYouTubeチャンネル「ゆるコンピュータ科学ラジオ」の堀元さんの言葉を借りるなら「コンピュータ科学(情報工学)にコンピュータは必要ない」そうです。確かにその通りで、アルゴリズムを勉強したり考えたりするのに必要なのはコンピュータではなくペンと紙なんですよね。
話がAIまで飛躍しましたが「アルゴリズムとデータ構造」の内容はデータのソート(並び替え)の方法やデータの格納方法と探索、といった情報工学の基礎中の基礎的な内容です。
例えば数値データをしまっていくときに普通に一列に並べて格納すると後で「"3"はデータの中にあったっけ?」と調べるときに前から一つずつデータを見ていって探す必要があります。

これでは結構探すのに時間がかかってしまいますよね。そこでデータを「5で割った余り」ごとに列でわけて格納するとどうでしょう。データ3を探す際は「5で割った余りが3」の列だけ探せばすみます。

明らかに早く「3」が見つかる確率が上がりますよね。これを「ハッシュ法」と言います。

私の受けた講義では種々のアルゴリズムをC言語により実装するのが演習課題でこの講義のおかげでC言語の地力が付いたなと思います。

2. 数値解析

名前から内容を推測するのが難しいですよね。数学的な内容かな?と思いながら私も履修登録したのを覚えています。もちろん数学は使うのですが内容は「どうやってコンピュータに計算をさせるか」といった感じです。

例えば次のような二次方程式$${x^2 - 1 = 0}$$を解くとき、
人間なら因数分解して$${(x+1)(x-1) = 0}$$になるから$${x = ±1}$$とすぐに考えられますがコンピュータはこの解き方が苦手です。$${x^2 - 3 = 0}$$はどうでしょう。整数の範囲では因数分解できませんよね。コンピュータは因数分解できる場合/できない場合をわざわざ場合わけして解いておらず、例えば次の「二分法」というアルゴリズムで解いています。

$${f(x) = x^2 - 3}$$とおきます。
①初期値aとbを適当に定めます。ここでは$${a = 0, b = 2}$$としてみます。
②aとbの中点を計算し$${x_1}$$とします。つまり$${x_1 = (a + b) / 2}$$です。
③$${f(a)f(x_1) < 0}$$なら解は$${a}$$と$${x_1}$$の間にあるということになります。この場合$${b}$$を$${x_1}$$で置き換えて②に戻ります。
一方$${f(x_1)f(b) < 0}$$なら解は$${x_1}$$と$${b}$$の間にあるということになります。この場合$${a}$$を$${x_1}$$で置き換えて②に戻ります。
もし$${f(x_1) = 0}$$なら$${x_1}$$は解なのでそこで終了です。
今回の場合$${x_1 = (0 + 2) / 2 = 1}$$で、
$${f(a) = 0^2 - 3 = -3, f(x_1) = 1^2 - 3 = -2, f(b) = 2^2 - 3 = 1}$$
となるので、$${f(x_1)f(b) < 0}$$だから解は$${1}$$と$${2}$$の間にあると分かります。$${a = 1, b = 2}$$として②にもどります。

これを繰り返すとどんどん解の存在する範囲が半分になってゆき、真の解の値に近づいていくわけです。実際プログラムを使って二分法で計算した結果は次のようになりました。

epochs:0a:0.000000x:0.000000b:2.000000
epochs:1a:1.000000x:1.000000b:2.000000
epochs:2a:1.500000x:1.500000b:2.000000
epochs:3a:1.500000x:1.750000b:1.750000
epochs:4a:1.625000x:1.625000b:1.750000
epochs:5a:1.687500x:1.687500b:1.750000
epochs:6a:1.718750x:1.718750b:1.750000
epochs:7a:1.718750x:1.734375b:1.734375
epochs:8a:1.726562x:1.726562b:1.734375
epochs:9a:1.730469x:1.730469b:1.734375

10回の繰り返しで$${x = 1.730469}$$となりました。真の解$${x = \sqrt3 = 1.73205080757・・・}$$に近づいているのが分かりますね。この計算は次のようなプログラムで行いました。

#include<stdio.h>

/* 関数f(x)を定義 */
double f(double x){
    return x*x - 3;
}

int main(){
    double a = 0, b = 2/* 初期値を設定 */
    int times = 10/* 繰り返し回数を設定 */
    double x;
    int i;
    for(i=0; i<times; i++){/* {}の中をtimes回繰り返す */
        printf("epochs:%d, a:%f, x:%f, b:%f\n", i, a, x, b); /* 計算結果を表示 */
        x = (a + b) / 2/* xを計算 */
        if(f(a) * f(x) < 0){b = x;} /* もしf(a)f(x) < 0 ならbをxで置き換え */
        else if(f(x) * f(b) < 0){a = x;} /* もしf(x)f(b) < 0 ならaをxで置き換え */
        else if(f(x) == 0){break;} /* もしf(x)=0ならbreak(終了) */
    }

    return 0;
}

人間には複雑そうな処理に見える作業でもプログラムにすると20行ちょっとで実装できてしまうのも数値解析のアルゴリズムの面白さだと思います。

数値解析に関する過去の記事はこちら↓

行列の固有値を求める「ハウスホルダー法」というアルゴリズムとその実装を紹介しています。めちゃくちゃニッチな内容ですが良かったら読んでください。紹介した二分法も使っています。

3. 機械学習

今情報工学科に入ってくる生徒のほとんどが機械学習(AI)を勉強したくて入って来ていると思います。私もそうでした。やはり機械学習に関する講義は面白かったです。パターン認識や自然言語処理など様々な分野でのAIの活用を学ばせてもらいました。
受けてみてわかったことは「AIは数学的なアルゴリズム」だということです。世間ではなんかすごい技術やプログラムでまるで人間を模倣しているかのように「AI」という言葉が一人歩きしてしまっていますが、所詮数学的に記述できる処理なのである程度数学がわかる人には何もおそれるものではないなと感じました。

過去の機械学習に関する記事はこちら↓

k-近傍法というアルゴリズムで百合漫画の出版社を推測するAIを作ってみました。実装としてはふざけちゃいましたがk-近傍法の説明自体はちゃんとしました。

ニューラルネットワークと遺伝的アルゴリズムでマンカラというボードゲームのAIを作りました。いわゆる強化学習というAI同士を戦わせて強くしていく方法なのですが弟をボコることは出来たのか、是非読んで頂きたいです。

4. コンピュータアーキテクチャ

コンピュータアーキテクチャを学ぶと何故今世界的に半導体が不足して困っているのかが分かるようになります。「あんな『電気を微妙に通す』だけの物質が何でそんなに大事なの?」と思っている方が多いかと思いますがコンピュータの中身は半導体だらけです。
コンピュータアーキテクチャではCPU(コンピュータの脳)がどのように構成されているかを学びます。

これが講義で扱った4ビットCPUの概略図なのですが講義を受ける前は「意味わからん」だったのが講義を受けていくうちにどんどん各部が何をしているのかわかるようになっていったのが楽しかったです。
講義を受けてもう一つ良かったのがPCやスマホのスペック表を前より読めるようになったことです。コア数・クロック数・RAM容量などの数値が実感を伴って見えるようになり、購入前にスペック表を読んで悩む時間が増えてしまいました…

5. 信号処理

「信号処理の勉強をしている」と言うと9割「あの赤黄青の?」という返事が返って来ます。信号機の勉強はしていませんし、信号機が発しているのは「信号」ではなく、赤は止まれ、青は進めといった意味を持つ「記号」だよな、とよく考えています。
じゃあ「信号」って何なのと言うとコンピュータやスマホで扱うデータ全てがある意味「信号」です。画像も映像も音声も多次元の「信号」なのです。データだけではありません。実世界の「光」や「放射線」、空気の振動である「音」、速度や加速度のような物理量も「信号」です。というか人間がそれらを「信号」として扱うことで私たちの生活は便利になっています。
実世界の信号のほとんどは「連続信号」です。高校数学の言葉で言うなら「連続関数」です。t(時間)軸に対し連続的な値を持っています。しかしこれをコンピュータで扱うのは困難です。コンピュータは離散的(デジタル)な処理が得意で連続的な処理は苦手です。そのため「連続信号」を「離散信号」に変換する必要があります。それが「A/D変換(アナログデジタル変換)」です。

例えばスマホで録音をするとき、スマホは連続的な空気の振動をそのまま記録しているのではなく、とびとびの時点での空気の振動のみを記録しています。その間隔がとても狭いので(多くの場合 1 / (44.1*10^3)秒の間隔で記録しています)人間が聴く分にはまるで連続に記録しているように思えるのです。
さらに録音した音を加工したいという需要があります。ノイズ(雑音)を除去したり音の輪郭をはっきりさせて聞こえやすいようにできると便利そうです。そのために録音した音がどのような周波数(高さ)の成分を持つのか解析します。それが「フーリエ解析」です。
信号処理では録音(サンプリング)とフーリエ解析(フーリエ級数展開、フーリエ変換、離散時間フーリエ変換、離散時間フーリエ級数展開、高速フーリエ変換、z変換…)について学びます。内容はめちゃめちゃ数学です。高校で数列が苦手だった人にはなかなか苦しい内容だと思います(私がそうでした…)。でも信号処理は現実世界とコンピュータの世界のいわば橋渡し的な内容を学ぶ学問で、どこに行っても役立つ内容だと思いました。

過去の信号処理に関する?記事はこちら↓

と言ってもほとんど関係ないのですが…ギターのレコーディングを行なっています。「オーディオインターフェース」の行なっていることはまさに信号処理で、電気的なギターの信号をデジタルに変換して記録するA/D変換です。

おわりに

以上ですがここに書き切れなかった講義でためになった講義もたくさんあります。例えば個人的には解析学や線形代数、数理計画法などは面白さにたどり着くことができなかったのですがこういった基礎的な数学が上記講義の内容を真に理解するのに大切だったりするので履修しない方がいいなんてことは全くないです。
情報工学はプログラミングだけじゃないということが伝えられたのなら嬉しいです。それでは。


この記事が気に入ったらサポートをしてみませんか?