Anatomie – chatgpz.de – KI-Tools & Praxiswissen https://chatgpz.de Unabhängige Tests, Anleitungen und Hintergründe zu KI-Tools. Fri, 14 Mar 2025 09:42:45 +0000 de-DE hourly 1 https://wordpress.org/?v=6.4.2 234900186 Anatomie einer Parkettdatei https://chatgpz.de/artificial-intelligence/anatomie-einer-parkettdatei/ https://chatgpz.de/artificial-intelligence/anatomie-einer-parkettdatei/#respond Fri, 14 Mar 2025 09:42:45 +0000 http://chatgpz.de/artificial-intelligence/anatomie-einer-parkettdatei/ [ad_1]

In den letzten Jahren ist Parquet zu einem Standardformat für die Datenspeicherung in geworden Huge Information Ökosysteme. Das säulenorientierte Format bietet mehrere Vorteile:

  • Eine schnellere Abfrageausführung, wenn nur eine Teilmenge von Spalten verarbeitet wird
  • Schnelle Berechnung von Statistiken über alle Daten hinweg
  • Reduziertes Speichervolumen dank einer effizienten Komprimierung

In Kombination mit Speicher -Frameworks wie Delta Lake oder Apache Iceberg integriert es sich nahtlos in Question -Engines (z. B. Trino) und Information Warehouse Compute Cluster (z. B. Snowflake, BigQuery). In diesem Artikel wird der Inhalt einer Parquetdatei unter Verwendung hauptsächlich Commonplace -Python -Instruments analysiert, um ihre Struktur besser zu verstehen und wie sie zu solchen Leistungen beiträgt.

Schreiben von Parkettdateien (en)

Um Parkettdateien zu erzeugen, verwenden wir Pyarrow, eine Python -Bindung für Apache -Pfeil, die Datenframes im Speicher im Spaltenformat speichert. Pyarrow ermöglicht eine feinkörnige Parameterabstimmung beim Schreiben der Datei. Dies macht Pyarrow perfect für die Manipulation des Parketts (man kann auch einfach verwenden Pandas).

# generator.py

import pyarrow as pa
import pyarrow.parquet as pq
from faker import Faker

pretend = Faker()
Faker.seed(12345)
num_records = 100

# Generate pretend information
names = (pretend.identify() for _ in vary(num_records))
addresses = (pretend.tackle().exchange("n", ", ") for _ in vary(num_records))
birth_dates = (
    pretend.date_of_birth(minimum_age=67, maximum_age=75) for _ in vary(num_records)
)
cities = (addr.break up(", ")(1) for addr in addresses)
birth_years = (date.12 months for date in birth_dates)

# Forged the info to the Arrow format
name_array = pa.array(names, kind=pa.string())
address_array = pa.array(addresses, kind=pa.string())
birth_date_array = pa.array(birth_dates, kind=pa.date32())
city_array = pa.array(cities, kind=pa.string())
birth_year_array = pa.array(birth_years, kind=pa.int32())

# Create schema with non-nullable fields
schema = pa.schema(
    (
        pa.area("identify", pa.string(), nullable=False),
        pa.area("tackle", pa.string(), nullable=False),
        pa.area("date_of_birth", pa.date32(), nullable=False),
        pa.area("metropolis", pa.string(), nullable=False),
        pa.area("birth_year", pa.int32(), nullable=False),
    )
)

desk = pa.Desk.from_arrays(
    (name_array, address_array, birth_date_array, city_array, birth_year_array),
    schema=schema,
)

print(desk)
pyarrow.Desk
identify: string not null
tackle: string not null
date_of_birth: date32(day) not null
metropolis: string not null
birth_year: int32 not null
----
identify: (("Adam Bryan","Jacob Lee","Candice Martinez","Justin Thompson","Heather Rubio"))
tackle: (("822 Jennifer Area Suite 507, Anthonyhaven, UT 98088","292 Garcia Mall, Lake Belindafurt, IN 69129","31738 Jonathan Mews Apt. 024, East Tammiestad, ND 45323","00716 Kristina Path Suite 381, Howelltown, SC 64961","351 Christopher Expressway Suite 332, West Edward, CO 68607"))
date_of_birth: ((1955-06-03,1950-06-24,1955-01-29,1957-02-18,1956-09-04))
metropolis: (("Anthonyhaven","Lake Belindafurt","East Tammiestad","Howelltown","West Edward"))
birth_year: ((1955,1950,1955,1957,1956))

Die Ausgabe spiegelt im Gegensatz zu Pandas eindeutig einen spaltenorientierten Speicher wider, in dem normalerweise eine herkömmliche „zeilenweise“ Tabelle angezeigt wird.

Wie wird eine Parquetdatei gespeichert?

Parquetdateien werden in der Regel in billigen Objektspeicherdatenbanken wie S3 (AWS) oder GCS (GCP) gespeichert, um durch Datenverarbeitungspipelines leicht zugänglich zu werden. Diese Dateien werden normalerweise mit einer Partitionierungsstrategie organisiert, indem Verzeichnisstrukturen eingesetzt werden:

# generator.py

num_records = 100

# ...

# Writing the parquet information to disk
pq.write_to_dataset(
    desk,
    root_path='dataset',
    partition_cols=('birth_year', 'metropolis')
)

Wenn birth_year Und metropolis columns werden als Partitionierungsschlüssel definiert, Pyarrow erstellt eine solche Baumstruktur im Verzeichnisdatensatz:

dataset/
├─ birth_year=1949/
├─ birth_year=1950/
│ ├─ metropolis=Aaronbury/
│ │ ├─ 828d313a915a43559f3111ee8d8e6c1a-0.parquet
│ │ ├─ 828d313a915a43559f3111ee8d8e6c1a-0.parquet
│ │ ├─ …
│ ├─ metropolis=Alicialand/
│ ├─ …
├─ birth_year=1951 ├─ ...

Die Strategie ermöglicht das Partitionsbeschneiden: Wenn eine Abfrage in diesen Spalten filtert, kann die Engine Ordnernamen verwenden, um nur die erforderlichen Dateien zu lesen. Aus diesem Grund ist die Partitionierungsstrategie entscheidend für die Begrenzung von Verzögerungs-, E/A- und Berechnung von Ressourcen, wenn große Datenmengen behandelt werden (wie es seit Jahrzehnten mit herkömmlichen relationalen Datenbanken der Fall ist).

Der Beschneidungseffekt kann leicht überprüft werden, indem die Dateien gezählt werden, die durch ein Python -Skript eröffnet werden, das das Geburtsjahr filtert:

# question.py
import duckdb

duckdb.sql(
    """
    SELECT * 
    FROM read_parquet('dataset/*/*/*.parquet', hive_partitioning = true)
    the place birth_year = 1949
    """
).present()
> strace -e hint=open,openat,learn -f python question.py 2>&1 | grep "dataset/.*.parquet"

(pid    37) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Boxpercent201306/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 3
(pid    37) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Boxpercent201306/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 3
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Boxpercent201306/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 4
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Boxpercent203487/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 5
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Boxpercent203487/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 3
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Clarkemouth/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 4
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Clarkemouth/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 5
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=DPOpercent20APpercent2020198/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 3
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=DPOpercent20APpercent2020198/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 4
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Eastpercent20Morgan/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 5
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Eastpercent20Morgan/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 3
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=FPOpercent20AApercent2006122/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 4
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=FPOpercent20AApercent2006122/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 5
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Newpercent20Michelleport/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 3
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Newpercent20Michelleport/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 4
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Northpercent20Danielchester/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 5
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Northpercent20Danielchester/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 3
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Portpercent20Chase/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 4
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Portpercent20Chase/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 5
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Richardmouth/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 3
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Richardmouth/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 4
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Robbinsshire/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 5
(pid    39) openat(AT_FDCWD, "dataset/birth_year=1949/metropolis=Robbinsshire/e1ad1666a2144fbc94892d4ac1234c64-0.parquet", O_RDONLY) = 3

Nur 23 Dateien werden von 100 ausgelesen.

Lesen einer Rohparkettdatei

Lassen Sie uns eine Rohparkettdatei ohne spezialisierte Bibliotheken dekodieren. Der Einfachheit halber wird der Datensatz ohne Komprimierung oder Codierung in eine einzelne Datei abgeladen.

# generator.py

# ...

pq.write_table(
    desk,
    "dataset.parquet",
    use_dictionary=False,
    compression="NONE",
    write_statistics=True,
    column_encoding=None,
)

Das erste, was Sie wissen sollten, ist, dass die Binärdatei von 4 Bytes umrahmt wird, deren ASCII -Darstellung „Par1“ ist. Die Datei ist beschädigt, wenn dies nicht der Fall ist.

# reader.py

with open("dataset.parquet", "rb") as file:
    parquet_data = file.learn()

assert parquet_data(:4) == b"PAR1", "Not a sound parquet file"
assert parquet_data(-4:) == b"PAR1", "File footer is corrupted"

Wie in der angegeben DokumentationDie Datei ist in zwei Teile unterteilt: die „Zeilengruppen“, die tatsächliche Daten enthalten, und die Fußzeile mit Metadaten (Schema unten).

Die Fußzeile

Die Größe der Fußzeile ist in den 4 Bytes vor dem Endmarker als unsignierte Ganzzahl angegeben, die im „Little Endian“ -Format geschrieben ist (angegeben „unpack Funktion).

# reader.py

import struct

# ...

footer_length = struct.unpack("<I", parquet_data(-8:-4))(0)
print(f"Footer dimension in bytes: {footer_length}")

footer_start = len(parquet_data) - footer_length - 8
footer_data = parquet_data(footer_start:-8)
Footer dimension in bytes: 1088

Die Fußzeileninformationen werden in einem Cross-Sprach-Serialisierungsformat genannt Apache -Sparsamkeit. Die Verwendung eines menschlich lesbaren, aber ausführlichen Codecs wie JSON und das dann in binäre Übersetzung wäre in Bezug auf die Speicherverwendung weniger effizient. Mit Sparsamkeit kann man Datenstrukturen wie folgt deklarieren:

struct Buyer {
	1: required string identify,
	2: non-obligatory i16 birthYear,
	3: non-obligatory checklist<string> pursuits
}

Auf der Grundlage dieser Deklaration kann Thrift Python -Code generieren, um Byte -Zeichenfolgen mit einer solchen Datenstruktur zu dekodieren (er generiert auch Code, um den Codierungsteil durchzuführen). Die Sparsamkeitsdatei, die alle in einer Parquetdatei implementierten Datenstrukturen enthält, kann heruntergeladen werden Hier. Nachdem wir die Sparsamkeits -Binärin installiert haben, rennen wir:

thrift -r --gen py parquet.thrift

Der generierte Python-Code wird im Ordner „Gen-Py“ platziert. Die Datenstruktur der Fußzeile wird durch die Filemetadata -Klasse dargestellt – eine Python -Klasse, die automatisch aus dem Thriftschema generiert wird. Unter Verwendung von Thrifts Python -Dienstprogrammen werden Binärdaten analysiert und in eine Instanz dieser Filemetadata -Klasse gefüllt.

# reader.py

import sys

# ...

# Add the generated lessons to the python path
sys.path.append("gen-py")
from parquet.ttypes import FileMetaData, PageHeader
from thrift.transport import TTransport
from thrift.protocol import TCompactProtocol

def read_thrift(information, thrift_instance):
    """
    Learn a Thrift object from a binary buffer.
    Returns the Thrift object and the variety of bytes learn.
    """
    transport = TTransport.TMemoryBuffer(information)
    protocol = TCompactProtocol.TCompactProtocol(transport)
    thrift_instance.learn(protocol)
    return thrift_instance, transport._buffer.inform()

# The variety of bytes learn is just not used for now
file_metadata_thrift, _ = read_thrift(footer_data, FileMetaData())

print(f"Variety of rows in the entire file: {file_metadata_thrift.num_rows}")
print(f"Variety of row teams: {len(file_metadata_thrift.row_groups)}")

Variety of rows in the entire file: 100
Variety of row teams: 1

Die Fußzeile enthält umfangreiche Informationen über die Struktur und den Inhalt der Datei. Zum Beispiel verfolgt es genau die Anzahl der Zeilen im generierten Datenrahmen. Diese Zeilen sind alle in einer einzigen „Zeilengruppe“ enthalten. Aber was ist eine „Zeilengruppe“?

Reihengruppen

Im Gegensatz zu rein säulenorientierten Formaten verwendet Parquet einen hybriden Ansatz. Vor dem Schreiben von Spaltenblöcken wird der Datenrahmen zunächst vertikal in Zeilengruppen unterteilt (die von uns generierte Parquetendatei ist zu klein, um in mehreren Zeilengruppen aufgeteilt zu werden).

Diese Hybridstruktur bietet mehrere Vorteile:

Parquet berechnet die Statistiken (z. B. min/max -Werte) für jede Spalte in jeder Zeilengruppe. Diese Statistiken sind für die Abfrageoptimierung von entscheidender Bedeutung, sodass Abfrage -Engines ganze Zeilengruppen überspringen können, die nicht mit Filterkriterien übereinstimmen. Zum Beispiel, wenn eine Abfrage nach filtert birth_year > 1955 Das maximale Geburtsjahr einer Zeilengruppe beträgt 1954, der Motor kann den gesamten Datenabschnitt effizient überspringen. Diese Optimierung wird als „Prädikat -Pushdown“ bezeichnet. Parquet speichert auch andere nützliche Statistiken wie unterschiedliche Wertzahlen und Nullzählungen.

# reader.py
# ...

first_row_group = file_metadata_thrift.row_groups(0)
birth_year_column = first_row_group.columns(4)

min_stat_bytes = birth_year_column.meta_data.statistics.min
max_stat_bytes = birth_year_column.meta_data.statistics.max

min_year = struct.unpack("<I", min_stat_bytes)(0)
max_year = struct.unpack("<I", max_stat_bytes)(0)

print(f"The beginning 12 months vary is between {min_year} and {max_year}")
The beginning 12 months vary is between 1949 and 1958
  • Zeilengruppen ermöglichen die parallele Verarbeitung von Daten (besonders wertvoll für Frameworks wie Apache Spark). Die Größe dieser Zeilengruppen kann basierend auf den verfügbaren Computerressourcen konfiguriert werden (mit dem mit dem row_group_size Eigenschaft in Funktion write_table Bei Verwendung von Pyarrow).
# generator.py

# ...

pq.write_table(
    desk,
    "dataset.parquet",
    row_group_size=100,
)

# /! Preserve the default worth of "row_group_size" for the subsequent elements
  • Auch wenn dies nicht das Hauptziel eines Säulenformats ist, behält die Hybridstruktur des Parquets bei der Rekonstruktion vollständiger Zeilen eine angemessene Leistung bei. Ohne Zeilengruppen erfordert das Wiederaufbau einer gesamten Zeile möglicherweise das Scannen der gesamten Spalte, die für große Dateien äußerst ineffizient wäre.

Datenseiten

Die kleinste Unterstruktur einer Parkettdatei ist die Seite. Es enthält eine Sequenz von Werten aus derselben Spalte und daher vom gleichen Typ. Die Auswahl der Seitengröße ist das Ergebnis eines Kompromisses:

  • Größere Seiten bedeuten weniger Metadaten zum Speichern und Lesen, was für Abfragen mit minimaler Filterung optimum ist.
  • Kleinere Seiten reduzieren die Menge an unnötigen Daten, die besser sind, wenn Abfragen auf kleine, verstreute Datenbereiche abzielen.

Lassen Sie uns nun den Inhalt der ersten Seite der Spalte dekodieren, die Adressen gewidmet sind, deren Ort im Fußzeile gefunden werden kann (angegeben durch die data_page_offset Attribut des Rechts ColumnMetaData). Jede Seite geht von einer Sparsamkeit voraus PageHeader Objekt mit Metadaten. Der Offset verweist tatsächlich auf eine Sparsamkeitsdarstellung der Seitenmetadaten, die der Seite selbst vorausgeht. Die Secondhand -Klasse heißt a PageHeader und kann auch in der gefunden werden gen-py Verzeichnis.

💡 Zwischen dem PageHeader und den tatsächlichen Werten, die in der Seite enthalten sind Dremel Format, das eine Codierung ermöglicht verschachtelte Datenstrukturen. Da unsere Daten ein regelmäßiges tabellarisches Format haben und die Werte nicht nullbar sind, werden diese Bytes beim Schreiben der Datei übersprungen (https://parquet.apache.org/docs/file-format/data-pages/).

# reader.py
# ...

address_column = first_row_group.columns(1)
column_start = address_column.meta_data.data_page_offset
column_end = column_start + address_column.meta_data.total_compressed_size
column_content = parquet_data(column_start:column_end)

page_thrift, page_header_size = read_thrift(column_content, PageHeader())
page_content = column_content(
    page_header_size : (page_header_size + page_thrift.compressed_page_size)
)
print(column_content(:100))
b'6x00x00x00481 Mata Squares Suite 260, Lake Rachelville, KY 874642x00x00x00671 Barker Crossing Suite 390, Mooreto'

Die generierten Werte erscheinen schließlich im Klartext und nicht codiert (wie beim Schreiben der Parkettdatei). Um das Säulenformat zu optimieren, wird jedoch empfohlen, einen der folgenden Codierungsalgorithmen zu verwenden: Wörterbuchcodierung, Auslauflänge -Codierung (RLE) oder Delta -Codierung (letztere werden für INT32- und INT64 -Typen reserviert), gefolgt von der Kompression mit GZIP oder SNAppy (verfügbare Codecs sind verfügbar Hier). Da codierte Seiten ähnliche Werte (alle Adressen, alle Dezimalzahlen usw.) enthalten, können Komprimierungsverhältnisse besonders vorteilhaft sein.

Wie in der dokumentiert SpezifikationWenn Charakterzeichenfolgen (byte_array) nicht codiert werden, wird jedem Wert seine Größe als 4-Byte-Ganzzahl vorausgeht. Dies kann in der vorherigen Ausgabe beobachtet werden:

Um alle Werte zu lesen (zum Beispiel die ersten 10), ist die Schleife ziemlich einfach:

idx = 0
for _ in vary(10):
    str_size = struct.unpack("<I", page_content(idx : (idx + 4)))(0)
    print(page_content((idx + 4) : (idx + 4 + str_size)).decode())
    idx += 4 + str_size
481 Mata Squares Suite 260, Lake Rachelville, KY 87464
671 Barker Crossing Suite 390, Mooretown, MI 21488
62459 Jordan Knoll Apt. 970, Emilyfort, DC 80068
948 Victor Sq. Apt. 753, Braybury, RI 67113
365 Edward Place Apt. 162, Calebborough, AL 13037
894 Reed Lock, New Davidmouth, NV 84612
24082 Allison Squares Suite 345, North Sharonberg, WY 97642
00266 Johnson Drives, South Lori, MI 98513
15255 Kelly Plains, Richardmouth, GA 33438
260 Thomas Glens, Port Gabriela, OH 96758

Und da haben wir es! Wir haben auf sehr einfache Weise erfolgreich nachgebaut, wie eine spezialisierte Bibliothek eine Parquetendatei lesen würde. Durch das Verständnis der Bausteine, einschließlich Header, Fußzeilen, Reihengruppen und Datenseiten, können wir besser schätzen, wie Funktionen wie Prädikat Pushdown und Partition-Beschneidung so beeindruckende Leistungsvorteile in datenintensiven Umgebungen bieten. Ich bin überzeugt zu wissen, wie Parquet unter der Haube arbeitet, hilft, bessere Entscheidungen über Speicherstrategien, Komprimierungsentscheidungen und Leistungsoptimierung zu treffen.

Alle in diesem Artikel verwendeten Code finden Sie in meinem Github -Repository unter https://github.com/kili-mandjaro/anatomy-parquetwo Sie weitere Beispiele untersuchen und mit unterschiedlichen Konfigurationen der Parquetdatei experimentieren können.

Unabhängig davon, ob Sie Datenpipelines erstellen, die Abfrageleistung optimieren oder einfach nur neugierig auf Datenspeicherformate sind, hoffe ich Daten Engineering Reise.

Alle Bilder stammen vom Autor.

[ad_2]

]]>
https://chatgpz.de/artificial-intelligence/anatomie-einer-parkettdatei/feed/ 0 7850
Die Anatomie eines autonomen Agenten | von Eric Broda | Dez. 2024 https://chatgpz.de/artificial-intelligence/die-anatomie-eines-autonomen-agenten-von-eric-broda-dez-2024/ https://chatgpz.de/artificial-intelligence/die-anatomie-eines-autonomen-agenten-von-eric-broda-dez-2024/#respond Wed, 18 Dec 2024 03:12:16 +0000 http://chatgpz.de/artificial-intelligence/die-anatomie-eines-autonomen-agenten-von-eric-broda-dez-2024/ [ad_1]

Eine Blaupause für autonome Agenten in einem Agentic Mesh-Ökosystem

Anatomie eines autonomen Agenten

Die jüngsten massiven Investitionen von Technologiegiganten sind quick eine Garantie dafür, dass bald ein Ökosystem autonomer Agenten auf uns zukommen wird. Aber was ist ein „autonomer Agent“?

Sebastian ThielkePlatform Economics Lead bei AWS, beschreibt es so (paraphrasierend): „Ein autonomer Agent reagiert auf Umweltreize, verfolgt ein Ziel proaktiv, verfügt über soziale Interaktionsfähigkeiten und kann kontinuierlich lernen und sich verbessern.“ Wikipedia bietet ein ähnliches Angebot Definition: „Autonome Agenten sind Computersysteme, die in einer komplexen dynamischen Umgebung leben, diese Umgebung wahrnehmen und autonom handeln und auf diese Weise eine Reihe von Zielen oder Aufgaben realisieren, für die sie entwickelt wurden.“ Und in einem früheren ArtikelIch habe die folgende Definition vorgeschlagen, die meiner Meinung nach beides erfasst: Autonome Agenten nutzen agentische KI (ausgefeiltes Denken und iterative Planung), um Aufgaben unabhängig zu planen und auszuführen.

Nachdem dies geklärt ist, möchte ich zum Hauptschwerpunkt dieses Artikels kommen: Wie sieht eine Architektur eines autonomen Agenten (im Folgenden als „Agent“ bezeichnet) aus und was sind ihre Hauptkomponenten? Welche Fähigkeiten müssen vorhanden sein, um einen „intelligenten“ Agenten zu erstellen, der Aufgaben planen und ausführen kann? Und da kein Agent für sich allein steht, sondern in einem Ökosystem von… arbeitet

[ad_2]

]]>
https://chatgpz.de/artificial-intelligence/die-anatomie-eines-autonomen-agenten-von-eric-broda-dez-2024/feed/ 0 5931
Die vollständige Anatomie der Umgebungs-KI im Gesundheitswesen: Ein 5-Minuten-Leitfaden https://chatgpz.de/artificial-intelligence/die-vollstaendige-anatomie-der-umgebungs-ki-im-gesundheitswesen-ein-5-minuten-leitfaden/ https://chatgpz.de/artificial-intelligence/die-vollstaendige-anatomie-der-umgebungs-ki-im-gesundheitswesen-ein-5-minuten-leitfaden/#respond Wed, 30 Oct 2024 19:34:52 +0000 http://chatgpz.de/artificial-intelligence/die-vollstaendige-anatomie-der-umgebungs-ki-im-gesundheitswesen-ein-5-minuten-leitfaden/ [ad_1]

Wie wir in der jüngsten Vergangenheit mit dem Aufkommen von Gen-KI- und GPT-Modellen beobachtet haben, verändert das kontextuelle Verständnis die Artwork und Weise, wie KI-Modelle in das menschliche Leben integriert werden. Da die durch Umgebungs-KI ausgelösten Reaktionen und Aktionen autonom, differenziert und maßgeschneidert sind, sind ihre Auswirkungen auf das Gesundheitswesen revolutionär.

Umgebungs-KI im Kontext des Gesundheitswesens verstehen

Wenn wir über die Zukunft des Gesundheitswesens sprechen, sprechen wir oft von konkreten Durchbrüchen oder Geräteentdeckungen. Damit solch große Revolutionen stattfinden können, sind jedoch kleinere Erfolge unvermeidlich.

Ambient AI ist ein kleiner, aber bedeutender Schritt in der Entwicklung der KI im Gesundheitswesen, der Möglichkeiten eröffnen wird, von denen wir nie wussten, dass sie existieren. Um Ihnen eine bessere Vorstellung zu geben, finden Sie hier die verschiedenen Möglichkeiten, wie Umgebungs-KI Konventionen im Gesundheitswesen neu schreiben wird.

Minimieren oder verkürzen Sie den Zeitaufwand für die klinische Dokumentation

Klinische Dokumentation Es ist keine Überraschung, dass Krankenhausmitarbeiter und Stakeholder einen Großteil ihrer Zeit mit der Durchführung klinischer Dokumentationsaufgaben verbringen. Da es sich um einen manuellen Prozess handelt, besteht auch die Möglichkeit von Fehlern. Zwar gibt es Modelle für maschinelles Lernen und KI im Gesundheitswesen Methoden zur Automatisierung des Prozesses sind nicht in Echtzeit verfügbar.

Hier kommt Ambient AI mit seiner sofortigen Generierung klinischer Dokumente ins Spiel durch:

  • Beobachtung der Patienteninteraktion und -geschichte entweder als Teil der App oder eines externen Geräts
  • Kuratierung verschiedener unterstützender Dokumente wie medizinischer Bilddateien von Patienten aus ihren jeweiligen EHRs
  • Stellen Sie alle anderen unstrukturierten Daten zusammen, die Diagnose, Behandlung oder Prognose und mehr unterstützen würden

Fernüberwachung von Patienten

Fernüberwachung von Patienten Die Wearables von heute leisten bereits hervorragende Arbeit bei der stillen Überwachung der Gesundheit und des Lebensstils ihrer Träger. Künftig wird Umgebungs-KI jedoch in der Lage sein:

  • Verfolgen Sie die Symptome des Patienten kontinuierlich und prüfen Sie, ob er unter Kontrolle ist
  • Hilfe bei der Früherkennung von Anomalien, die zu lebensbedrohlichen Erkrankungen führen können.
  • Fernüberwachung durch Krankenhäuser, um Interessenvertretern im Gesundheitswesen dabei zu helfen, die Genesung von Patienten zu verstehen
  • Erinnern Sie Patienten proaktiv an ihre bevorstehenden Termine und vereinbaren Sie sogar einen Taxiservice, wenn ein chirurgischer Eingriff erforderlich ist und vieles mehr

Formulierung personalisierter Behandlungspläne

Erstellung individueller Behandlungspläne Die Leistungserbringung im Gesundheitswesen ist personalisiert, bestimmte Aspekte wie die Medikation sind jedoch immer noch allgemein gehalten. Mit Umgebungs-KI können Interessenvertreter im Gesundheitswesen einen tieferen Einblick in die genetischen Informationen, die Krankengeschichte, Allergien, Lebensstilfaktoren und mehr eines Patienten erhalten, um umfassende und maßgeschneiderte Medikamente und Methoden zur Patientenversorgung vorzuschlagen.

Da solche individualistischen Variationen berücksichtigt werden, ist die Gesundheitsversorgung auf diese Weise wirkungsvoller und minimiert das Risiko von Nebenwirkungen und Gegnern.

Der Weg nach vorne

Bei Ambient AI geht es darum, die Technologie so unsichtbar und menschlich wie möglich zu machen. Die Weiterentwicklung dieses Konzepts erfordert nicht nur Backend-Funktionalitäten wie KI-Coaching und Datenanmerkung sondern ein tieferes Verständnis der humanen Feinheiten im Gesundheitsökosystem.

[ad_2]

]]>
https://chatgpz.de/artificial-intelligence/die-vollstaendige-anatomie-der-umgebungs-ki-im-gesundheitswesen-ein-5-minuten-leitfaden/feed/ 0 4877
Anatomie von Home windows-Funktionen. Theorie und Praxis einer… | von João Pedro | Juni 2024 https://chatgpz.de/machine-learning/anatomie-von-home-windows-funktionen-theorie-und-praxis-einer-von-joao-pedro-juni-2024/ https://chatgpz.de/machine-learning/anatomie-von-home-windows-funktionen-theorie-und-praxis-einer-von-joao-pedro-juni-2024/#respond Tue, 11 Jun 2024 11:42:11 +0000 http://chatgpz.de/machine-learning/anatomie-von-windows-funktionen-theorie-und-praxis-einer-von-joao-pedro-juni-2024/ [ad_1]

Theorie und Praxis einer unterschätzten SQL-Operation

Foto von Marcus Woodbridge An Unsplash

Der IT-Bereich ist für seine ständigen Veränderungen bekannt. Jeden Tag werden neue Instruments, neue Frameworks, neue Cloud-Anbieter und neue LLMs erstellt. Doch selbst in dieser geschäftigen Welt scheinen einige Prinzipien, Paradigmen und Instruments die Standing Quo von „nichts ist für die Ewigkeit“. Und im Datenbereich gibt es dafür kein so eindrucksvolles Beispiel wie die SQL-Sprache.

Seit seiner Entstehung in den 80er Jahren hat es das Zeitalter der Information Warehouses überstanden, sich in Hadoop/Information-Lake/Large Information als Hive materialisiert und ist heute noch als eine der Spark-APIs lebendig. Die Welt hat sich stark verändert, aber SQL ist nicht nur lebendig geblieben, sondern auch sehr wichtig und präsent.

Aber SQL ist wie Schach: Die Grundregeln sind leicht zu verstehen, aber schwer zu meistern! Es ist eine Sprache mit vielen Möglichkeiten, vielen Wegen, um dasselbe Drawback zu lösen, vielen Funktionen und Schlüsselwörtern und leider vielen unterschätzten Funktionalitäten, die uns, wenn wir sie besser kennen würden, beim Erstellen von Abfragen sehr helfen könnten.

Aus diesem Grund möchte ich in diesem Beitrag über eine der weniger bekannten SQL-Funktionen sprechen, die ich beim Erstellen meiner täglichen Abfragen äußerst nützlich fand: Fensterfunktionen.

Die traditionellen und bekanntesten SGBDs (PostgreSQL, MySQL und Oracle) basieren auf Konzepten der relationalen Algebra. Darin werden die Zeilen Tupel genannt und die Tabellen sind Relationen. Eine Relation ist eine Menge (im mathematischen Sinne) von Tupeln, d. h. es gibt keine Ordnung oder Verbindung zwischen ihnen. Aus diesem Grund gibt es keine Standardordnung der Zeilen in einer Tabelle, und die Berechnung, die an einer Zeile durchgeführt wird, hat keinen Einfluss auf die Ergebnisse einer anderen Zeile und wird auch nicht von diesen beeinflusst. Selbst Klauseln wie ORDER BY ordnen nur Tabellen, und es ist nicht möglich, Berechnungen in einer Zeile basierend auf den Werten anderer Zeilen durchzuführen.

Einfach ausgedrückt beheben Fensterfunktionen dieses Drawback, indem sie die SQL-Funktionalitäten erweitern und es uns ermöglichen, Berechnungen in einer Zeile basierend auf den Werten anderer Zeilen durchzuführen.

1-Aggregieren ohne Aggregation

Das trivialste Beispiel zum Verständnis von Home windows-Funktionen ist die Fähigkeit, ‚aggregieren ohne aggregieren‚.

Wenn wir eine Aggregation mit dem herkömmlichen GROUP BY-Verfahren durchführen, wird die gesamte Tabelle in eine zweite Tabelle zusammengefasst, in der jede Zeile ein Ingredient einer Gruppe darstellt. Mit Home windows Features ist es möglich, statt der Zusammenfassung der Zeilen eine neue Spalte in derselben Tabelle zu erstellen, die die Aggregationsergebnisse enthält.

Wenn Sie beispielsweise alle Ausgaben in Ihrer Ausgabentabelle addieren müssen, gehen Sie üblicherweise wie folgt vor:

SELECT SUM(worth) AS complete FROM myTable

Mit Home windows-Funktionen würden Sie etwa Folgendes erstellen:

SELECT *, SUM(worth) OVER() FROM myTable
-- Word that the window perform is outlined at column-level
-- within the question

Das folgende Bild zeigt die Ergebnisse:

Bild 1. Traditionelles „Gruppieren nach“ vs. Home windows-Funktionen.

Anstatt eine neue Tabelle zu erstellen, wird der Wert der Aggregation in einer neuen Spalte zurückgegeben. Beachten Sie, dass der Wert derselbe ist, die Tabelle jedoch nicht ‚zusammengefasst‚, die ursprünglichen Zeilen wurden beibehalten — wir berechneten lediglich eine Aggregation ohne Aggregation Der Tisch 😉

Die OVER-Klausel ist ein Hinweis darauf, dass wir eine Fensterfunktion erstellen. Diese Klausel definiert, über welche Zeilen die Berechnung durchgeführt wird. Im obigen Code ist sie leer, daher wird SUM() über alle Zeilen berechnet.

Dies ist nützlich, wenn wir Berechnungen basierend auf Summen (oder Durchschnitts-, Mindest- und Höchstwerten) von Spalten durchführen müssen. Beispielsweise um zu berechnen, wie viel jede Ausgabe in Prozent zum Gesamtwert beiträgt.

In realen Fällen möchten wir vielleicht auch die Particulars nach Kategorien, wie im Beispiel in Bild 2, wo wir die Unternehmensausgaben nach Abteilungen haben. Auch hier können wir die Gesamtausgaben jeder Abteilung mit einem einfachen GROUP BY ermitteln:

SELECT depto, sum(worth) FROM myTable GROUP BY depto

Oder geben Sie eine PARTITION-Logik in der Fensterfunktion an:

SELECT *, SUM(worth) OVER(PARTITION BY depto) FROM myTable

Sehen Sie das Ergebnis:

Bild 2. Traditionelles „Gruppieren nach“ vs. Home windows-Funktionen II.

Dieses Beispiel hilft zu verstehen, warum die Operation als „Fenster“-Funktion bezeichnet wird – die OVER-Klausel definiert eine Reihe von Zeilen, über die die entsprechende Funktion ausgeführt wird, ein „Fenster“ in der Tabelle.

Im obigen Fall wird die Funktion SUM() in den von der Spalte „Depto“ (RH und SALES) erstellten Partitionen ausgeführt – sie summiert alle Werte in der Spalte „Wert“ für jedes Ingredient in der Spalte „Depto“ isoliert. Die Gruppe, zu der die Zeile gehört (RH oder SALES), bestimmt den Wert in der Spalte „Gesamt“.

2 — Zeit- und Bestellbewusstsein

Manchmal müssen wir den Wert einer Spalte in einer Zeile auf Grundlage der Werte anderer Zeilen berechnen. Ein klassisches Beispiel ist das jährliche Wachstum des BIP eines Landes, das anhand des aktuellen und des vorherigen Werts berechnet wird.

Berechnungen dieser Artwork, bei denen wir den Wert des vergangenen Jahres, die Differenz zwischen der aktuellen und der nächsten Zeile, den ersten Wert einer Reihe usw. benötigen, sind ein Beweis für die Leistungsfähigkeit der Home windows-Funktion. Tatsächlich weiß ich nicht, ob dieses Verhalten mit Commonplace-SQL-Befehlen erreicht werden könnte! Wahrscheinlich wäre es möglich, aber es wäre eine sehr komplexe Abfrage …

Aber Home windows-Funktionen machen es unkompliziert, siehe das Bild unten (Tabelle mit der Aufzeichnung der Körpergröße einiger Kinder):

Bild 3. Beispiel für eine analytische Funktion.
SELECT 
12 months, peak,
LAG(peak) OVER (ORDER BY 12 months) AS height_last_year
FROM myTable

Die Funktion LAG( ‚column‘ ) ist dafür verantwortlich, den Wert von ‚column‘ in der vorherigen Zeile zu referenzieren. Sie können sich das als eine Abfolge von Schritten vorstellen: In der zweiten Zeile berücksichtigen Sie den Wert der ersten; in der dritten den Wert der zweiten; und so weiter… Die erste Zeile zählt nicht (daher die NULL), da es keinen Vorgänger hat.

Natürlich ist ein Ordnungskriterium erforderlich, um zu definieren, was die „vorherige Zeile“ ist. Und das ist ein weiteres wichtiges Konzept in Home windows-Funktionen: Analysefunktionen.

Im Gegensatz zu herkömmlichen SQL-Funktionen berücksichtigen analytische Funktionen (wie LAG), dass eine Reihenfolge in den Zeilen vorhanden ist – und diese Reihenfolge wird durch die Klausel ORDER BY innerhalb von OVER() definiert, d. h. das Konzept der ersten, zweiten, dritten Zeile usw. wird innerhalb des Schlüsselworts OVER definiert. Das Hauptmerkmal dieser Funktionen ist die Möglichkeit, auf andere Zeilen relativ zur aktuellen Zeile zu verweisen: LAG verweist auf die vorherige Zeile, LEAD verweist auf die nächsten Zeilen, FIRST verweist auf die erste Zeile in der Partition usw.

Das Schöne an LAG und LEAD ist, dass beide ein zweites Argument akzeptieren, den Offset, der angibt, wie viele Zeilen nach vorne (für LEAD) oder hinten (für LAG) geschaut werden soll.

SELECT 
LAG(peak, 2) OVER (ORDER BY 12 months) as height_two_years_ago,
LAG(peak, 3) OVER (ORDER BY 12 months) as height_three_years_ago,
LEAD(peak) OVER (ORDER BY 12 months) as height_next_year
FROM ...

Und auch Berechnungen mit diesen Funktionen sind problemlos möglich:

SELECT 
100*peak/(LAG(peak) OVER (ORDER BY 12 months))
AS "annual_growth_%"
FROM ...

3 – Zeitbewusstsein und Aggregation

Zeit und Raum sind nur eins — sagte einmal Einsteinm, oder so ähnlich, ich weiß nicht ¯_(ツ)_/¯

Da wir nun wissen, wie man partitioniert und ordnet, können wir beides zusammen verwenden! Um auf das vorherige Beispiel zurückzukommen: Nehmen wir an, es gibt mehrere Kinder an diesem Tisch und wir müssen die Wachstumsrate jedes einzelnen berechnen. Das ist ganz einfach: Kombinieren Sie einfach Ordnen und Partitionieren! Ordnen wir nach Jahr und partitionieren wir nach dem Namen des Kindes.

SELECT 1-height/LAG(peak) OVER (ORDER BY 12 months PARTITION BY identify) ...
Bild 4. ORDER BY + PARTITION BY

Die obige Abfrage führt Folgendes aus: Sie partitioniert die Tabelle nach untergeordneten Elementen, ordnet in jeder Partition die Werte nach Jahr und dividiert den aktuellen Höhenwert des Jahres durch den vorherigen Wert (und subtrahiert das Ergebnis von eins).

Wir nähern uns dem vollständigen Konzept des „Fensters“! Es handelt sich um einen Tabellenausschnitt, eine Reihe von Zeilen, die nach den in PARTITION BY definierten Spalten gruppiert und nach den Feldern in ORDER BY sortiert sind. Alle Berechnungen werden nur unter Berücksichtigung der Zeilen in derselben Gruppe (Partition) und einer bestimmten Reihenfolge durchgeführt.

4-Rangliste und Place

Home windows-Funktionen können in drei Kategorien unterteilt werden, von denen wir zwei bereits besprochen haben: Aggregationsfunktionen (COUNT, SUM, AVG, MAX, …) und Analysefunktionen (LAG, LEAD, FIRST_VALUE, LAST_VALUE, …).

Die dritte Gruppe ist die einfachste – Rangfolgefunktionen, deren größter Exponent die Funktion row_number() ist, die eine Ganzzahl zurückgibt, die die Place einer Zeile in der Gruppe darstellt (basierend auf der definierten Reihenfolge).

SELECT row_number() OVER(ORDER BY rating)

Rating-Funktionen geben, wie der Identify schon sagt, Werte basierend auf der Place der Zeile in der Gruppe zurück, die durch die Sortierkriterien definiert wird. ROW_NUMBER, RANK und NTILE sind einige der am häufigsten verwendeten.

Bild 5. Beispiel für eine Rating-Funktion

Im Bild oben wird eine Zeilennummer basierend auf der Punktzahl jedes Spielers erstellt

… und ja, es begeht die schreckliche Programmiersünde, bei 1 zu beginnen.

5-Fenstergröße

Alle bisher vorgestellten Funktionen berücksichtigen bei der Berechnung der Ergebnisse ALLE Zeilen in der Partition/Gruppe. Beispielsweise berücksichtigt die im ersten Beispiel beschriebene Funktion SUM() alle Zeilen der Abteilung, um die Gesamtsumme zu berechnen.

Es ist jedoch möglich, eine kleinere Fenstergröße anzugeben, d. h. wie viele Zeilen vor und nach der aktuellen Zeile in die Berechnungen einbezogen werden sollen. Dies ist eine hilfreiche Funktion zum Berechnen von gleitenden Durchschnitten/rollierenden Fenstern.

Betrachten wir das folgende Beispiel mit einer Tabelle, die die tägliche Anzahl der Fälle einer bestimmten Krankheit enthält, wobei wir die durchschnittliche Anzahl der Fälle unter Berücksichtigung des aktuellen Tages und der beiden vorherigen berechnen müssen. Beachten Sie, dass dieses Drawback mit der zuvor gezeigten LAG-Funktion gelöst werden kann:

SELECT
( n_cases + LAG(n_cases, 1) + LAG(n_cases, 2) )/3
OVER (ORDER BY date_reference)

Aber wir können das gleiche Ergebnis eleganter erreichen, indem wir das Konzept von Rahmen:

SELECT
AVG(n_cases)
OVER (
ORDER BY date_reference
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
)

Der obige Rahmen gibt an, dass wir den Durchschnitt nur für die beiden vorherigen (VORHERGEHENDEN) Zeilen und die aktuelle Zeile berechnen müssen. Wenn wir die vorherige, die aktuelle Zeile und die folgende Zeile berücksichtigen möchten, können wir den Rahmen ändern:

AVG(n_cases)
OVER (
ORDER BY date_reference
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
)

Und das ist alles, was ein Body ist – eine Möglichkeit, die Reichweite einer Funktion auf eine bestimmte Grenze zu beschränken. Standardmäßig (in den meisten Fällen) berücksichtigen Home windows-Funktionen den folgenden Body:

ROWS BETWEEN UNBOUDED PRECEDING AND CURRENT ROW
-- ALL THE PREVIOUS ROWS + THE CURRENT ROW
Bild 6. Erkunden der Fenstergrößendefinition

[ad_2]

]]>
https://chatgpz.de/machine-learning/anatomie-von-home-windows-funktionen-theorie-und-praxis-einer-von-joao-pedro-juni-2024/feed/ 0 1338