ひらめの日常

日常のメモをつらつらと

Scalaで競技プログラミング: 標準入力周りで調べたこと

複数変数の初期化

例えば、1 2 3のように空白区切りで3つの標準入力を受け取るために、次のようなコードをよく書きます。

val sc = new Scanner(System.in)
val v, e, r = sc.nextInt()

これは左辺の変数の個数分、右辺の式が評価されているようです。(公式ドキュメントが見当たらないので、探しています...)

scala> val a, b, c = 1
val a: Int = 1
val b: Int = 1
val c: Int = 1

scala> val a, b, c = util.Random.nextInt()
val a: Int = 2127446030
val b: Int = 1199584050
val c: Int = 638157382

これは ScannernextInt() を使うことによって実現できるのですが、Scalascala.io.StdIn.readInt() ではできません。

Scanner (Java Platform SE 8)

Scala Standard Library 2.13.3 - scala.io.StdIn

なぜかというと、ScalareadInt() は「readLine() した結果に対して toInt を呼び出している」だけだからです。なので空白区切りの入力に対しては readLine().split(" ").map(_.toInt) のように文字列を分割する処理を入れなければいけません。readInt() の内部実装は以下の通りです。

/** Reads an int value from an entire line of the default input.
 *
 *  @return the Int that was read
 *  @throws java.io.EOFException if the end of the
 *  input stream has been reached.
 *  @throws java.lang.NumberFormatException if the value couldn't be converted to an Int
 */
def readInt(): Int = {
  val s = readLine()
  if (s == null)
    throw new java.io.EOFException("Console has reached end of input")
  else
    s.toInt
}

複数行の読み込み

この記事を参考にしました。

qiita.com

AOJなどでは、行数が与えられずに、「与えられた行数分処理しなさい」という問題があります。行数が与えられればその数だけループ回せば良いのですが、そうではないので困ってしまいますね。(例えばこの問題などです:Aizu Online Judge

その際はio.Source.stdin.getLines() を呼び出すことで、次の入力がある限りは読み込み続けてくれます。

Scala Standard Library 2.13.3 - scala.io.Source

for (l <- io.Source.stdin.getLines()) {
  val arr = l.split(" ").map(_.toInt)
  ...
}

Array.fill

サイズnの入力を受け取り、配列として初期化する際に、次のようなコードをよく書きます。

val a = Array.fill(n)(sc.nextInt())

これでn回の入力を受け取っているのですが、これは Array.fill の第二引数が名前渡し引数(call-by-name)になっているからです。そのおかげで、第二引数がn回呼び出されることになり、意図した挙動になります。

Scala Standard Library 2.12.4 - scala.Array

By-name Parameters | Tour of Scala | Scala Documentation

By-name parameters are evaluated every time they are used. They won’t be evaluated at all if they are unused. This is similar to replacing the by-name parameters with the passed expressions.

Array.fill の内部実装は以下の通りです。

  /** Returns an array that contains the results of some element computation a number
   *  of times.
   *
   *  Note that this means that `elem` is computed a total of n times:
   *  {{{
   * scala> Array.fill(3){ math.random }
   * res3: Array[Double] = Array(0.365461167592537, 1.550395944913685E-4, 0.7907242137333306)
   *  }}}
   *
   *  @param   n  the number of elements desired
   *  @param   elem the element computation
   *  @return an Array of size n, where each element contains the result of computing
   *  `elem`.
   */
  def fill[T: ClassTag](n: Int)(elem: => T): Array[T] = {
    if (n <= 0) {
      empty[T]
    } else {
      val array = new Array[T](n)
      var i = 0
      while (i < n) {
        array(i) = elem
        i += 1
      }
      array
    }
  }

コメントや例が書いてあり、丁寧だと感じました。

Note that this means that elem is computed a total of n times

Scalaで競技プログラミング: ダイクストラ法

C++で書いたライブラリをScalaで書き直しています。ダイクストラ法全体として以下のようなコードになりました。

case class Edge(to: Int, w: Long)

case class Graph(n: Int) {
  val g: Array[Array[Edge]] = Array.fill(n)(Array.empty)

  def push(from: Int, edge: Edge): Unit = {
    g(from) :+= edge
  }

  def dijkstra(start: Int, Inf: Long = 1e18.toLong): Array[Long] = {
    val d = Array.fill(n)(Inf)
    d(start) = 0
    val queue = mutable.PriorityQueue.empty[(Long, Int)](Ordering.Tuple2[Long, Int].reverse)
    queue.enqueue((0, start))

    while (queue.nonEmpty) {
      val (minCost, minV) = queue.dequeue()
      if (d(minV) >= minCost) {
        g(minV).foreach { e =>
          if (d(e.to) > d(minV) + e.w) {
            d(e.to) = d(minV) + e.w
            queue.enqueue((d(e.to), e.to))
          }
        }
      }
    }
    d
  }
}

今回の主な新情報は PriorityQueue についての以下の行です。

 val queue = mutable.PriorityQueue.empty[(Long, Int)](Ordering.Tuple2[Long, Int].reverse)

Scala Standard Library 2.12.0 - scala.collection.mutable.PriorityQueue

元々ScalaPriorityQueue は降順で管理されています。今回は、(コスト: Long, 頂点id: Int) というタプルを PriorityQueue で管理します。その際は以下のように順序が規定されています。最初に第一要素を比べ、同じだったら第二要素を比べます。

def compare(x: (T1, T2), y: (T1, T2)): Int = {
  val compare1 = ord1.compare(x._1, y._1)
  if (compare1 != 0) return compare1
  ord2.compare(x._2, y._2)
}

ダイクストラで用いる際には、ある頂点までのコストが軽い順に並べ替えられていた方が嬉しいので、昇順になっている必要があります。そこで、 Ordering を引数に与えることで、並べ替えの順序を指定してあげます。降順の逆の昇順に並べたいので、Ordering.Tuple2[Long, Int].reverse を指定することになります。

他にも dequeue がpopするだけでなく要素も返すところは C++ と異なりますね。(むしろ返す方が自然だとは思いますが...)

AOJの問題でverifyしました。入出力含めた全てのコードはこちらをご覧ください。

github.com

JetBrainsのIDEを使うならSettings Repositoryを活用しよう

JetBranisのIDEの設定を、IDE間で共通化したい...!と思った人向けの記事です。 結論としてはこれを読めば解決する話ではあるのですが。 pleiades.io

JetBrainsのIDEって使いやすくて高機能で便利ですよね。自分はこれなしでは開発できない体になってしまいました。社会人は一部無料で、学生であればなんと全て無料で使うことができます。すごいですね

blog.jetbrains.com

こうしてJetBrainsの恩恵に授かっていると、ScalaIntelliJで、C++はCLionで、iOSはAppCodeで...のように複数のIDEを使い分けることになります。こうなったときに毎回設定を0からやるのは非常に面倒ですよね。以前自分は設定ファイルをexportして、それを他のIDEで取り込むことをやってました。そうなると、一つのIDEでキーマップを更新すると他が追従せずに混乱したり、会社のPCで新たに設定した項目が私用のPCには反映されていなかったりして大変です。

そこで冒頭に添付した記事を参考にしてSettings Repositoryを使いましょう。

pleiades.io

これを使えば、GitHub上に設定ファイルをまとめておき、全てのIDEはそこを一箇所参照することで同期的に設定を管理することができます。もう「あっちでは設定してあるのに、もう片方のIDEでは設定してないよ...」といったことは起きないのです。

快適なJetBrainsライフを送りましょう〜〜

Scala: Ordered[T] と Ordering[T] の違い

結論

  • Ordered[T] は自身に継承し、比較可能にする
  • Ordering[T] は自身を変えることなく、外側から変換を提供する

gist.github.com

Ordered[T]

例えば、単純に比較するだけのクラスを作る。このクラスは Ordered[T] を継承していて、compareメソッドを実装する必要がある。

参考: Scala Standard Library 2.13.5 - scala.math.Ordered

case class MyOrderedNum(value: Int) extends Ordered[MyOrderedNum] {
  override def compare(that: MyOrderedNum): Int = {
    if (this.value < that.value) -1
    else if (that.value < this.value) 1
    else 0
  }
}

こんな感じで呼び出せる。

assert(MyOrderedNum(10) > MyOrderedNum(2)) // => success!

Ordering[T]

implicitなパラメータとして Ordering[T] を与えている。クラスの外側で Ordering[T] の実装を提供することで、比較ができるようになる。この方法だと、クラス自体を変えることなく、外側から実装を追加することができる。

参考: Scala Standard Library 2.13.5 - scala.math.Ordering

ScalaInt, String などもこちらの方法を用いて比較可能にされている。これは、Int のようなプリミティブなクラスに関しては AnyVal を継承しているだけに留めたく、他のクラスを継承したくないという思想があるらしい。

参考: scala - Why does Int not inherit/extend from Ordered[Int] - Stack Overflow

case class MyOrderingNum(value: Int)(implicit ord: Ordering[MyOrderingNum]) {
  def >(that: MyOrderingNum): Boolean = ord.compare(this, that) > 0
}

implicit object MyOrdering extends Ordering[MyOrderingNum] {
  override def compare(x: MyOrderingNum, y: MyOrderingNum): Int = {
    if (x.value < y.value) -1
    else if (y.value < x.value) 1
    else 0
  }
}

こんな感じで呼び出せる。

assert(MyOrderingNum(10) > MyOrderingNum(2)) // => success!

Appendix

Numeric[T]Ordering[T] を継承していて、他にも四則演算をサポートしている。

trait Numeric[T] extends Ordering[T]

参考: Scala Standard Library 2.13.5 - scala.math.Numeric

参考

kmizu.hatenablog.com

masayuki038.github.io

3ヶ月でやった事を振り返る - 入社1年目1~3月

はじめに

3ヶ月ごとに何をやったか、社内・社外関係なくブログにまとめていきたいと思います。今回は年度の最後の3ヶ月です。新卒一年目の終わりということでなんだか感慨深いですね。

これまでの記事はこちら

hiramekun.hatenablog.com

hiramekun.hatenablog.com

hiramekun.hatenablog.com

お仕事

この3ヶ月は、主に不具合への対応や、暗黙知になっている部分のドキュメンテーションなどを行っていました。友人がプレゼントしてくれた 日本語スタイルガイド(第3版)技術者のためのテクニカルライティング入門講座 を読んで、その内容を社内向けに発表をしました。一回このようなテクニカルライティングに関する本を読むと、文章を書く時に立ち止まって意識することが増えて良いですね。まだ全然改善する余地のある文章を書いているので、日々意識して少しづつ良い文章が書けるようになっていければと思います。

社内で学習心理学の勉強会もやっています。グラフィック学習心理学―行動と認知 (Graphic text book) という本を読んでいます。教育学の基礎的な内容ですが、輪読することで理解が深まり、他の人と読むことで継続するのでとても良い時間だと感じています。

Scalaでいうと、モナドトランスフォーマーを少し使っています。OptionTEitherTなどですね。しかし、正直なところ「モナドがなんであるか」について何もわかっていないので、どこかのタイミングで時間を取らなければいけないと感じています。

お勉強

たくさん本を読みました。

教育関連

この本は分厚くて読み切るのが大変そうだったので、ゆるく読書会を開催して読み進めています。毎回2〜3人に参加していただいています。初めての試みだったのですが、読み続けるモチベーションが湧いて良いと思います。他の本でも一緒に読み進める人を作っていくことをやっていきたいです。

hiramekun.hatenablog.com

教育効果に関するエビデンスをまとめてある本で非常に面白いです。こちらから読書会参加者募集中です〜!

connpass.com

他には、学校の最前線に立つ先生方がどのような状態にあるのか知りたいと思ってこの本を読んだり、

hiramekun.hatenablog.com

hiramekun.hatenablog.com

自分にとって大きなテーマである「教育格差」について勉強したいと思って、社会的階層と学力の階層がどのように生じているか。またそれがどのように変化してきているかについて学んだりしました。

hiramekun.hatenablog.com

Scala関連

Scala関連でいうと実務で使っている技術を深いレベルで腰を据えて勉強したいという思いが強くありました。そこで、この3ヶ月では、Akkaとsbtの勉強をしました。

hiramekun.hatenablog.com

hiramekun.hatenablog.com

sbtに関しては、そのビルドが自動で並列化されていたり、インタラクティブなconsoleがどれほど便利なのかを知るなどしました。少し古い本でもあったので、より新しい本が(できれば日本語で)出版されないかなーと待ち望んでいます。

sbt in Action: The simple Scala build tool

sbt in Action: The simple Scala build tool

エンジアリング前半

まずは、ドキュメンテーションをするにあたってどのように文章を書くのが良いかを学びました。テクニカルライティングと呼ばれる技術で、「ライティング技術はセンスではなく身につけることができる」という言葉が心強かったです。

hiramekun.hatenablog.com

hiramekun.hatenablog.com

また、「エンジニアリングの組織づくりについて興味があるなら読むと良いよ」会社の先輩におすすめされた「エンジニアリング組織論への招待」を読みました。責任と権限についてどう捉えて、組織としてどのように対処していくかや、メンタリングで意識することなどが印象に残りました。

hiramekun.hatenablog.com

統計検定を受けたいなーと思っているので、その基礎的な線形代数の復習をしました。個人的には視覚的にイメージを持ちやすく、数式のお気持ちも知ることができて良い本と巡り合えたなと思います。このシリーズの「プログラミングのための確率統計」も読み進めています。

hiramekun.hatenablog.com

SQL関連も勉強をしました。2冊目は友人におすすめされた本ですが、「SQLは面白いよ!」というプッシュを受けて読んでみました。SQLの背後にある思想や、その思想がどのように SQLの文法や挙動に関係してくるかを知ることができて、技術書としても読み物としても面白かったです。2冊目を読んでいく中で、SQLに対する理解が浅いところがあったので、1冊目に戻って基礎的なところを復習したりしてました。

DockerやKubernetesは仕事で使ってはいるものの、背後でどのような物が動いているのかについて全く知識を持っていなかったので、この本を読みました。結局のところDockerはLinuxの仕組みを使って成り立っているのですが、実際にシステムコールを触ってどう動くのかを見てみたいと思いました。Kubernetesに関してはもう少し実務で触れてからの方が実感を持って読み進められそうだと感じました。

趣味

スマブラ

スマブラではスマメイトでレート1700を達成することができました。とは言っても上振れを引いただけなので、コンスタントに1700行けるようになりたいですね。ホムラとヒカリが参戦して、少し触っているのですが、全然勝てません。。。メインキャラ以外使えないのは恥ずかしいので、きちんとスマブラ力を鍛えていこうと思います。

カメラ

あまり遠出しての写真は撮れていないですね。これは以前撮った桜です。いろいろと忙しくて、今年は桜を撮りにいく前に散ってしまったなあと悲しくなっています。

『教育効果を可視化する学習科学』を読んだ ー 第1部 学級内での学び

はじめに

『教育効果を可視化する学習科学』を読みました。3部に分かれているので、3回に分けてブログにまとめます。

この本は、教育効果につながる様々な科学的知見や論文をまとめている本です。元々『教育の効果』という本で、学力に影響を与える要因を比較して論じ、話題になっていました。

教育の効果: メタ分析による学力に影響を与える要因の効果の可視化

正直和訳が難解な箇所が多いので、基本的に和訳の本を読みつつ、わかりづらい章や箇所を下記の原著に戻って確認しています。自分が興味を持ったところしか取り上げていないので、網羅性を求めている方は本を手に取って是非読んでみてください!

勉強会を開催して読んでいます。参加したい方は是非一緒に読破しましょう! connpass.com

※2021/04/11追記 まとめスライドを作りました!こちらの方が読みやすいかもしれません

www.slideshare.net

第1章 なぜ生徒は学校で学ぶことが好きではないのか?

生徒は学校があまり好きではない。なぜそのような結果が得られるかを説明する。

元来人間は「新たに思考する」ことよりも「蓄えられた記憶から引っ張り出す」ことを優先する。「新たに思考する」ことは苦労を伴うため、「新たに思考する努力」が必要になるが、努力するには「達成できるかもしれない」という自己効力感が必要になる。さらに、「達成できるかもしれない」と感じるためには、新たに学ぶ内容に対して、自分が少しでも内容を知っていることが重要になる。

最終的に生徒は、生徒が知っていることと教師が生徒に知ってほしいことに隔たりがあると、好奇心が湧いて来ずに楽しいと思えない状態に陥る。

第2章 知識は教えることの障壁になるのか?

教え方の観点からみると、「知識に詳しい熟達者になっていても、教えることが上手とは限らない」。 しかし、生徒のモチベーションの観点からみると、「生徒は先生が熟達者のように博識な人の方が、多くを学ぼうとする」。

熟達者にまつわる諸事実

  1. 熟達者は初心者にとっての課題の難しさを過小評価してしまう。
    • 特に、人は技術を習得したのち、その技術について習得する時間を過小評価する傾向がある
  2. 熟達者のヒントやコミュニケーションは貧弱なものになりやすい。
    • 初心者が所有する知識量を正確に読み取ることが難しい。
  3. 生徒は知識が豊富な先生から学ぼうとする
    • 事実1:知識を生徒に示すことで、生徒は教師を信頼し、やる気にさせてくれると認識してくれる。
    • 事実2:どんなに知識を持っていても、教師が知っていることと生徒がその時求めている指導の間にギャップがあると問題を生じる。

「教えること」の枠に囚われずに考えると、教師の知識の深さは、生徒へのフィードバックや生徒の活動を評価する際に非常に重要になる。なので、総合的に知識は教師のためになるという主張をしている。

第3章 教師と生徒の関係

生徒と教師の良好な関係は持続的な作用がある。

生徒と教師の関係が持続する諸事実

  • 幼い生徒と教師との間の良好な関係は、反社会的な行動レベルの低下や、長期にわたる行動上の問題を改善する。
  • 生徒と教師の関係性は、初期の段階で良好だった場合はその先も良好になる。
  • 「関係性改善のプログラムを受講した教師」による授業を受講した生徒は、「そうではない教師」に比べて、翌年の成績が改善した

明記はされていないが、ここにおける「良好な関係」とは、「親密さの高い状態」であると読み取った。さらに「親密さ」とは「教師が生徒に働きかけるもののうち、感情的な側面」であると定義されている。(注:日本語がわかりずらかったのでブログ著者の解釈が入っている。元の日本語は「親密さとは、教授の相互作用の情意的文脈を表している。」)

第4章 教師としてのあなたの人柄

生徒は教師が信頼できるかどうか評価している。その評価は、教師の人柄とは関係なく、生徒に対する教師の接し方をどのように捉えているかに関連している

  1. 一番教師にとって重要なのは、ポジティブでオープンなコミュニケーションを行うことである。特に、生徒たちが、接してもらう際に大切にしているのは、「公平・威厳・個人の尊重」の3点である。この3点に対してコミットすることが必要になる。
  2. もう一つ重要なのは、教師の非言語的な振る舞い。教師が他者に対してどのように振る舞っているかを生徒はロールモデルとして捉えており、それが社会のルールから逸脱していると信用を失う。
    ※ 特に嘘をつくことは、関係性を失うことに一番大きな作用がある。

上記のような、生徒による教師の評価は、ものの10秒で始まっている。特に「何を話しているか」よりも「どのように話しているか」に生徒は注意が向けており、教師の雰囲気を10秒程度で把握している。

生徒が高い学力を達成するために必要な行動として、「援助要請行動」というものがある。これは、助けを求めようとするような意思の側面であり、内発的動機が高い生徒によくみられる。この援助要請に影響を与えるのが、生徒との信頼関係である。生徒は、教師が自分たちを好意的な姿勢で支えてくれることに気付くと、内発的動機をもとにして質問ができるようになる。

まとめると、込み入ったことを考えて奮闘しているときに、自分たちを助けてくれるような信頼できる教師を生徒は高く評価するということ。

第5章 学級学習のグローバルな指標としての時間

教室の中で何にどの程度時間を使っているかは研究対象としてしばしば取り上げられる。その際には、同じ「時間」といっても以下の4つの区分に時間が分けられることに留意する必要がある。

  • Allocated time: カリキュラムや時間割上確保された時間
  • Instructional time: 実際に指導している時間
  • Engaged time: 生徒が実際に学習対象に注意を向けている時間
  • Academic learning time: 生徒が学習し、高い達成度を得る、知的学習時間(ALTと呼ばれる)

学級内で4つの区分があり、さらに生徒や学級ごとに大きく異なる。それを教師が全て把握するのは難しく、時間がどのように使われているかについてはわかっていないことも多い

学級内の時間に関して、留意点として次のようなものもある。

  • Allocated time それ自体と、学業成績の相関関係は強くない。その一方で、同じ教科でも学校ごとに費やされる時間は大きく異なっており、生徒の学ぶ機会に対しては直接影響する重要な要因である。また、Allocated time のうち Engaged time の割合が少ない生徒は、課題の出来が良くないことも想像される。
  • 勉強に費やす時間に関しては、個々人が勉強に費やす時間と本人の成績結果の間には関連があるにはしても、異なる能力である人をそれぞれ比較する場合は関連が見えづらいものとなる。

単元を跨いで関連づけるような知識の統合には、別の題材同士を繋げるのに時間と労力が必要となる。カリキュラムを減らすなどして確保される時間が少なくなると、そのような知識の統合に時間を取れなくなる。生徒に意味のある情報を覚えていて欲しいならば、知識の統合を促すような活動が必要であり、深い学びを促す際には時間の役割は大きい

※ ある研究では、時間配分の減少は選択式テストには影響はなかったが、記述式の問題では得点が大きく下がった。

第6章 Recitation method と学級学習の性質

Recitation method は、教師が生徒に対して情報のインプット後にいくつか内容に関する基本的な内容を質問をする形式のことで復唱式勉強法と呼ぶことができる。IREサイクルやCDRメソッドとしてもよく知られている。

  • IREサイクル:initiation-response-evaluation
  • CDRサイクル:conventional-direct-recitation

この教授法は、教師の生徒に対する権威を保っていられ、かつ授業のコントロールができる丁度良い方法として捉えられることが多い。そのため、現在に至るまで多くの場面で用いられている

しかしながらこの教授法は以下のような理由から頻繁に批判されてきている

  • 観察によると、教師の質問は大半が簡単な難易度のものに留まり、単純な答えを要求している。
  • 一度に一人の生徒のみ活発になっている。大半の生徒はその間何もしていないことが多い。
  • 教育という活動が、権威ある人物からパッケージ化された知識を得るものになってしまう。
  • Recitation method によるコミュニケーションは、予測のしやすいものになるが、生徒に対して刺激の少ないものとなってしまう。

生徒が授業に対して活発な状態になっていることが大事ではあるが、それは質問した時のみ達成できるわけではない。さらに、一方的な講義時間が長ければ長くなるほど以下のようなデメリットが生ずる。

  • 生徒は授業に集中している割合が少なくなる。
    ※ ある仮説によると、高校レベルの生徒は10分までしか集中して授業を聞いていない。
  • 情報過多になると、理解していたとしてもさらに混乱を生じることがある。

第7章 基礎学力における自発運動化に関する指導

無意識に脳に負荷をかけずにできる能力のことを自発運動化と呼ぶ。本書では、特に数字情報へのアクセスや単語の認知に対する能力を取り上げる。自発運動化が欠如していると、思考・理解する能力の欠如を引き起こす。なぜなら、目的が単語を理解することに終始してしまい、全体の文脈を理解することが疎かになってしまうため。

多くの子供が、読解力の欠如の最たる原因として、単語を理解する時点で苦労していると徐々に明らかになっている。理解力の問題ではなく、それ以前の情報システムが単語の認識に対して影響を及ぼしている。単語を早く処理することができないと、例え単語の意味を理解していたとしても文章を理解することは不可能になる。このように、自発運動化が欠けていると、情報の処理に大きな負荷がかかってしまう

逆に、自発運動化により基礎的な技能が無意識にできるようになると、さらに深いレベルでの思考ができるようになる。その意味では、反復と強化は知識を取り出しやすくするための手段であり、知的成長が促進できる。

自発運動化は、子供の生活に影響を及ぼす全ての大人が子供に対して支援をする必要があり、教師にその役割を押し付けることは不適切。一方で、反復読みやMULTILTなどの教授方法により、自発運動化を発展させること自体は可能である。

第8章 フィードバックの役割

生徒は、次回に繋がるような、活動をどのように改善すれば良いかを知りたがっている。それに対して、教師は「否定的なフィードバック」を与えることでそれが満たされていると感じることが常である。否定的なフィードバックは肯定的なフィードバックよりも印象残りやすいため、注意する必要がある。

フィードバック自体は、学業の到達度に関わる最も強力な要因の一つである。生徒に対するフィードバックは以下のときに効果を発揮する。

  1. 生徒が成功とはどのようなものなのかを知り、
  2. 彼らの現在地と、目的地との間の距離を減らすことが目指されていることを理解し、
  3. 次に進む地点についての情報が与えられたとき。

フィードバックの方法として、「賞賛する」ことに関しては注意が必要だ。確かに勉強に対する快適な環境が整うかもしれないが、この賞賛を受けること自体が学ぶことに対してプラスになる調査結果は存在していない。特により簡単な作業の際に生まれつきの能力を賞賛すると、困難な状況の際には諦めやすくなってしまう。

また、教師は生徒からのフィードバックを受ければ受けるほど、教師の行動は改善し、結果として生徒は大きな恩恵を受ける。

第9章 社会的モデリングと明示的な教え方を通した複合的な技能の習得

指導する際に、何をどれだけ直接的に指導するかは重要な議論の対象となる。

教師は、学習に関して実演し、それを学習させるコーチやモデルの役割を担う。こうした実演を見るだけで、生徒が何か実現可能になるわけではない。なので、観察学習を促すためには、教師は慎重に段階を追った道筋を示し、生徒が情報を段階を追って消化できるように努めなければならない

本書で取り上げられた二つの研究によると、

  • 探究の過程は、そのステップごとに焦点を提示し、そのステップごとにどのような手法をとるかの目的を理解しやすくさせる。
  • 認知的タスク分析(CTA)に基づいた、適度に単純な作業を分解する方法で授業を行うと、授業からの離脱率が下がった。(8%→1%)

このように、どのような手法を用いて思考するかは明確に教えられることが必要であることがわかる。

以上のような見解に対して、「個人の発見的に生み出される知識はよりしっかりしたものだ」という反対意見が存在する。しかしながらこの意見は間違っている。個人的な発見それ自体が、人々の実際の学習を支援するということに根拠はほぼなく、以下のようなデメリットが明らかになっている。

  • 知能的機能にかかる認知負担の増加
  • 共有された知識には存在している、確かで体系的な知識を得ることができない
  • きちんとしたモデルなしに作業を行う人よりも、注意深く観察した方が優れた結果を得る

第10章 専門的技能とはどのようなものか

専門的技能とは、繰り返し発揮される特出したパフォーマンスのことを表す。クラスでの教授方法についても専門的技能があることが分かっている。例えば、同じ程度の期間経験を積んでいる教師を比較しても、専門的技能を身につけている人(ここでは熟達者と呼ぶ)とそうでない人がいて、教える能力には大きな違いが見られる。

熟達者は以下の7つの特徴を持つ。

  1. 専門としている領域でのみ特出している。
  2. 多くの、そしてより意味のあるパターンを知覚する。
  3. 課題解決をほとんどミスなくこなす。
  4. 専門としている領域においては、非常に大きな短期記憶を持っている。
  5. 目に見える課題を、より深く本質的なレベルで捉える。
  6. 課題を慎重に定性的に分析することに、より時間を使う。
  7. 自己管理の卓越したスキルを持つ。

また、熟達者にとっては意識していないレベルの事柄が多くなり、彼ら自身がそれを説明することは困難になっていく。この事実から、一般人に対して熟達者が説明していることはあまり信用ならない。

第11章 どのようにして専門的技能を発達させるのか

すでに獲得した技術を繰り返し時間練習すれば自ずとその技術が上がっていく、というわけではない。熟達者はより「意識的な練習(deliberate practice)」を行っていることがわかっている

まず専門的技能は、長年の絶え間ない鍛錬と、周りからの環境に恵まれている必要があることが調査でわかっている。その上で練習をする際は、ただ漫然と技能の練習をするのではなく、技能の改善に対して明示的にコミットする必要がある。このような意識的な練習は構造化されたゴールに向かうことを意味している。そしてそれを行うためには、短期的なゴールや個別最適化されたフィードバックが必要になる。

このような練習を経て、熟達者は高いレベルのスキルをほとんど意識的な努力なしに発揮することができるようになる。これは以前の章でも説明した自発運動化(automaticity)によるものである。

しかしながら、自発運動化は技能の発達を妨げる場合もあり、自発運動化に対する見解も注意が必要だ。自発運動化が獲得されると、獲得した段階の技能レベルに対して意識的な努力なしにアクセスすることができる。つまり練習を繰り返すことにより、自覚的な技術獲得段階から、より先の発達が止まった無意識段階に移行してしまうのである。

数々の研究から、天才的な技能が先天的に獲得されているかについても疑問が投げかけられた。結局のところ、幼少期に高い技能を見出された人は、そのほとんどが大人になっても技能が進歩することはあまりない。早い段階で才能のある人を選別してしまうことは、潜在的により高い才能を持つ人を排除してしまう

第12章 学級での指導領域における専門的技能

教え方の領域に熟達者はいることがわかっている。学級単位で生徒の到達度データに関する統計的な分析によってそれが明らかになった。p163にあるように、熟達した教師について発見された事項は、10章で取り上げた専門的技能の特徴と結びつけることができる。

教え方の領域の専門的技能は、実験的方法を用いて研究されることも多い。

  • 授業の映像を見せられた実験によれば、熟達した教師の場合は、著しく高いレベルで教室の様子を読み取る能力を有していることが発見された。熟達者は以下のような点を認知し用いる点で、平均的な教師と異なっていた。
    • 授業の構造についての情報
    • 自身の要求と期待
    • 生徒の活動の傾向
  • 熟達した教師は他の教師とは違い、生徒の理解を非言語的な合図から推測することにおいて極めて正確だった。
    • 画面に映る生徒と親しい時のみ上記事実が見られた。

また、熟達した教師を実際の教室で観察した実験から、熟達した教師の特徴が以下の3点浮かび上がった。

  • 生徒の努力を最適に引き出すために目標を設定したり、挑戦心をくすぐったりする。
  • 指導の方向性を決めやすくするために、生徒の学習をモニタリングしたりフィードバックしたりする。
  • 教え方をここの状況に適合させ、指導上必要な事項を素早く判断できるように、高いレベルで知識を利用する。

このように、熟達者としての教師は、生徒との対人関係において感受性を鋭敏なレベルで用いることが求められている

第2部へ続く

hiramekun.hatenablog.com

『プログラミングのための線形代数』を読んだ

はじめに

線形代数で何をやっているのかイメージがつきやすい良書ということで友人におすすめしてもらったので、『プログラミングのための線形代数』を読みました。

プログラミングのための線形代数

プログラミングのための線形代数

ブログにまとめるというよりも、本を読み返した方が確実に効果があるので、内容をきちんとまとめたりはしません。特に印象に残った内容に関してメモとして残しておきます。(このメモも、本を読んでないとなんのことかさっぱりだと思います。)

まとめ&感想

大学1年生の頃に読んでおきたかった本でした。まずは線形代数という道具が一体どのように役に立つのか、そこから入ります。1年生の頃に線形代数を勉強した時、抽象的な概念ばかりで一体なんの役に立つのかと首を傾げていた覚えがありますので、こういう話が導入部分で書いてあるのは嬉しいです。線形代数の各概念を空間でイメージし、さらに行間や式自体のお気持ちを補足してもらっているので、非常に読み進めやすい本でした。

特に大事なところは、行列は空間をイメージする行列は写像というあたりでしょうか。

特に印象に残ったところ

基底について

特定のベクトルを指定するのに、明確に番地を指定する必要がある。その番地の基準となるのが、基底である。この定義からも、基底と呼ぶための条件は、次のようになる。

  • 今考えている空間内のどんなベクトルでも、基底の線形結合で表される。
  • しかも、その表し方はただ一つだけである。

そして、基底ベクトルの本数を持ってその空間の次元と定義する。

行列は写像

 y=Ax とは、行列  A を指定することで、ベクトルを別のベクトルに移す写像が定まるということ。つまり点を点に移すことであり、空間全体が変形するところをイメージすると良い。

核(kernel)と像(image)

  • 与えられた Aに対して、 Ax=oに移ってくるような集合を Aの核(kernel)と呼ぶ。
  • 与えられた Aに対して、 xを色々動かした時に Aで移り得る y=Axの集合を、 Aの像(image)と呼ぶ。

正則性との同値表現

  • どんな n次元ベクトル yにも、 y=Axとなる xが一つだけある
  •  A正則行列逆行列が存在する
  •  A写像は「ぺちゃんこにつぶさない」
  •  Ax=oとなるのは x=oだけ
    •  KerAが原点のみ
    •  dimKerA=0
  •  Aの列ベクトルが線形独立
  •  A写像は「行先の空間全体をカバーする」
  •  rankA = dimImA=n
  •  detA \neq 0
  •  A固有値0を持たない

LU分解の嬉しさ

LU分解とは、与えられた行列を下三角行列と上三角行列の積で表すこと。一旦LU分解されれば、行列式などの計算が少ない計算量でできる。前処理として行うことであと段階の計算が楽になることから、数値計算の基本として頻繁に利用されている。