STACKドキュメント

ドキュメントホーム | カテゴリインデックス | | サイトマップ

問題作成クイックスタート 1

コンピュータによる数学の自動採点は次のフェーズで動作します。

  1. 問題作成
  2. テスト
  3. デプロイ
  4. レポート

これらのリンクにはそれぞれ詳細な解説が書かれてあります。このページの目的は,簡単な例を題材にして問題作成の概要を学ぶことです。

イントロダクション

MoodleのSTACK問題タイプは数学の問題を扱うための「車輪」として設計されたものです。数学の問題は表には出てこないですが,あるデータ構造を持って作成されており,このページでは簡単な例を題材にして,問題を作成するプロセスを説明します。

問題はMoodleの小テストモジュールから作成します。Moodleの問題バンクに新しい問題を作成する際に,問題タイプとしてSTACKを選択します。複雑そうに見えますが,くじけないで頑張ってください。

多くの入力欄がありますが,入力必須の部分はごくわずかで,「問題名」や「問題テキスト」がそれらに該当します。問題テキストは,受験の際に学生に表示される問題文です。解答入力欄があれば(デフォルトでは解答入力欄は一つです),「正答」を必ず入力してください。「ポテンシャル・レスポンス・ツリー」(デフォルトでは一つのノード)の作成も必須になります。

問題の例

では,サンプル問題をさっそく作成してみましょう。「問題名」は必須なので,ここでは仮に問題 1としておきます。

問題テキストには以下の情報を入力してください。コピー&ペーストで貼り付けてもかまいません。

\((x-1)^3\) を \(x\) で微分しなさい。
[[input:ans1]]
[[validation:ans1]]

このテキストについて,いくつかの点に気がつくでしょう。

  • テキストには LaTeX の数式環境が含まれています。
  • [[input:ans1]]というタグが,ans1とラベル化された解答欄になります。つまり,学生が解答を入力するボックスがこの位置に配置されます。
  • [[validation:ans1]]というタグの部分に,学生の解答ans1の書式が正しいかどうかのフィードバックが表示されます。

デフォルトでは,新しい問題を作成すると,自動的に一つの解答欄が作成され,学生の解答を処理するアルゴリズムであるポテンシャル・レスポンス・ツリーが用意されます。

下にスクロールすると,解答欄のセクションがあります。正しいCASの文法で正答例を入力します。例えば,

3*(x-1)^2

問題と正答例が用意できたので,次に学生の解答が正しいかどうかを判定する必要があります。

ポテンシャル・レスポンス・ツリーによる学生の解答の処理

学生の解答を処理するために,ポテンシャル・レスポンス・ツリーというアルゴリズムが必要になります。

このポテンシャル・レスポンス・ツリーによって,学生の解答の性質が決定され,その結果に応じてフィードバックや採点などの結果が返されます。

サンプルの問題では,次の点について確認し,フィードバックを返す必要があります。

  1. 解答が正しいかどうか
  2. 学生は間違って積分をしていないか
  3. 合成関数の微分公式を使わないで,展開してから微分していないか

デフォルトでは,新しく問題を作成したときprt1という名前で一つのポテンシャル・レスポンス・ツリーが作成されます。 ポテンシャル・レスポンス・ツリーは何個でも作成することができます(作成しない場合もあり得ます)。これらのツリーで生成されたフィードバックは,[[feedback:prt1]]のタグで指定された場所に表示されます。デフォルトでは,このタグは「特定フィードバック」に配置されますが,「問題テキスト」内に配置することもできます。

ポテンシャル・レスポンス・ツリーは少なくとも一つのポテンシャル・レスポンスのノードからなる,非循環・有効グラフです。デフォルトでは一つのポテンシャル・レスポンスが含まれ,これは次のシンプルな処理を行います。

  1. 評価関数によって,評価対象評価基準を比較する(いくつかのオプションが指定され得る)
  2. もし評価関数の結果がであれば,のブランチ(枝)の処理を行う
  3. もし評価関数の結果がであれば,のブランチ(枝)の処理を行う

評価関数自体がフィードバックを提示するように設計されている場合もあります(ただし,教師のほうでフィードバックを提示しないように設定することも可能です)。評価関数は,教師用に内部的な解答メモを生成しますが,これは,後の学生の解答のレポートにおいて重要になります。

ポテンシャル・レスポンス・ツリーの各ブランチは次の処理を行います。

問題テキスト内で解答欄にans1という名前を指定しているので,数式処理による計算では,学生の解答をans1として参照します。正答を 3*(x-1)^2 としていたので,要素を以下のようにします。

 評価対象 = ans1
 評価基準 = 3*(x-1)^2
 評価関数 = 代数等価

そして [変更を保存する] ボタンを押下します。もし保存に失敗したら,エラーをチェックし,修正してからもう一度保存してください。

こうして,最小限の問題が作成・保存されました。要約すると,我々は以下のことを行いました。

  1. 問題文の入力
  2. 正答例の入力
  3. 学生の解答が正答例である 3*(x-1)^2 と代数的に等しいかどうかの判定を行うという指定

次に,作成した問題のプレビュー(確認)を行うために,問題バンクの「プレビュー」アイコン(虫眼鏡型アイコン)をクリックします。

問題のプレビュー

エラーがなければ,Moodleの問題バンクから "問題のプレビュー" のリンクを選択し,問題を確認することができます。解答欄に

3*(x-1)^2

と入力してみてください。

そして,[チェック] ボタンを押下します。

システムはまず,解答が文法的に正しいかどうかを判断します。

もう一度 [チェック] ボタンを押下してください。

システムはポテンシャル・レスポンス・ツリーによって,入力した解答が正答例の 3*(x-1)^2 と代数的に等価であるどうかを判定します。 もし"即時評価"のオプションが「オン」になっていなければ,解答を2度入力する必要があります(解答の文法チェックと,正答性評価のため)。なお,入力したものは全て,表に保存されます。

我々はここで,よりよいフィードバックを提示したいので,もう一度問題を編集することにします。問題バンクページに戻り,編集のリンクを選んでください。

よりよいフィードバック

最初の評価関数の結果が「偽」の場合を考えてみましょう。例えば,学生が間違って微分ではなく積分をしてしまっていないかどうかを判定したい場合,別のポテンシャル・レスポンスのノードを追加することによって可能になります。

プレビュー画面を閉じてもう一度問題の編集を行います。ポテンシャル・レスポンス・ツリーのところまでスクロールし,ノードのリストの下の [新しいノードを追加する] ボタンを押下します。

ノード1の「偽」ブランチの,"次のノード" を [ノード2]に設定します。このようにして,最初の評価が「偽」の場合,このノード2を実行することになります。

もし学生が間違って積分していた場合,積分定数があるかもしれないし,ないかもしれません。もし積分定数を入力していた場合,どの文字を使うかは予想できません!したがって,この問題を解決する最良の方法は,学生の解答を微分し,問題文の式と比較することです。

ノード2を次のようにします。

評価対象 = diff(ans1,x)
評価基準 = (x-1)^3
評価関数 = 代数等価

このようにして積分したかどうかを判定することができますが,何を出力したらよいでしょうか。以下のようにするとよいでしょう。

  1. 「真」のブランチで,点数を0とする
  2. 「真」のブランチで,間違って積分しているようです!というフィードバックを提示する

STACKは解答メモ に"有益なメモ"を追加します。このメモは,ランダムに生成された問題に対応した解答が提示された場合に,同様な解答をグルーピングする場合などに有効です。このことは,レポートの中で検討します。

[変更を保存する] ボタンを押下して,問題をプレビューします。

さらに良いフィードバック:解答の形式

学生は正答を解答しようとしますが,時折,不適切な方法で解答することがあります。 例えば,合成関数の微分について知らず,微分すべき多項式を展開し,因数分解されていない形式で解答する場合があります。このような場合には,学生に対してどのような間違いを犯したかを知らせるフィードバックを与えるとよいかもしれません。

再び,[新しいノードを追加する]ボタンを押下し,上記のことを実現するために別の評価関数を適用する必要があります。

このポテンシャル・レスポンスを利用するために,ノード 1を編集して,「真」のブランチで次のノードをノード 3に設定します。ノード 3に入ったら,学生の解答は正答であるということですから,やるべきことは,その解答が因数分解されいてるかどうかを評価することだけです。このために,別の評価関数を使用する必要があります。

ノード 3を次のように設定します。

評価対象 = ans1
評価基準 = 3*(x-1)^2
評価関数 = 因数分解
オプション = x
抑制 = Yes.

評価関数「因数分解」は,自動的にフィードバックを提示しますが,ここではそれは適切ではありません。我々は解答が因数分解されいてるかどうかを確認するだけでよいので,quiet設定します。また,何が変数であるかを指定するために,オプションに$x$を設定する必要があります。

採点を次にようにします。

  1. 「真」のブランチで,点数を1とする
  2. 「偽」のブランチで,点数を1とする(ただし,減点すべきであるという考え方もありますので,それは出題者次第です)
  3. 「偽」のブランチで,例えば次のようなフィードバックを設定します。

あなたの解答は因数分解されていません。合成関数の微分の方法を使って微分の計算を行うことができ,そうすれば,解答は因数分解された形になります。

この新しいフィードバックは,展開された解答,例えば 3*x^2-6*x+3 を入力することで確認することができます。

このように,必要に応じてポテンシャル・レスポンスをさらに追加することができ,学生が犯しやすい微妙な間違いについて確認することができます。それぞれのケースで評価関数を使い分けて,様々な種類の解答を処理することができます。

ランダム問題

この段階で,新しい問題として保存しておくとよいでしょう。

乱数を使って問題を作成したいという場合もよくあり,それは自然な拡張です。そのために,問題変数 を利用します。

STACK 3 では変数の設定のために Maxima の書式を使いますが,その文法は一般的ではないかもしれません。変数に値を割り当てるために,コロン : が使われます。例えば,変数 n に値 5 を割り当てるために, n:5 という書式を使います。

この前の例から,次のように 問題変数 の部分を変更し,

p : (x-1)^3;

問題テキスト を次のようにします。

@p@ を \(x\) で微分しなさい。
[[input:ans1]]
[[validation:ans1]]

そして,正答を

diff(p,x)

とします。ローカル変数 p を定義し,それを問題テキストの中で使用していることに注目してください。数式を表現するために,$ 記号を使用したものと,@ を使用したものとの違いがあります。フィードバック部を含め,問題の中でテキストをベースとしたフィールドは CASテキスト と呼ばれます。これは,数式が挿入されるHTMLで,LaTeX は $ を使って,そして CASの表記(問題変数を含む)は @ を使って数式が挿入されます。CASテキスト のドキュメントにはより詳しい解説があります。CASの表記は,問題変数の定義に応じて評価されたものが表示されます。

@p@ という表記を使ったので,問題が表示された時,ユーザは問題文中で \(p\) の表記を目にすることはなく p評価された値が表示されます。

正答の入力欄で,px で微分するCASのコマンドが使われていることに注目してください。ランダム問題でもCASが学生の解答を正しく処理することが必要になります。 したがって,ポテンシャル・レスポンス・ツリーでも変数 pdiff(p,x)(あるいは,その他のCASコマンドである場合もあります)を正しく適用しなければなりません。

いよいよ,これからランダム問題を作成しましょう。そのために,問題変数 を次のように変更します。

n : 2+rand(3);
p : (x-1)^n;

この新しい例では,新しい変数 n を乱数として定義しています。

この n を使って p が定義され,問題の中で使用されます。

CAAにおけるランダム問題を作成する時,乱数について言及しているのは,実は,擬似乱数のことを意味しています。それぞれの学生に対してどの乱数が生成されたかの履歴を保持するために,STACKでは特別なコマンドが用意されていて,それは Maxima の乱数のコマンドとは別のものです。

それは rand コマンドであり,それは一般的な"ランダムなものを"生成するものです。詳細はランダム生成を参照してください。rand コマンドは乱数を生成したり,リストの中からのランダムな選択にも利用できます。

問題メモ

問題メモを使うことによって,教師は,各学生に対してどのバージョンの問題が課せられたかを調べることが可能となります。問題メモ が同じ時,またその時のみ,同じバージョンの問題であることになります。したがって,ランダム問題の場合は,問題メモを空欄にすることはできません。

例えば,問題メモ欄は次のようにします。

\[ \frac{d}{d@x@}@p@ = @diff(p,x)@ \]

問題変数内で rand() が使われている問題では,問題メモを空欄にすることはできないので,上記のような指定は極めて重要です。これを強制することによって,問題メモを指定しないことにより,後々抱くであろう,ランダム問題のどのバージョンかを区別することができないという不満を避けることが可能となります。

問題を編集,保存し,プレビューを行ってみてください。問題のランダムな新しいバージョンが得られるでしょう。

次のランダム化

この時点で,上記の問題を新しい問題として保存することを考えていることでしょう。

ランダム化の特別な例として,以下に示されている問題を試してみましょう。この問題は,乱数を含み,またリストの中から変数や数式がランダムに選択される例となっています。

n : rand(5)+3;
v : rand([x,s,t]);
p : rand([sin(n*v),cos(n*v)]);

問題テキストを次のように変更します。

@p@ を @v@ で微分せよ。
[[input:ans1]]
[[validation:ans1]]

再び,ポテンシャル・レスポンス・ツリーを通じて diff(p,v) のような式を使う必要がありますし,diff(ans1,v) を使う場合もあります。

ノード 3を削除してください。評価関数「因数分解」はこの問題の内容では意味がありません。

たとえ最初はランダムに問題を生成するつもりはなくても,最初の時点で問題変数を使うといいでしょう。また,問題が次第に複雑になってくると,問題変数やフィードバック変数の複雑な Maxima コマンドに対してコメントをつけるようにするとよいでしょう。そうすることで,その問題を編集したいと考えている人が読みやすいコードとなります。コメントは次のように挿入することができます:v : rand([x,s,t]) /* v を ランダムに x, s, t のいずれかとする */

問題メモを次のように更新する必要があります。

\[ \frac{d}{d@v@}@p@ = @diff(p,v)@ \]

問題テスト(問題の確認)

問題を確認することは時間がかかり面倒な作業ですが,問題が正常に動作することを保証するために重要な作業です。この作業を手助けするために,STACKでは"問題テスト"を定義することができます。これはソフトウェア工学の"ユニットテスト"と同じ原理です。

問題のプレビュー画面で,右上の問題テストを実行しますのリンクをクリックします。

詳細は問題テストを参照してください。

まず,ポテンシャル・レスポンス・ツリーのノード 3が削除されていることを確認してください。テストケースを追加するをクリックして問題の確認項目を追加してください。例えば,以下の情報を入力します。

ans1 = diff(p,v)
点数 = 1
原点 = 0
解答記録 = prt1-1-T

システムは自動的にdiff(p,v)を評価しans1を作成し,この情報を使って採点します。これがあなたが設定した実際の結果と一致するはずです。これにより,問題の確認作業を自動かすることができます。

必要であればいくつでもテストケースを追加することができますが,通常は想定される各ケースに対してテストを追加することにより,そのケースに該当するかどうかを明確に判定できるものである必要があります。追加するテストケースとしては,ここでは,学生が間違って積分してしまったかどうかを明確に判定できるものであるべきでしょう。

もしあなたの問題がランダム化を行っている場合,学生に提示する前に問題をデプロイする必要があります。これは,問題のテストページの先頭にあるデプロイのインターフェースで実行されます。

次のステップ

STACKで作成することのできる問題の種類は非常に柔軟性があります。

問題作成クイックスタートの次のパートでは複数解答欄の問題を扱います。


ドキュメントホーム | カテゴリインデックス | | サイトマップ