irt_ruby 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3864e3faec7cbf0a1d96649b1493a843df0fcb029a2106b99e682f1770b9f499
4
+ data.tar.gz: e6901babf0c08c5de4e8d644ee4c5e8607f1213a965864874455af2e1ea5ead5
5
+ SHA512:
6
+ metadata.gz: 519eb1b5d1e5c74234482b83d72faacb85445b5259860278512a49f3212ce62840a8db8c801d6873be377b7b6cf808693af4456185bf2a64a679b20b6f21a33b
7
+ data.tar.gz: c6f4d4e13582c15045bc040815f88c5d07562ecbb1554daccd6ea6383462ff7c56f3c0adeecc8c4eb29f800faf865a896f0edba4a80979f35c5d46fd897ba72d
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "matrix"
4
+
5
+ module IrtRuby
6
+ # A class representing the Rasch model for Item Response Theory.
7
+ class RaschModel
8
+ def initialize(data, max_iter: 1000, tolerance: 1e-6, learning_rate: 0.01)
9
+ @data = data
10
+ @abilities = Array.new(data.row_count) { rand }
11
+ @difficulties = Array.new(data.column_count) { rand }
12
+ @max_iter = max_iter
13
+ @tolerance = tolerance
14
+ @learning_rate = learning_rate
15
+ end
16
+
17
+ # Sigmoid function to calculate probability
18
+ def sigmoid(x)
19
+ 1.0 / (1.0 + Math.exp(-x))
20
+ end
21
+
22
+ # Calculate the log-likelihood of the data given the current parameters
23
+ def likelihood
24
+ likelihood = 0
25
+ @data.row_vectors.each_with_index do |row, i|
26
+ row.to_a.each_with_index do |response, j|
27
+ prob = sigmoid(@abilities[i] - @difficulties[j])
28
+ likelihood += response == 1 ? Math.log(prob) : Math.log(1 - prob)
29
+ end
30
+ end
31
+ likelihood
32
+ end
33
+
34
+ # Update parameters using gradient ascent
35
+ def update_parameters
36
+ last_likelihood = likelihood
37
+ @max_iter.times do |_iter|
38
+ @data.row_vectors.each_with_index do |row, i|
39
+ row.to_a.each_with_index do |response, j|
40
+ prob = sigmoid(@abilities[i] - @difficulties[j])
41
+ error = response - prob
42
+ @abilities[i] += @learning_rate * error
43
+ @difficulties[j] -= @learning_rate * error
44
+ end
45
+ end
46
+ current_likelihood = likelihood
47
+ break if (last_likelihood - current_likelihood).abs < @tolerance
48
+
49
+ last_likelihood = current_likelihood
50
+ end
51
+ end
52
+
53
+ # Fit the model to the data
54
+ def fit
55
+ update_parameters
56
+ { abilities: @abilities, difficulties: @difficulties }
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "matrix"
4
+
5
+ module IrtRuby
6
+ # A class representing the Three-Parameter model for Item Response Theory.
7
+ class ThreeParameterModel
8
+ def initialize(data, max_iter: 1000, tolerance: 1e-6, learning_rate: 0.01)
9
+ @data = data
10
+ @abilities = Array.new(data.row_count) { rand }
11
+ @difficulties = Array.new(data.column_count) { rand }
12
+ @discriminations = Array.new(data.column_count) { rand }
13
+ @guessings = Array.new(data.column_count) { rand * 0.3 }
14
+ @max_iter = max_iter
15
+ @tolerance = tolerance
16
+ @learning_rate = learning_rate
17
+ end
18
+
19
+ # Sigmoid function to calculate probability
20
+ def sigmoid(x)
21
+ 1.0 / (1.0 + Math.exp(-x))
22
+ end
23
+
24
+ # Probability function for the 3PL model
25
+ def probability(theta, a, b, c)
26
+ c + (1 - c) * sigmoid(a * (theta - b))
27
+ end
28
+
29
+ # Calculate the log-likelihood of the data given the current parameters
30
+ def likelihood
31
+ likelihood = 0
32
+ @data.row_vectors.each_with_index do |row, i|
33
+ row.to_a.each_with_index do |response, j|
34
+ prob = probability(@abilities[i], @discriminations[j], @difficulties[j], @guessings[j])
35
+ likelihood += response == 1 ? Math.log(prob) : Math.log(1 - prob)
36
+ end
37
+ end
38
+ likelihood
39
+ end
40
+
41
+ # Update parameters using gradient ascent
42
+ def update_parameters
43
+ last_likelihood = likelihood
44
+ @max_iter.times do |_iter|
45
+ @data.row_vectors.each_with_index do |row, i|
46
+ row.to_a.each_with_index do |response, j|
47
+ prob = probability(@abilities[i], @discriminations[j], @difficulties[j], @guessings[j])
48
+ error = response - prob
49
+ @abilities[i] += @learning_rate * error * @discriminations[j]
50
+ @difficulties[j] -= @learning_rate * error * @discriminations[j]
51
+ @discriminations[j] += @learning_rate * error * (@abilities[i] - @difficulties[j])
52
+ @guessings[j] += @learning_rate * error * (1 - prob)
53
+ @guessings[j] = [[@guessings[j], 0].max, 1].min # Keep guessings within [0, 1]
54
+ end
55
+ end
56
+ current_likelihood = likelihood
57
+ break if (last_likelihood - current_likelihood).abs < @tolerance
58
+
59
+ last_likelihood = current_likelihood
60
+ end
61
+ end
62
+
63
+ # Fit the model to the data
64
+ def fit
65
+ update_parameters
66
+ {
67
+ abilities: @abilities,
68
+ difficulties: @difficulties,
69
+ discriminations: @discriminations,
70
+ guessings: @guessings
71
+ }
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "matrix"
4
+
5
+ module IrtRuby
6
+ # A class representing the Two-Parameter model for Item Response Theory.
7
+ class TwoParameterModel
8
+ def initialize(data, max_iter: 1000, tolerance: 1e-6, learning_rate: 0.01)
9
+ @data = data
10
+ @abilities = Array.new(data.row_count) { rand }
11
+ @difficulties = Array.new(data.column_count) { rand }
12
+ @discriminations = Array.new(data.column_count) { rand }
13
+ @max_iter = max_iter
14
+ @tolerance = tolerance
15
+ @learning_rate = learning_rate
16
+ end
17
+
18
+ # Sigmoid function
19
+ def sigmoid(x)
20
+ 1.0 / (1.0 + Math.exp(-x))
21
+ end
22
+
23
+ # Calculate the log-likelihood of the data given the current parameters
24
+ def likelihood
25
+ likelihood = 0
26
+ @data.row_vectors.each_with_index do |row, i|
27
+ row.to_a.each_with_index do |response, j|
28
+ prob = sigmoid(@discriminations[j] * (@abilities[i] - @difficulties[j]))
29
+ if response == 1
30
+ likelihood += Math.log(prob)
31
+ elsif response.zero?
32
+ likelihood += Math.log(1 - prob)
33
+ end
34
+ end
35
+ end
36
+ likelihood
37
+ end
38
+
39
+ # Update parameters using gradient ascent
40
+ def update_parameters
41
+ last_likelihood = likelihood
42
+ @max_iter.times do |_iter|
43
+ @data.row_vectors.each_with_index do |row, i|
44
+ row.to_a.each_with_index do |response, j|
45
+ prob = sigmoid(@discriminations[j] * (@abilities[i] - @difficulties[j]))
46
+ error = response - prob
47
+ @abilities[i] += @learning_rate * error * @discriminations[j]
48
+ @difficulties[j] -= @learning_rate * error * @discriminations[j]
49
+ @discriminations[j] += @learning_rate * error * (@abilities[i] - @difficulties[j])
50
+ end
51
+ end
52
+ current_likelihood = likelihood
53
+ break if (last_likelihood - current_likelihood).abs < @tolerance
54
+
55
+ last_likelihood = current_likelihood
56
+ end
57
+ end
58
+
59
+ # Fit the model to the data
60
+ def fit
61
+ update_parameters
62
+ { abilities: @abilities, difficulties: @difficulties, discriminations: @discriminations }
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IrtRuby
4
+ VERSION = "0.1.0"
5
+ end
data/lib/irt_ruby.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "irt_ruby/version"
4
+ require "irt_ruby/rasch_model"
5
+ require "irt_ruby/two_parameter_model"
6
+ require "irt_ruby/three_parameter_model"
7
+
8
+ module IrtRuby
9
+ class Error < StandardError; end
10
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: irt_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alex Kholodniak
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-06-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '13.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '13.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: IrtRuby is a Ruby gem that provides implementations of the Rasch model,
56
+ Two-Parameter model, and Three-Parameter model for Item Response Theory (IRT). It
57
+ allows you to estimate the abilities of individuals and the difficulties, discriminations,
58
+ and guessing parameters of items based on their responses to a set of items.
59
+ email:
60
+ - alexandrkholodniak@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - lib/irt_ruby.rb
66
+ - lib/irt_ruby/rasch_model.rb
67
+ - lib/irt_ruby/three_parameter_model.rb
68
+ - lib/irt_ruby/two_parameter_model.rb
69
+ - lib/irt_ruby/version.rb
70
+ homepage: https://github.com/SyntaxSpirits/irt_ruby
71
+ licenses:
72
+ - MIT
73
+ metadata:
74
+ homepage_uri: https://github.com/SyntaxSpirits/irt_ruby
75
+ source_code_uri: https://github.com/SyntaxSpirits/irt_ruby
76
+ changelog_uri: https://github.com/SyntaxSpirits/irt_ruby/CHANGELOG.md
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '2.6'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubygems_version: 3.4.16
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: A Ruby gem that provides implementations of Rasch, Two-Parameter, and Three-Parameter
96
+ models for Item Response Theory (IRT).
97
+ test_files: []