Spaces:
Runtime error
Runtime error
import numpy as np | |
from codeScripts.rubrics import * | |
class PlentasMethodology(): | |
""" | |
The methodology developed in Plentas consists in iteratively compute the similarity between two sentences: the baseline response and one variable group of sentences from the student's response. The goal of it is to identify in the text the subresponses to each subquestion so the answer-question similarity is better obtained and thus the overall calculated similarity fits better to the expected one. | |
Inputs: | |
-settings: The settings from the config json and the api. | |
""" | |
def __init__(self, settings): | |
self.settings = settings | |
self.maxSimilarity = -99999 | |
self.SemanticLevel = Semantica2(self.settings) | |
def getSimilarity(self, sentences, similarityMethod): | |
""" | |
This function calculates the similarity between two responses using the Plentas methodology | |
Inputs: | |
sentences: pre-processed sentences of the student's response | |
similarityMethod: choose between spacy or bert | |
Outputs: | |
similarity: an array of the generated similarity for each subquestion | |
""" | |
#Initializing the similarity array so if the student's response is blank default content is output | |
similarity = np.zeros(len(self.settings.indice_minipreguntas)) | |
#obtaining the similarity for each subquestion | |
for minirespuesta, minipregunta in zip(self.settings.minirespuestas, self.settings.indice_minipreguntas): | |
self.SemanticLevel.output.initInforms(self.settings.studentID, minipregunta, similarityMethod) | |
#if the response is not blank ... | |
if len(sentences) >= 1 and sentences[0] != '': | |
self.maxSimilarity = -99999 | |
#varying the group of sentences | |
for agrupation in list(range(self.settings.minAgrupation,self.settings.maxAgrupation)): | |
#varying the size of the group of sentences | |
for s in range(len(sentences)): | |
try: | |
#extracting the sentences | |
r_alumno, r_label = self.__Line2LineAnalysis__(sentences, s, agrupation) | |
#computing its similarity | |
#similar = self.__computeSimilarity__(r_alumno, minirespuesta, similarityMethod) | |
similar = self.SemanticLevel.computeSimilarity(r_alumno, minirespuesta, similarityMethod) | |
self.SemanticLevel.output.updateInformsBucle(self.settings.studentID, minipregunta, r_alumno, r_label, agrupation, similar, similarityMethod, 1 if similar > self.maxSimilarity else 0) | |
#storing the highest | |
if similar > self.maxSimilarity: | |
self.maxSimilarity = similar | |
except: | |
break | |
#stacking the similarity of each subquestion | |
similarity[int(minipregunta[12:])] = self.maxSimilarity | |
return similarity | |
def __Line2LineAnalysis__(self, sentences, size, start): | |
""" | |
This function extracts the required group of sentences from a response. | |
Inputs: | |
-sentences: the array of sentences from the student's response | |
-size: the max number of sentences to extract. | |
-start: the array position from where to start extracting | |
Outputs: | |
respuesta_alumno: the extracted sentences | |
r_name: the label of those sentences (their position in the response and, thus, in the input array) | |
""" | |
new_respuesta = "" | |
breaking_variable = sentences[size+start-1] | |
for line in sentences[size:size+start]: | |
new_respuesta= new_respuesta + line + '. ' | |
respuesta_alumno = new_respuesta.lower() | |
if start == 1: | |
r_name = "Line " + str(size+1) | |
else: | |
r_name = "Lines " + str(size+1) + " - " + str(size+start) | |
return respuesta_alumno, r_name | |
def EvaluationMethod(self, studentID, response, similarity_array, similarity_type = "spacy"): | |
notaSemantica = 0 | |
esSuperior = 0 | |
esIntermedio = 0 | |
for umbralL, umbralH in zip(self.SemanticLevel.output.min_umbral, self.SemanticLevel.output.max_umbral): | |
for minipregunta, similarity in zip(self.settings.indice_minipreguntas, similarity_array): | |
print(minipregunta, similarity) | |
if similarity >= umbralL: | |
if similarity <= umbralH: | |
if not esSuperior: | |
esIntermedio = 1 | |
else: | |
esIntermedio = 0 | |
esSuperior = 1 | |
if esSuperior: | |
notaSemantica +=1 | |
elif esIntermedio: | |
notaSemantica += 0.5 | |
esSuperior = 0 | |
esIntermedio = 0 | |
notaSemantica = notaSemantica/len(self.settings.indice_minipreguntas) | |
self.SemanticLevel.output.updateInforms(studentID, umbralL, umbralH, notaSemantica, similarity_type, response) | |
#Descomment if analyzing more than one threshold option | |
#if umbralL == 0.3 and umbralH == 0.7: | |
#notaGuardar = notaSemantica | |
#notaSemantica = 0 | |
#return notaGuardar | |
return notaSemantica | |