борьба с развертыванием проекта классификатора машинного обучения

Вопрос или проблема

Пожалуйста, может кто-нибудь помочь мне с этим? Когда я пытаюсь отладить веб-приложение после применения алгоритмов машинного обучения (векторизация BagOfWords и классификаторы), я столкнулся с проблемами, и ошибка была следующей:

  File "c:\Users\LENOVO\Desktop\webapp\app2.py", line 42, in predict
    tweet_vect = words.transform([tweet]).toarray()
AttributeError: 'numpy.ndarray' object has no attribute 'transform'
127.0.0.1 - - [14/Apr/2023 11:29:54] "POST / HTTP/1.1" 500 

Итак, мой код выглядит следующим образом, model.py :

df = pd.read_csv ('C:\\Users\\LENOVO\\Desktop\\webapp\\df.csv')
df.head()

from nltk.stem import WordNetLemmatizer
lemma= WordNetLemmatizer()
stop = stopwords.words('English')
def clean_tweets(text):
    text = text.lower()
    words= nltk.word_tokenize(text)
# Лемматизация - это еще одна техника, используемая для уменьшения измененных слов до их корневого слова. Она описывает алгоритмический процесс идентификации «леммы» измененного слова (словарная форма) на основе его предполагаемого значения.
    words=" ".join ([lemma.lemmatize(word) for word in words 
                     if word not in (stop)])
    text="".join(words)
# удаление не буквенных символов
    text = re.sub('[^a-z]',' ',text)
    return text


# создание корпуса:
from nltk.stem import PorterStemmer
df.head(10)
corpus  = []
pstem = PorterStemmer()
for i in range(df['cleaned_tweets'].shape[0]):
    tweet = re.sub("[^a-zA-Z]", ' ', df['cleaned_tweets'][i])
    #Преобразование слов в строчные
    tweet = tweet.split()
    #Удаление стоп-слов, затем стемминг
    tweet = [pstem.stem(word) for word in tweet if not word in set(stopwords.words('english'))]
    tweet=" ".join(tweet) 
    #Добавление очищенного твита в корпус
    corpus.append(tweet)

df = df.drop(['text'],axis=1)
print("Корпус успешно создан") 
print(pd.DataFrame(corpus)[0].head(10))
rawTexData = df["cleaned_tweets"].head(10)
cleanTexData = pd.DataFrame(corpus, columns=['corpus'])
frames = [rawTexData, cleanTexData]
result = pd.concat(frames, axis=1, sort=False)
result

#Создание нашего словаря 
uniqueWordFrequents = {}
for tweet in corpus:
    for word in tweet.split():
        if(word in uniqueWordFrequents.keys()):
            uniqueWordFrequents[word] += 1
        else:
            uniqueWordFrequents[word] = 1
            
#Преобразование словаря в DataFrame
uniqueWordFrequents = pd.DataFrame.from_dict(uniqueWordFrequents,orient="index",columns=['Word Frequent'])
uniqueWordFrequents.sort_values(by=['Word Frequent'], inplace=True, ascending=False)
uniqueWordFrequents.head(10)
uniqueWordFrequents['Word Frequent'].unique()
uniqueWordFrequents = uniqueWordFrequents[uniqueWordFrequents['Word Frequent'] >= 20]
print(uniqueWordFrequents.shape)
from sklearn.feature_extraction.text import CountVectorizer
counVec = CountVectorizer(max_features = uniqueWordFrequents.shape[0])
bagOfWords = counVec.fit_transform(corpus).toarray()



b = bagOfWords
y = df['target']

print("b shape = ",b.shape)
print("y shape = ",y.shape)

b_train , b_test , y_train , y_test = train_test_split(b,y,test_size=0.20, random_state=55, shuffle =True)
print('разделение данных успешно')
multinomialNBModel = MultinomialNB(alpha=0.1)
multinomialNBModel.fit(b_train,y_train)

print("модель multinomialNB выполнена успешно")

passModel=PassiveAggressiveClassifier()
passModel.fit(b_train,y_train)
print ('модель Passive Regressive выполнена успешно')

modelsNames = [('multinomialNBModel',multinomialNBModel),
               ('PassiveAggressiveClassifier',passModel)]

from sklearn.ensemble import VotingClassifier
votingClassifier = VotingClassifier(voting = 'hard',estimators= modelsNames)
votingClassifier.fit(b_train,y_train)
print("модель votingClassifier выполнена успешно")



models = [multinomialNBModel, passModel, votingClassifier]

for model in models:
    print(type(model).__name__,' Тестовый балл: ' ,model.score(b_train, y_train))
    print(type(model).__name__,' Балл на тесте: ' ,model.score(b_test, y_test))
    
    y_pred = model.predict(b_test)
    print(type(model).__name__,' F1 Балл: ' ,f1_score(y_test,y_pred))

    

 
bagOfWords
import pickle
pickle.dump(votingClassifier, open("model.pkl", "wb"))
pickle.dump(bagOfWords, open("words.pkl", "wb"))

app2.py:

from flask import Flask
from flask import render_template
from flask import request
from flask import jsonify
from flask import redirect
from flask import url_for
import re
import nltk
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
import numpy as np
import joblib
nltk.download('stopwords')
import pickle

app = Flask(__name__)
ps = PorterStemmer()

model = pickle.load(open('model.pkl', 'rb'))
words = pickle.load(open('words.pkl', 'rb'))
       
# Построение функциональности
@app.route("https://datascience.stackexchange.com/", methods=['GET'])
def home():
    return render_template('index2.html')

def predict(text):
    tweet = re.sub('[^a-zA-Z]', ' ', text)
    tweet = tweet.lower()
    tweet = tweet.split()
    tweet = [ps.stem(word) for word in tweet if not word in stopwords.words('english')]
    tweet=" ".join(tweet)
    tweet_vect = words.transform([tweet]).toarray()
    prediction = 'FAKE' if model.predict(tweet_vect) == 0 else 'REAL'
    return prediction
@app.route("https://datascience.stackexchange.com/", methods=['POST'])
def webapp():
    text = request.form['text']
    prediction = predict(text)
    return render_template('index2.html', text=text, result=prediction)
@app.route('/predict/', methods=['GET','POST'])
def api():
    text = request.args.get('text')
    prediction = predict(text)
    return jsonify(prediction=prediction)
if __name__ == "__main__":
    app.run()

пожалуйста, любая помощь

Ошибка возникает, когда выполнение доходит до этой строки в app.py:

tweet_vect = words.transform([tweet]).toarray()

Помните, что transform – это один из методов класса CountVectorizer. Следовательно, если переменная words хранила такой класс, эта строка сработала бы. Поскольку этого не произошло, это говорит о том, что переменная, вероятно, не хранит экземпляр CountVectorizer 🙂

На самом деле, если вы проверите, как эта переменная была определена ранее в model.py и затем сохранена, вы найдете эту строку:

bagOfWords = counVec.fit_transform(corpus).toarray()

Обратите внимание, что в этом выражении метод toarray был последним, который был вызван, что означает, что значение, хранящееся в bagOfWords, было выводом этого метода, а не фактическим экземпляром CountVectorizer (который и имеет метод transform, который здесь потерян).

Вот почему, когда вы пытаетесь вызвать этот метод на объекте, который был сохранен, программа не может его найти.

Эта конкретная ошибка может быть решена заменой этой строки в model.py:

bagOfWords = counVec.fit_transform(corpus).toarray()

на

bagOfWords = counVec.fit_transform(corpus)

но я не анализировал все возможные зависимости в коде и, если значение этой переменной предполагается использовать в виде массива где-то еще, вы можете вводить новые ошибки, поэтому будьте осторожны с любыми изменениями. В общем, вы всегда хотите сохранить весь экземпляр CountVectorizer как этот объект, потому что он будет полезен позже для воспроизводимости.

Удачи!

Ответ или решение

Конечно! Давайте разберем вашу проблему с развертыванием проекта классификатора машинного обучения.

Ошибка, с которой вы столкнулись:

AttributeError: 'numpy.ndarray' object has no attribute 'transform'

Происходит она из-за того, что вы вызываете метод transform() для объекта, который на самом деле является numpy.ndarray, а не экземпляром класса CountVectorizer. Это произошло, когда вы сделали следующее в вашем файле model.py:

bagOfWords = counVec.fit_transform(corpus).toarray()

Метод fit_transform возвращает матрицу признаков в виде numpy.ndarray, когда вы вызываете toarray(), и, таким образом, вы потеряли доступ к объекту CountVectorizer, который содержит метод transform().

Решение проблемы

Чтобы исправить эту ошибку, вам необходимо сохранить сам объект CountVectorizer, а не только его выходные данные. Вот как вы можете это сделать:

  1. Замените строку
bagOfWords = counVec.fit_transform(corpus).toarray()

на

bagOfWords = counVec.fit_transform(corpus)  # Здесь мы сохраняем только разреженную матрицу
  1. В конце вашего кода model.py, добавьте следующую строчку, чтобы сохранить сам объект CountVectorizer:
pickle.dump(counVec, open("words.pkl", "wb"))  # Сохраняем объект CountVectorizer

Теперь ваш файл words.pkl будет содержать сам объект CountVectorizer, и вы сможете вызывать метод transform() на нем в вашем приложении Flask.

Обновленный код для model.py

Ваш обновленный код в model.py должен выглядеть так:

from sklearn.feature_extraction.text import CountVectorizer

# Ваш предыдущий код...

# Создаем словарь
uniqueWordFrequents = {}
# Логика создания уникальных частот слов...

# Создаем объект CountVectorizer
counVec = CountVectorizer(max_features = uniqueWordFrequents.shape[0])
bagOfWords = counVec.fit_transform(corpus)  # Изменено

# Сохраняем модели и векторы
pickle.dump(votingClassifier, open("model.pkl", "wb"))
pickle.dump(counVec, open("words.pkl", "wb"))  # Изменено

Обновленный код для app2.py

Убедитесь, что в app2.py вы загружаете объект CountVectorizer следующим образом:

words = pickle.load(open('words.pkl', 'rb'))  # Этот объект теперь содержит ваш CountVectorizer

Теперь при вызове метода transform() у вас не должно быть ошибок, и вы сможете успешно развернуть ваш проект.

Если у вас возникнут дополнительные вопросы или вам потребуется помощь с другими аспектами проекта, не стесняйтесь спрашивать! Желаю удачи в вашей работе над проектом классификации!

Оцените материал
Добавить комментарий

Капча загружается...