Описание набора данных

В наши дни большие языковые модели и приложения или инструменты находятся во всех новостях и социальных сетях. Страница трендов GitHub демонстрирует значительное присутствие репозиториев, которые широко используют большие языковые модели. Мы увидели фантастические возможности больших языковых моделей для написания текстов для маркетинга, обобщения документов, сочинения музыки и генерации кода для разработки программного обеспечения.

Предприятия имеют множество табличных данных (один из старейших и наиболее распространенных форматов данных, которые могут быть представлены в виде таблицы со строками и столбцами), накопленных внутри компании и в Интернете. Можем ли мы применить большие языковые модели к табличным данным в традиционном жизненном цикле машинного обучения, чтобы повысить производительность модели и добавить ценность для бизнеса?

В этой статье мы рассмотрим следующую тему с полным кодом реализации Python:

  • Подскажите инженерам преобразовать табличные данные в текст
  • Нулевая классификация с API OpenAI (модель GPT-3.5: text-davinci-003)
  • Повышение производительности модели машинного обучения с помощью API встраивания OpenAI — text-embedding-ada-002
  • Объяснимость прогнозов с помощью OpenAI API — gpt-3.5-turbo
  • age: возраст заявителя

Модели машинного обучения

Данные доступны на веб-сайте Kaggle по лицензии CC0 1.0 Universal (CC0 1.0) Public Domain Dedication, которая не является авторским правом (вы можете копировать, изменять, распространять и выполнять работу даже в коммерческих целях). Пожалуйста, перейдите по указанной ниже ссылке:



Он содержит демографические характеристики, медицинские показания и цели. Столбцы поясняются ниже:

  • пол: пол заявителя
  • cp: тип боли в груди: значение 1 — типичная стенокардия, значение 2 — атипичная стенокардия, значение 3 — неангинозная боль и значение 4 — бессимптомная.
  • trtbps: артериальное давление в покое (в мм рт. ст.)
  • chol: холестерин в мг/дл, полученный с помощью датчика ИМТ
  • fbs: уровень сахара в крови натощак > 120 мг/дл, 1 = верно, 0 = неверно
  • restecg: результаты электрокардиографии в покое
  • талах: достигнута максимальная частота сердечных сокращений
  • exng: стенокардия, вызванная физической нагрузкой (1 = да; 0 = нет)
  • старый пик: предыдущий пик
  • слп: наклон
  • caa: количество крупных судов
  • thall: тал ставка
  • вывод: целевая переменная, 0 = меньше вероятность сердечного приступа, 1 = больше вероятность сердечного приступа
  • Предварительная обработка: проверка отсутствующих значений, горячее кодирование, стратифицированное разделение обучающих тестов и т. д.

Нулевая классификация с OpenAI API

Модели бинарной классификации разработаны для прогнозирования вероятности сердечного приступа. Этот раздел будет охватывать:

  • Построение 4 моделей, включая три обобщенные линейные модели и одну древовидную модель: логистическая регрессия, гребень, лассо и случайный лес.
  • Оценка модели с помощью AUC
  • Модель на основе дерева (случайный лес) лучше всего работает с гораздо более высоким AUC.

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

import warnings
warnings.filterwarnings("ignore")

# Math and Vectors
import pandas as pd
import numpy as np

# Visualizations
import plotly.express as px

# ML
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
import concurrent.futures

# Utils functions
from utils import prediction, compile_prompt, get_embedding, ml_models, create_auc_chart, gpt_reasoning
pd.set_option('display.max_columns', None)

# load data
df = pd.read_csv("./data/raw data/heart_attack_predicton_kaggle.csv")
df.shape

# check missing value
df.isna().sum()

# check outcome distribution
df['output'].value_counts()

# one-hot encoding
cat_cols = ['sex','exng','cp','fbs','restecg','slp','thall']
df_model = pd.get_dummies(df,columns=cat_cols)
df_model.shape

# train test stratified split
# Seperate dependent and independent variables
X = df_model.drop(axis=1,columns=['output'])
y = df_model['output'].tolist()
X_tr, X_val, y_tr, y_val = train_test_split(X, y, test_size=0.2, random_state=101,
                                                stratify=y,shuffle=True)

Теперь давайте построим объект модели, подгоним модель, сделаем прогноз на тестовом наборе и рассчитаем AUC.

## model function
def ml_models():
    lr = LogisticRegression(penalty='none', solver='saga', random_state=42, n_jobs=-1)
    lasso = LogisticRegression(penalty='l1', solver='saga', random_state=42, n_jobs=-1)
    ridge = LogisticRegression(penalty='l2', solver='saga', random_state=42, n_jobs=-1)
    rf = RandomForestClassifier(n_estimators=300, max_depth=5, min_samples_leaf=50, 
                                max_features=0.3, random_state=42, n_jobs=-1)
    models = {'LR': lr, 'LASSO': lasso, 'RIDGE': ridge, 'RF': rf}
    return models

models = ml_models()
lr = models['LR']
lasso = models['LASSO'] 
ridge = models['RIDGE'] 
rf = models['RF'] 

pred_dict = {}
for k, m in models.items():
    print(k)
    m.fit(X_tr, y_tr)
    preds = m.predict_proba(X_val)[:,1]
    auc = roc_auc_score(y_val, preds)
    pred_dict[k] = preds
    print(k + ': ', auc)

Далее давайте визуализируем и сравним производительность модели (AUC).

В этой визуализации:

  • 3 обобщенные линейные модели имеют аналогичный уровень производительности, а AUC ниже, чем ожидаемая древовидная модель.
  • Предварительная обработка табличных данных для оперативного инжиниринга

Предварительная обработка табличных данных

Мы выполним нулевую классификацию табличных данных с помощью API OpenAI, основанного на модели text-davinci-003. Прежде чем мы углубимся в реализацию Python, давайте немного разберемся с классификацией нулевого выстрела. Определение от Hugging face:

Классификация Zero Shot — это задача прогнозирования класса, который не был замечен моделью во время обучения. Этот метод, использующий предварительно обученную языковую модель, можно рассматривать как пример переносного обучения, которое обычно относится к использованию модели, обученной для одной задачи, в приложении, отличном от того, для чего она была изначально обучена. Это особенно полезно в ситуациях, когда количество помеченных данных невелико.

В нулевой классификации модель получает подсказку и последовательность текста, описывающую то, что мы хотим, чтобы модель делала, и без каких-либо примеров ожидаемого поведения. Этот раздел будет охватывать:

  • Побуждение LLM
  • Прогноз нулевого выстрела с помощью API GPT-3.5: text-davinci-003
  • Оценка модели с помощью AUC
  • Как получить вложения OpenAI через вызов API

Побуждение LLM

Во-первых, давайте обработаем данные перед запросом:

df_gpt = df.copy()
df_gpt['sex'] = np.where(df_gpt['sex'] == 1, 'Male', 'Female')
df_gpt['cp'] = np.where(df_gpt['cp'] == 1, 'Typical angina', 
                       np.where(df_gpt['cp'] == 2, 'Atypical angina', 
                       np.where(df_gpt['cp'] == 3, 'Non-anginal pain', 'Asymptomatic')))
df_gpt['fbs'] = np.where(df_gpt['fbs'] == 1, 'Fasting blood sugar > 120 mg/dl', 'Fasting blood sugar <= 120 mg/dl')
df_gpt['restecg'] = np.where(df_gpt['restecg'] == 0, 'Normal', 
                       np.where(df_gpt['restecg'] == 1, 'Having ST-T wave abnormality (T wave inversions and/or ST elevation or depression of > 0.05 mV)', 
                                    "Showing probable or definite left ventricular hypertrophy by Estes' criteria"))
df_gpt['exng'] = np.where(df_gpt['exng'] == 1, 'Exercise induced angina', 'Without exercise induced angina')
df_gpt['slp'] = np.where(df_gpt['slp'] == 0, 'The slope of the peak exercise ST segment is downsloping', 
                       np.where(df_gpt['slp'] == 1, 'The slope of the peak exercise ST segment is flat', 
                                    'The slope of the peak exercise ST segment is upsloping'))
df_gpt['thall'] = np.where(df_gpt['thall'] == 1, 'Thall is fixed defect', 
                       np.where(df_gpt['thall'] == 2, 'Thall is normal', 'Thall is reversable defect'))

# test df to dict
application_list = X_val.to_dict(orient='records')
len(application_list)

Получить ответ API — многопроцессорность

Подсказки — это мощный инструмент для взаимодействия с большими языковыми моделями для выполнения определенной задачи. Подсказка — это пользовательский ввод, на который модель должна реагировать. Подсказки могут быть различной формы, т. е. текст, изображение.

В этой статье подсказка включает инструкции с ожидаемым форматом вывода JSON и сам вопрос. С набором данных сердечного приступа текстовое приглашение может быть таким:

Далее мы определим подсказку и функцию вызова API, которая создает подсказку и получает ответ от API OpenAI-3.5.

def prediction_GPT3_5(data, explain = False):
    if explain:
        prompt = prompt_logic(explain)
    else:    
        prompt = prompt_logic(explain)
    print(prompt)
    response = openai.Completion.create(
        model = 'text-davinci-003',
        prompt=prompt,
        max_tokens=64,
        n=1,
        stop=None,
        temperature=0.5,
        top_p=1.0,
        frequency_penalty=0.0,
        presence_penalty=0.0
    )

    try:
        output = response.choices[0].text.strip()
        output_dict = json.loads(output)
        return output_dict
    except (IndexError, ValueError):
        return None

def prediction(combined_data_argu):
    application_data, explain = combined_data_argu
    response = prediction_GPT3_5(application_data, explain)
    return response

Классификация нулевого выстрела AUC

Многопроцессорность используется для ускорения вызова API. Код:

### get prediction from GPT-3.5 model: text-davinci-003 - multiprocessing pool
with concurrent.futures.ThreadPoolExecutor() as executor:
    # Combine credit_data and explain into a single iterable
    combined_data = zip(application_list, [False] * len(application_list))
    # Submit the transaction processing tasks to the executor
    results = executor.map(prediction, combined_data)

    # Collect the responses into a list
    responses = list(results)
responses_df = pd.DataFrame(responses)
responses_df.shape

Повысьте производительность модели машинного обучения с помощью встраивания OpenAI

AUC составляет 0,48 для классификации с нулевым выстрелом, что предполагает, что прогнозы хуже, чем случайный случай, и указывает на то, что потенциально в модели GPT-3.5 text-davinci-003 в этом наборе данных нет утечки.

auc_gpt= roc_auc_score(y_val, responses_df['output'])
auc_gpt

Сравнение производительности модели — с функциями встраивания и без них

Встраивание LLM — это конечная точка большой языковой модели (например, OpenAI API), которая упрощает выполнение задач на естественном языке и коде, таких как семантический поиск, кластеризация, моделирование тем и классификация. Благодаря быстрой разработке табличные данные преобразуются в текст на естественном языке, который можно использовать для создания вложений. Вложения могут улучшить производительность традиционных моделей машинного обучения, позволяя им лучше понимать естественный язык и адаптировать контекст с небольшим объемом размеченных данных. Короче говоря, в этом контексте это один из типов разработки функций.

Инжиниринг признаков — это процесс преобразования необработанных данных в признаки, которые лучше представляют основную проблему для прогностических моделей, что приводит к повышению точности модели на невидимых данных.

В этом разделе вы увидите:

  • Сравнение производительности модели — с функциями встраивания и без них
  • Встроенные функции незначительно улучшают производительность обобщенной линейной модели (логистическая регрессия, поездка и лассо).

Во-первых, давайте определим функцию для получения вложений через API и слияния с необработанным набором данных:

# define function to fetch the embedding
def get_embedding(text, model="text-embedding-ada-002"):
   text = text.replace("\n", " ")
   return openai.Embedding.create(input = [text], model=model)['data'][0]['embedding']

# API call and merge with raw data
df_gpt['ada_embedding'] = df_gpt.combined.apply(lambda x: get_embedding(x, model='text-embedding-ada-002'))
df_gpt = df_gpt.join(pd.DataFrame(df_gpt['ada_embedding'].apply(pd.Series)))
df_gpt.drop(['combined', 'ada_embedding'], axis = 1, inplace = True)
df_gpt.columns = df_gpt.columns.tolist()[:14] + ['Embedding_' + str(i) for i in df_gpt.columns.tolist()[14:]]
df = pd.concat([df, df_gpt[[i for i in df_gpt.columns.tolist() if i.startswith('Embedding_')]]], axis=1)
df_gpt.shape

Подобно чистым моделям машинного обучения, мы также проведем стратифицированное разделение и подгонку модели:

# Seperate dependent and independent variables
X = df.drop(axis=1,columns=['output'])
y = df['output'].tolist()

X_tr, X_val, y_tr, y_val = train_test_split(X, y, test_size=0.2, random_state=101,
                                                stratify=y,shuffle=True)
models = ml_models()
lr = models['LR']
lasso = models['LASSO'] 
ridge = models['RIDGE'] 
rf = models['RF'] 
pred_dict_gpt = {}
for k, m in models.items():
    print(k)
    m.fit(X_tr, y_tr)
    preds = m.predict_proba(X_val)[:,1]
    auc = roc_auc_score(y_val, preds)
    pred_dict_gpt[k + '_With_GPT_Embedding'] = preds
    print(k + '_With_GPT_Embedding' + ': ', auc)

Объяснимость модели с помощью OpenAI API — gpt-3.5-turbo

Комбинируя модели без встроенных функций, мы получаем всего 8 моделей. Кривая ROC на тестовом наборе приведена ниже:

pred_dict_combine = dict(list(pred_dict.items()) + list(pred_dict_gpt.items()))
create_auc_chart(pred_dict_combine, y_val, 'Model AUC')

Как правило, мы наблюдаем:

  • Модель случайного леса с внедренными функциями работает лучше всего и немного лучше, чем модель случайного леса без встроенных функций.
  • Подготовка ввода для OpenAI API

Мы видим потенциал интеграции больших языковых моделей в традиционный процесс обучения моделей и повышения качества результатов. У нас может возникнуть вопрос: могут ли большие языковые модели помочь объяснить модельное решение? Давайте коснемся этого в следующем разделе.

Краткое содержание

Объяснимость модели — одна из ключевых тем в приложениях машинного обучения, особенно в таких областях, как страхование, здравоохранение, финансы и право, где пользователям необходимо понимать, как модель принимает решение на локальном и глобальном уровне. Я написал статью, посвященную Интерпретация модели глубокого обучения с использованием SHAP, если вы хотите узнать больше об интерпретации модели в моделях глубокого обучения.

Этот раздел охватывает:

  • Получение рассуждений через модель gpt-3.5-turbo
  • «https://platform.openai.com/docs/guides/embeddings/what-are-embeddings»

Во-первых, давайте подготовим ввод для вызова API.

application_data = application_list[0]
application_data

{'age': 51,
 'sex': 'Male',
 'cp': 'Atypical angina',
 'trtbps': 125,
 'chol': 245,
 'fbs': 'Fasting blood sugar > 120 mg/dl',
 'restecg': 'Normal',
 'thalachh': 166,
 'exng': 'Without exercise induced angina',
 'oldpeak': 2.4,
 'slp': 'The slope of the peak exercise ST segment is flat',
 'caa': 0,
 'thall': 'Thall is normal'}

Далее давайте обсудим, вызвав gpt-3.5-turbo API.

message_objects = [
        {"role": "system", "content": '''You are a medical expert / underwriter in a global insurance company. Your job is to evaluate the chance of having heart attack. Please encode your response as json in the following format
        {{
            "decision": "<Either less chance of heart attack or more chance of heart attack>",
        }}'''},
        {"role": "user", "content": prompt},
    ]

completion = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=message_objects,
        max_tokens=1000,  # Adjust the max_tokens as per your desired response length
        stop=None,  # Set custom stop conditions if required
    )

# Extract the response message content
    response_content = completion.choices[0].message["content"]

Ответ впечатляет, а большая языковая модель демонстрирует сильные способности к рассуждениям наряду с разумными объяснениями.

Большие языковые модели — это мощный инструмент для решения широкого спектра вариантов использования в различных отраслях. Создание приложений LLM стало проще и доступнее. LLM определенно добавят предприятию реальную ценность для бизнеса.

Давай останемся на связи…

Приглашаю вас присоединиться ко мне в захватывающем и плодотворном приключении по изучению данных! Оставайтесь на связи, подписавшись на мою страницу «Medium», чтобы получать постоянный поток захватывающего контента по науке о данных. В ближайшие месяцы я поделюсь более подробной информацией об основах машинного обучения, основах НЛП и комплексной реализации науки о данных. Здоровья!

Ссылка

Что такое классификация Zero-Shot? – Hugging Face
Узнайте о классификации Zero-Shot с помощью машинного обученияhuggingface.co

Построение обобщенных линейных моделей и древовидной модели на общедоступном наборе данных Kaggle «Heart Attack Analysis & Prediction Dataset».







Улучшение прогнозирования табличных данных с помощью большой языковой модели через OpenAI API