関数とは何か – その歴史とプログラミングと機械学習

機械学習技術 人工知能技術 プログラミング技術 デジタルトランスフォーメーション 深層学習 自然言語処理 ITシステム 機械学習における数学 データの情報幾何的アプローチ 本ブログのナビ
関数について

関数は、一般的に、ある集合内の各要素に対して、別の集合内の唯一の要素を割り当てる規則として数学的に定義されるものとなる。このとき、最初の集合は「定義域」と呼ばれ、関数が適用される値の範囲を表す。二つ目の集合は「値域」と呼ばれ、関数によって得られる値の範囲を表す。

例えば、以下のような関数を考えてみる。

\[f(x) = x^2\]

この関数は、実数の集合を定義域とし、正の実数の集合を値域とする。つまり、この関数には任意の実数を入力することができ、それに対応する唯一の正の実数が出力されるものとなる。

このように、数学的には関数は定義域と値域の二つの集合を持ち、定義域内の各要素に対して値域内の唯一の要素が対応する規則として定義される。このとき、一つの値に対して複数の定義がある場合、それは関数ではない。

このような数学的な定義は、関数が数学以外の分野でも広く使用されており、関数が何を表しているかを明確にするための重要な概念となる。

なお、関数の議論をする上でベースとなる集合論に関しては”集合論の概要と参考図書“に概要と参考図書について述べているのでそちらを参照のこと。

関数の歴史 – 関数という概念はどのようにして誕生し、発展してきたのか

現在の関数の定義は以下のようなものとされている「XとYを空でない集合とせよ、任意のx∈Xに対して、ただ一つのy∈Yが対応している時、関数f:X→Yが定まったといい、y=f(x)と記す」これは対応としての概念(つまり写像概念)を基礎に置いたアプローチとなる。この関数という概念は、17世紀に数学者のゴットフリート・ライプニッツとアイザック・ニュートンによって発明された。

それ以前の数学では、数値のみを扱い、ギリシア時代より「比例」という概念はあったが、変数の概念は存在していなかった。これが16世紀になると、数学者ジョルダーノ・ブルーノが、数値の変化を表す「変化量」という概念を導入し、更に、17世紀には、フランスの数学者ルネ・デカルトが、座標系を用いて関数を表す方法を提唱し、これらが現代的な関数の基礎となっていった。

これらの概念を引き継ぎ、17世紀にライプニッツは、微積分学を考える上で、ある量(引数)を与えたときに、別の量(関数値)を返す規則として関数を定義した。また、ニュートンは、代数方程式を解くために関数の考え方を用いた。ライプニッツとニュートンはそれぞれ、ある変数の値に応じて別の値を返す関係を表すために、新しい記法と概念を導入し、この関係を表すために、今日我々が使っているような関数の記号(f(x)など)を使い、関数の性質を研究した。

その後、18世紀には、レオンハルト・オイラーやジョゼフ・ルイ・ラグランジュなどの数学者が、関数の性質をさらに詳しく研究し、関数解析や微積分学などの分野を発展させた。彼らは、関数を代数的な式ではなく、幾何学的な曲線や曲面として捉え、微積分学や微分方程式の解法に関数の考え方を応用した。

19世紀に入ると、関数論の発展が進み、アーベル、ガロア、ワイエルシュトラス、リーマンなどの数学者たちが、関数の性質や理論を研究した。彼らは、解析的な関数、代数的な関数、トポロジー的な関数など、多様な種類の関数を考え、数学の多くの分野で関数の理論を応用した。

20世紀に入ると、関数の概念はさらに発展し、コンピュータサイエンスの分野でも関数の考え方が重要な役割を果たすようになった。現代の数学やコンピュータサイエンスでは、関数の理論は非常に重要な役割を果たしており、関数に関する研究は今もなお進んでいる。

この「関数」や無限級数を用いて、自然科学や工学、経済学などの多くの分野での数学的な問題を解決することを研究する学問が、解析学と呼ばれるものとなる。

解析学は、微積分学、実解析学、複素解析学、関数解析学などの分野に分けられる。微積分学は、関数の微分や積分を研究する分野であり、物理学や工学などの応用分野でも重要な役割を果たしている。実解析学は、実数に関する解析を研究する分野であり、関数の収束や連続性、微分可能性などを扱う。複素解析学は、複素数に関する解析を研究する分野であり、特に複素関数の微分や積分を扱う。関数解析学は、無限次元の関数空間や作用素についての解析を扱う分野であり、量子力学や偏微分方程式の研究に応用されている。

関数とプログラミング

関数型言語(1)“等でも述べているようにプログラミングにおいて、関数はプログラム内で再利用可能なコードブロックであり、特定の処理を実行するために呼び出されるものとなる。関数は、プログラムの構造を分割し、複数の関数を組み合わせることで、複雑な処理を実現することができる。

プログラミング言語によって、関数の定義方法や使用方法が異なるが、一般的には以下のような特徴を持つ。

  • 名前と引数:関数は名前を持ち、呼び出し時に引数を指定することで処理を実行する。引数は、関数に与える入力値であり、関数内で処理される。
  • 処理の定義:関数は、処理を実行するためのコードブロックを持つ。このコードブロックは、関数が呼び出されたときに実行される。
  • 戻り値:関数は、呼び出し元に対して結果を返すことができる。この返り値は、呼び出し元で利用することができる。

関数の定義方法は、プログラミング言語によって異なるが、例えばPythonでの関数の定義例は以下のようになる。

def add_numbers(a, b):
    return a + b

この関数は、「add_numbers」という名前を持ち、引数として「a」と「b」を受け取る。関数内では、aとbを足した結果を返す。これを呼び出す場合は、以下のようにする。

result = add_numbers(2, 3)
print(result)

この場合、関数は「2」と「3」を引数として受け取り、それらを足した結果である「5」を返す。この結果は、resultに代入され、最終的には「5」と出力される。

関数を使うことで、同じ処理を繰り返し書く必要がなくなり、プログラムの保守性が向上するという利点がある。また、複雑な処理を関数に分割することで、プログラムの可読性が向上するという利点もある。

関数とは、数学やプログラミングなどの分野で、一つの入力に対して一つの出力を返す操作や処理のことを指す。関数は、入力値を受け取り、その入力値に基づいて計算や処理を行い、最終的な結果を出力する。

数学において、関数は一般に f(x) のように表される。ここで、x は関数に入力される値であり、f(x) はそれに対応する出力の値を表す。たとえば、f(x) = x^2 という関数は、入力された値 x を二乗して、その結果を出力する関数となる。

プログラミングにおいても、関数は同様に定義される。プログラムの中で関数は、処理をまとめたブロックのようなものであり、必要に応じて呼び出される。関数には、引数と呼ばれる入力値を渡すことができ、関数内でそれを使って処理を行った結果が、戻り値として返される。たとえば、次のような Python の関数を考えてみましょう。

def square(x):
    return x * x

この関数は、引数として x を受け取り、x の二乗を計算してその結果を返す。この関数を使って、square(3) と呼び出すと、9 という値が返される。

関数には、様々な種類がある。たとえば、引数を受け取らない関数、複数の引数を受け取る関数、戻り値を返さない関数、戻り値のない関数、再帰的な関数などがある。また、関数の中で他の関数を呼び出すこともできる。関数を上手く使うことで、プログラムの処理を簡潔にまとめたり、重複する処理を減らすことができる。

関数と人工知能について

関数は、機械学習”最適化の数学“で述べられているような機械学習の最適化においても重要な役割を果たす。以下に、関数がどのように人工知能技術に利用されているかについて述べる。

  • 活性化関数

人工ニューラルネットワークにおいて、活性化関数は入力値を非線形な出力値に変換するために使用される。例えば、シグモイド関数やReLU関数がよく用いられる。活性化関数は、ニューロンの出力を決定するために使用され、多層ニューラルネットワークにおいては、複数の活性化関数を組み合わせて複雑な処理を実現する。

  • 損失関数

機械学習において、損失関数は、予測値と正解値の誤差を計算するために使用される。損失関数は、学習中に最小化されるべき目的関数として使用される。代表的な損失関数には、平均二乗誤差や交差エントロピー誤差がある。

  • 最適化関数

機械学習において、最適化関数は、モデルのパラメータを更新するために使用される。最適化関数は、損失関数を最小化するようにパラメータを更新することで、モデルの学習を実現する。代表的な最適化関数には、確率的勾配降下法やAdamがある。

  • 特徴量エンジニアリング

機械学習において、特徴量エンジニアリングは、データから有用な特徴量を抽出するための処理です。この処理には、さまざまな関数が利用されます。例えば、テキストデータの場合は、単語の出現頻度やtf-idfなどの関数が用いられます。

  • クラス分類器

機械学習において、クラス分類器は、データを複数のクラスに分類するために使用る。例えば、ロジスティック回帰やSVMなどの分類器がある。これらの分類器は、入力値とパラメータを組み合わせた関数として実現されている。

これらの様々な関数を用いることで、機械学習および人工知能技術は発展してきた。以下にこれら関数に関する参考図書を並べる。

関数に関する参考図書

まず関数に関する初歩的な参考図書として「関数とはなんだろう―三角関数から複素関数・超関数まで」がある。

これは三角関数、対数関数、複素関数、汎関数、超関数などさまざまな関数についての話題が述べられた数学の入門書となる。内容は以下のようになる。

第1章 三角関数がわかる
第2章 指数関数がわかる
第3章 対数関数がわかる
第4章 複素関数がわかる
第5章 汎関数がわかる
第6章 超関数がわかる
第7章 無限がわかる
関連図書

次にもう少し専門的な関数に関する参考図書としては「関数とは何か」がある。

これは関数概念の歴史的な発展を可能な限り史実に忠実に考察し,かつ,現代の解析学の学習者・研究者の関心に応えるように配慮し,現代数学的な視点を加味した記述を試みたもので内容は以下のようになる。

関数とは何か 岡本 久、 長岡 亮介
	第一部 おおまかな流れ
		第1章 数学史の難しさについて
			1.1 歴史的由来を探ることの難しさ
			1.2 歴史を評価することの大切さと難しさ
			1.3 第一発見者問題について
			1.4 歴史的評価の弁証法
			演習問題
		第2章 関数
			2.1 関数概念のはじまり
			2.2 本格的な解析学の誕生 オイラーの登場
			2.3 振動弦論争
			2.4 オイラーの新しい関数概念
			2.5 フーリエの革命
			2.6 ディリクレの解析学への貢献とその影響
		第3章 微積分法の合理化と極限概念
			3.1 基礎を欠いた微積分法?
			3.2 連続性
			3.3 導関数の定義のなかった解析学
			3.4 微積分法の合理化
			演習問題
	第二部 各論
		第4章 解析学の創始者 オイラー
			4.1 オイラーの位置付け
			4.2 オイラーの業績
			4.3 オイラー全集について
			演習問題
		第5章 解析学の緻密化
			5.1 解析学の基礎
			5.2 ラグランジェの貢献
			5.3 ボルツァーノの貢献
			5.4 コーシーの貢献
			5.5 アーベルの貢献
			5.6 その他
			演習問題
		第6章 フーリエ級数 解析学の新展開
			6.1 フーリエ級数とは
			6.2 フーリエ級数の由来
			演習問題
		第7章 フーリエ級数の収束
			7.1 フーリエ級数の収束 : ディリクレ
			7.2 フーリエ級数の収束 : 様々な十分条件
			7.3 フーリエ級数論の意義
			7.4 フーリエ展開の一意性
			演習問題
		第8章 連続だが至る所微分不可能な連続関数とその
			8.1 連続性と微分可能性
			8.2 リーマンの不連続関数
			8.3 ワイエルシュトラスの微分不可能関数
			8.4 高木関数とその周辺
			8.5 ペシコブィッチ型の微分不可能関数
			8.6 その他の話題
			8.7 原始関数
			8.8 解析関数
			演習問題
		第9章 解析学のもう一つの流れ
			9.1 一次補間(線形補間)
			9.2 対数と補間
			9.3 補間とは
			9.4 ニュートン補間
			9.5 ラグランジェ補間とルンゲ現象
			9.6 補間と補外
			9.7 パースカラi
			9.8 九章算術
			9.9 円弧
			9.10 ワイエルシュトラスの多項式近似定理、ベルンシュタイン多項式
			9.11 ワイエルシュトラスの定理の精密化等、掛谷の定理
			演習問題
		付録
			A 複素関数論の歴史
				A.1 虚数から複素数へ
				A.2 微積分と虚数
				A.3 コーシーの複素積分論
				A.4 コーシーの複素積分論の後期の展開
			B 常微分方程式
				B.1 初期の微分方程式
				B.2 コーシーとペアノ
				B.3 南雲道夫の定理
			C ギブス現象
				C.1 ギブス現象小史
				C.2 ギブス現象を回避するには
			D 様々な定理
				D.1 ワイエルシュトラウスの定理の周辺
				D.2 メンショフの定理
				D.3 マズルキェヴッチの定理の証明
				D.4 項別積分について
				D.5 微積分の基本定理
				D.6 楕円の円長
			E 関数の定義の変遷
			F 本書に登場する主な主人公の生涯
			G 巻末演習問題の解答

次に、プログラミングと関数の観点から見た参考図書として、元祖関数型言語であるLISPの参考図書「初めてのLisp関数プログラミング

これは関数型言語の元祖であるLISPを使った関数型プログラミングについてまとめられたもので内容は以下のようになる。

初めてのLisp関数プログラミング
	第1章 関数プログラミングとは何か - そして、それがなぜ難しいのか
		1.1 関数型プログラミングとは
			1.1.1 純粋関数と参照透過性
			1.1.2 副作用
			1.1.3 関数型プログラミングの概観
		1.2 関数型プログラミングの歴史
			1.2.1 関数型プログラミング黎明期(1930〜1960年代) -ラムダ計算の誕生からLispへ
			1.2.2 関数型プログラミング揺濫期(1970年代)- Lisp v.s. MLの戦争
			1.2.3 関数型プログラミング発展期(1980年代) - AIによる黄金時代
			1.2.4 関数型プログラミング雌伏期(1990年代) - Lispの雌伏とHaskellの誕生
			1.2.5 関数型プログラミング再生期(2000年代) -F#やScalaによる新たな時代に
			1.2.6 関数型プログラミング言語第2次成長期(2010年代) -IoT時代の関数型へ
		1.3 関数型プログラミングでは何が嬉しいのか
			1.3.1 再利用がしやすい
			1.3.2 並列処理に向いている
			1.3.3 バグが少ない
			1.3.4 テストがしやすい
			1.3.5 コードの最適化/形式手法の適用/コードの自動制せに向いている
			1.3.6 動的プログラミングができる-抽象的なプログラミングができる
			1.3.7 その他嬉しいところ
		1.4 関数型プログラミングはなぜ難しいのか
			1.4.1 変数が使えない→破壊的代入を行う→副作用のないプログラム
			1.4.2 代入文が使えない→破壊的代入文→副作用のないプログラム
			1.4.3 配列が使えない→ミュータブルなデータ構造→副作用のないプログラム
			1.4.4 再帰プログラミングがしにくい→副作用のないプログラム
			1.4.5 連続的な関数適用がしにくい→副作用のないプログラム
			1.4.6 高階関数が難しい→関数型プログラミングの便利で難しい機能
			1.4.7 評価戦略が面倒→関数型プログラミングの便利で難しい機能
			1.4.8 他の機能が難しそう→関数型プログラミングの便利な機能
			1.4.9 関数型の設計方法がわからない
			1.4.10 パラダイムシフトが大変
			1.4.11 関数型プログラミングは難しくない
		1.5 関数型プログラミングを使いこなすには
			1.5.1 副作用のないプログラムのために
			1.5.2 関数型プログラミングの便利な機能のために
			1.5.3 不純関数型プログラミングの勧め
			1.5.4 日関数型プログラミング言語での関数型プログラミングの勧め
		1.6 まとめ
	第2章 関数型プログラミングほ学ぶためのLisp超入門
	第3章 関数型プログラミングの基本
	第4章 プログラムパラダイムの比較
	第6章 関数型プログラミングの演習
	LISP

さらにweb技術の中心にあるJavascriptでの関数プログラミングの参考図書としては「Javascript関数型プログラミング」がある。

本書ではJavascriptをベースとした関数プログラミングについて述べられている。内容は以下のようになる。

■Part1 発想の転換とキーコンセプト

第1章 関数型で思考する
1.1 関数型プログラミングを学ぶと役に立つのか?
1.2 関数型プログラミングとは何か
1.3 関数型プログラミングの利点
1.4 まとめ

第2章 関数型言語としてのJavaScript
2.1 なぜJavaScriptなのか
2.2 関数型プログラミング vs. オブジェクト指向プログラミング
2.3 関数
2.4 クロージャとスコープ
2.5 まとめ

■Part 2 関数型のデザインとコーディング

第3章 データ構造の数を減らし、操作の数を増やす
3.1 アプリケーションの制御フローを理解する
3.2 メソッドチェーン
3.3 関数チェーン
3.4 コードを把握する
3.5 再帰的に考えることを学ぶ
3.6 まとめ

第4章 モジュール化によるコードの再利用
4.1 メソッドチェーンと関数パイプライン
4.2 互換性のある関数のための要件
4.3 カリー化された関数評価
4.4 部分適用とパラメータ束縛
4.5 関数パイプラインを合成する
4.6 関数コンビネータを使ってフロー制御を管理する
4.7 まとめ

第5章 複雑性を抑えるデザインパターン
5.1 命令型エラー処理の欠点
5.2 より優れたソリューション:ファンクター
5.3 モナドを使った関数型エラー処理
5.4 モナドチェーンと合成
5.5 まとめ

■Part 3 関数型のスキルを磨く

第6章 関数型コードのテスト
6.1 ユニットテストへの関数型プログラミングの影響
6.2 命令型プログラムのテストにおける課題
6.3 関数型コードをテストする
6.4 プロパティベースのテストを利用して仕様を把握する
6.5 コードカバレッジにより有効性を測定する
6.6 まとめ

第7章 関数型コードの最適化
7.1 関数実行の中身を調べる
7.2 遅延評価を使用して実行を遅らせる
7.3 "必要に応じて呼び出す"戦略を実現する
7.4 再帰と末尾呼び出し最適化(TCO)
7.5 まとめ

第8章 非同期イベント/データのための関数型手法
8.1 非同期コードの課題
8.2 Promiseによる第一級非同期処理
8.3 遅延データ生成
8.4 RxJSによる関数型プログラミングとリアクティブプログラミング
8.5 まとめ

付録A 本書で使用したJavaScriptライブラリ
A.1 関数型JavaScriptライブラリ
A.2 本書で使用したその他のライブラリ

最後に、最適化の数学に関する参考図書としては「初めての最適化」がある。

これは機械学習の中で主要な問題となる最適化問題に対する書物となり、内容は以下のようになる。

第1章 数学的準備
第2章 凸関数
第3章 最適化問題
第4章 制約つき最適化問題
第5章 線形計画問題
第6章 変分問題
第7章 制約つき変分問題
第8章 計算機利用
第9章 練習問題の解答

コメント

  1. […] 関数とは何か – その歴史とプログラミングと機械学習 […]

タイトルとURLをコピーしました