kot 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d51222d3929d9c0712fe696713d63329b18950e6fdde1975e1c97b7076b4959d
4
+ data.tar.gz: 802eecd963724fd4398292b645a2f1a681eddadcc177b3d63b66785e4a7a8479
5
+ SHA512:
6
+ metadata.gz: b024eda53798ada11f65efbc172843da5a6d7836cc0140178da8ab0381618e10094cb7fe51d6f5636218d75edeb1425d55b05ddcd9c82287bedbd62728ee6dcf
7
+ data.tar.gz: 772bc25d250dc89b2ce11e148cca0a5638b93575de92d979f911d49e39e7fca1abd978338b24a70582a3dafbe096b0b878338a4236f4b68624994ca4fa83d33b
@@ -0,0 +1,4 @@
1
+ require('kot/item_response_theory')
2
+ require('kot/hill_climbing_estimator')
3
+ require('kot/randomesque_selector')
4
+ require('kot/test')
@@ -0,0 +1,62 @@
1
+ module Kot
2
+
3
+ class HillClimbingEstimator
4
+
5
+
6
+
7
+ # "The variable stepsize changed the 0 estimate by half the distance to the appropriate ... value in the item pool."
8
+ def dodd(est_theta:0.0, items:[], last_response:[])
9
+ max_b = items.map(&:b).max
10
+ min_b = items.map(&:b).min
11
+
12
+ last_response ? est_theta + ((max_b - est_theta) / 2.0) : est_theta - ((est_theta - min_b) / 2.0)
13
+ end
14
+
15
+ def estimate(responses:[], items:[], all_items:[], est_theta:0.0)
16
+
17
+
18
+ if responses.uniq.count == 1
19
+ raise ArgumentError.new("Responses are all #{responses.first} but missing all_items argument") if all_items.empty?
20
+ return dodd(est_theta:est_theta, items:all_items, last_response:responses.last)
21
+ end
22
+
23
+ lower_bound = items.map(&:b).min
24
+ upper_bound = items.map(&:b).max
25
+
26
+ return lower_bound if upper_bound == lower_bound
27
+
28
+ best_theta = - Float::INFINITY
29
+ max_ll = - Float::INFINITY
30
+
31
+ 10.times do
32
+
33
+ step_size = (upper_bound - lower_bound) / 10
34
+ intervals = (lower_bound...upper_bound).step(step_size)
35
+
36
+ intervals.each do |ii|
37
+
38
+ ll = ItemResponseTheory.log_likelihood(ii, responses, items)
39
+
40
+
41
+ if ll > max_ll
42
+ max_ll = ll
43
+
44
+ #TODO - precision-based early exit
45
+ best_theta = ii
46
+ else
47
+ lower_bound = best_theta - step_size
48
+ upper_bound = [ii, best_theta+step_size].max #HACK
49
+ break
50
+ end
51
+
52
+ end
53
+
54
+ # End of hillclimb
55
+ end
56
+
57
+ return best_theta
58
+ end
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,54 @@
1
+ module Kot
2
+
3
+
4
+ # Requires a, b, c, d
5
+ module ItemResponseTheory
6
+
7
+ #
8
+ # Module methods for statistics based on estimated theta, items and responses
9
+ #
10
+
11
+ def self.log_likelihood(est_theta, responses, items)
12
+ ps = items.map {|i| i.icc(est_theta) }
13
+ ls = ps.each_with_index.map {|e,i| responses[i] ? Math.log(e) : Math.log(1.0 - e)} #TODO: Polychotomous
14
+ ls.inject(:+)
15
+ end
16
+
17
+ def self.test_info(est_theta, items)
18
+ items.map {|i| i.inf(est_theta) }.inject(:+)
19
+ end
20
+
21
+ def self.var(est_theta, items)
22
+ 1.0/test_info(est_theta, items)
23
+ end
24
+
25
+ def self.see(est_theta, items)
26
+ Math.sqrt(var(est_theta, items))
27
+ end
28
+
29
+
30
+ #
31
+ # Methods intended for inclusion into Item-classes
32
+ #
33
+
34
+ def icc_component(theta)
35
+ Math.exp(-a * (theta - b))
36
+ end
37
+
38
+ # Item characteristic curve
39
+ def icc(theta)
40
+ c + ((d - c) / (1 + icc_component(theta)))
41
+ end
42
+
43
+ # Information value of an item
44
+ def inf(theta)
45
+ vp = icc(theta)
46
+
47
+ top = (a ** 2) * ((vp - c) ** 2) * ((d - vp) ** 2)
48
+ bottom = ((d - c) ** 2) * vp * (1.0 - vp)
49
+
50
+ top/bottom
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,15 @@
1
+ module Kot
2
+
3
+ class RandomesqueSelector
4
+
5
+ def initialize(bin_size = 5)
6
+ @bin_size = bin_size
7
+ end
8
+
9
+ def select(est_theta, possible_items)
10
+
11
+ possible_items.sort_by {|i| - i.inf(est_theta)}.slice(0, @bin_size).sample
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,41 @@
1
+ module Kot
2
+
3
+
4
+ class Test
5
+
6
+ attr_reader :est_theta
7
+
8
+ def initialize(item_bank, est_theta = 0.0, selector = RandomesqueSelector.new, estimator = HillClimbingEstimator.new)
9
+ @item_bank = item_bank
10
+ @est_theta = est_theta
11
+ @selector = selector
12
+ @estimator = estimator
13
+
14
+ @responses = []
15
+ @asked_items = []
16
+ end
17
+
18
+
19
+ def see
20
+ return Float::INFINITY if @asked_items.empty?
21
+ ItemResponseTheory.see(@est_theta, @asked_items)
22
+ end
23
+
24
+ def update_est_theta
25
+ @est_theta = @estimator.estimate(est_theta: @est_theta, responses:@responses, items:@asked_items, all_items:@item_bank)
26
+ end
27
+
28
+ def next_item
29
+ possible_items = @item_bank - @asked_items
30
+ @selector.select(@est_theta, possible_items)
31
+ end
32
+
33
+ def respond(response, item)
34
+ @responses << response
35
+ @asked_items << item
36
+ update_est_theta
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,3 @@
1
+ module Kot
2
+ VERSION = '0.0.1'.freeze
3
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Adam Watkins
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-08-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: " Kot is a basic toolkit for getting started with computerised adaptive
14
+ testing (CAT). It includes a module to calculate item response theory (IRT) statistics
15
+ for dichotomous items with 1-4PL characteristic curves (ICCs), a Hill Climbing ability
16
+ (theta) estimator, a Randomesque selector and a Test class to make tying all this
17
+ together easier.\n"
18
+ email:
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - lib/kot.rb
24
+ - lib/kot/hill_climbing_estimator.rb
25
+ - lib/kot/item_response_theory.rb
26
+ - lib/kot/randomesque_selector.rb
27
+ - lib/kot/test.rb
28
+ - lib/kot/version.rb
29
+ homepage: https://github.com/stupidpupil/kot
30
+ licenses:
31
+ - GPL-3.0+
32
+ metadata: {}
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 2.7.6
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: Kot is a basic toolkit for getting started with computerised adaptive testing
53
+ (CAT).
54
+ test_files: []